183 comments

[ 222 ms ] story [ 4109 ms ] thread
I really like this. I hope some younger people with more time on their hands push this farther.
I'm not sure I follow what this is. Where would I use Nock and Hoon?
To build your startup? No.

To have fun? Why not.

I should rephrase my question: on what technology platforms would one use Nock and Hoon? Embedded systems? Anything (due to "portability")?
You are still missing the point. They wrote it because it looked like fun. It's not targeting a business problem as such it's more like it's scratching the "This looks like fun" itch.

Could it maybe be used for something sure. But that doesn't have to be the motivation of the authors.

In the end it compiles down to C, so supposedly any system. Though the virtual machine is bound to have side effects (I/O) so you are bound to whatever platforms they have impleme ted those for, which might as well be Windows XP.

Tldr; this question warrants an answer from someone who knows.

Here's one way to think about it.

You have a Facebook profile, right? That's essentially a special-purpose cloud computer - a cloud information appliance. But, wouldn't it be cool to have an actual personal computer in the sky? Where "Facebook" or whatever would just be... a program on that computer?

You can get a Linux box in the sky, easy. But... that's 15 million lines of code you're wrangling. On a network which makes Helm's Deep look like Mayberry.

So, if it's your home in the cloud, it's not a cute little bungalow in the cloud. It's a giant castle in the cloud guarded by experienced professional elf ninja warriors. And ya know, even experienced professional elf ninja warriors, when they're off duty, like to let their hair down and not be thinking about orcs every other minute.

So if you want the bungalow in the cloud, you need basically a new programming/execution environment, and oh also a new network. So basically a new everything. So, a person could despair, or he could go build a new everything...

As others have pointed out, this is art.

You don't look at art, and ask "Why did you do this??". You simply enjoy it. The artist did it, to do it, and nothing further.

If you can not see this that way, then I am truly sorry.

If it is truly art then it doesn't make much sense why he is trying so damn hard to make it practical.
I see beauty in many things. I'm not yet at the level of programming where I see beauty in syntax -- maybe one day though!
I'm pretty sure this is a giant joke ? Or nothing is implemented yet (and still, kind of jokish especially in description)?
Is this comment a joke?

I haven't tried compiling it, but even if large parts of the documentation say "this isn't finished yet" there are code and compilation instructions for Linux and OSX. If it's a joke then it's a joke that two contributors seem to have taken very seriously for a number of months now.

EDIT: Not like, say, Flynn... jab jab

I meant in a similar vein to say, esoteric languages or subsests like jsfuck.com.

I see this is considered more art, and I would agree with that.

It appears as if it is a large art + learning experience, and I appreciated that after I watched the movie.

Not a lot of _novel_ ideas per se, but an interesting mixture of things.

This felt like an epilog to 2001 a space odyssey. Alien world.
The video shows an utterly fascinating mixture of Lisp, Erlang, Plan 9, and Bitcoin. The only missing ingredient is a proper static type system!
I was with you til you introduced the Hoon syntax. Why ruin a great concept with a shit language? WHAT IS WRONG WITH LANGUAGE DESIGNERS?! Just come up with a sane language with a sane syntax on a great platform. This is apparently asking a lot. It's not fucking rocket science.
I agree entirely! This is so much better than the typical "middlebrow dismissive" that I upvoted it...

And actually, if you don't like Hoon you can build your own language on this platform. So long as it compiles to Nock. You'll probably have to write your first compiler in Hoon, but we do have pretty decent combinator parsers. If you can swallow the syntax...

I like that you upvote your critics. That amuses me greatly. I had not viewed the video before I made my first comment but after watching the video I'm impressed with your implementation and solid practical concepts, but I still abhor your Hoon syntax. I haven't looked into Nock yet but I have a feeling I might knock its syntax as well, pun intended.
A better link would be the front page: http://www.urbit.org/

I guess on the Internets, you never release anything - it's released for you. Please be warned, (a) the doc is incomplete, (b) if you create an Urbit ship you'll eventually have to destroy it, as we don't have continuity yet.

Lame qn but does the name Albert Jay Nock have anything to do with 'Nock'?
http://en.wikipedia.org/wiki/Albert_Jay_Nock http://en.wikipedia.org/wiki/Tea_at_the_Palaz_of_Hoon

Four-letter names that haven't been overexposed are hard to find. But four letters fits in a 32-bit direct atom, so the attraction is pretty irresistible.

Nice! Thought so.
> But four letters fits in a 32-bit direct atom, so the attraction is pretty irresistible.

Reminds me of how ITS limited filenames to six letters per component, because they used six bits per character and six times six is thirty-six bits, or one machine word.

To this day, HAKMEM ('Hacks Memo') is still called that:

http://en.wikipedia.org/wiki/HAKMEM

Watching the video blew my brains out the back of my head. Figuratively of course. Thanks for not letting me get anything productive done for the rest of the day.
So here I am, in a submarine, learning a foreign language. What an afternoon.
Hoon is a high-level language which defines itself in Nock. Its self-compiling kernel, 7000 lines of code, specifies Hoon unambiguously; there is no Hoon spec. Hoon can be classified as a pure, strict higher-order static type-inferred functional language, with co/contra/bivariance and genericity. However, Hoon does not use lambda calculus, unification, or other constructs from “PL theory.” Hoon also excels at handling and validating untyped data, a common task on teh Internets. Its syntax is entirely novel and initially quite frightening.

Crank detected. Homing in for the kill.

Have fun!

I recommend you start with the Nock tutorial:

http://www.urbit.org/2013/08/22/Chapter-2-nock.html

The build instructions in this file are out of date, use the ones from the Arvo chapter. Also, probably the best short overview is the header comment in the Hoon compiler:

https://github.com/urbit/urbit/blob/master/urb/zod/arvo/hoon...

Also don't miss the video: https://vimeo.com/75312418

Oh wow.

After watching the video I'm legitimately interested in more than the language. You've got some cool ideas going on there. I'll be emailing for a 32-bit destroyer in a second.

So rather than having a lengthy standard it has lots of small non-standardized and brittle performance optimizations?

I remain skeptical over whether this tradeoff is worth it.

It's fairly easy to make them non-brittle, because it's very easy to rig a testing framework to run both the hand-optimized "jet" and the pure code, and compare them.

Standardizing performance is a subtler and more interesting point. It's a fairly safe bet that anything in the kernel that needs to be is jet-propelled. Above that layer, who knows? Good old normative text may handle it.

But in general, the feeling should be like the difference between hardware GL and software GL. The developer doesn't see it and the user sees it only as fast versus slow.

What about when the pure code is too slow to run? Or when the pure code is wrong but the jet is right - so that the nook spec is now not sufficient to determine semantics.

Let me bury that criticism though by saying that this is the most beautiful piece of work I have seen in some time. If more people were willing to be a little crazy we might not be quite as tangled in spaghetti.

Thanks, and you're right about both problems.

One, it takes a good bit of work to boot Arvo beyond a merely correct nock interpreter. The Hoon type system, for instance, is enormously painful if not jet-propelled.

Two, the kind of bug you're describing is in fact the nastiest class of bug. The best way to get around it is to always make sure you write the pure code first. But this isn't possible in a variety of circumstances - and it sure wasn't possible when making Hoon first compile itself. So, as inevitably in the real world, there is no substitute for not screwing up.

Because Nock is so simple (just a few substitution rules) I wonder if it'd be reasonable to formalize it in a theorem prover like Coq, or Agda to ensure correctness.
That's not entirely different from what a simple JIT does (or the unoptimised stage of a JIT without an interpreter).
I think it's a fascinating tradeoff. A typical approach with JIT-compilation is to write relatively inefficient code and hope that the JIT compiler picks up on it and optimizes it for you. Their approach seems to instead be to say "if you generate particular sequences of instructions, we'll detect those and instead execute a more efficient version, every time".

IMO this is a really cool idea because the performance optimizations are quite a bit less brittle than the ones you get with a JIT-compiled virtual machine.

This is what about 90% of the libc libraries out there do as well. Also tracing jits also do the same thing they see a trace that has a known optimization and it is performed.
"if you generate particular sequences of instructions, we'll detect those and instead execute a more efficient version, every time"

This is what JITs do. At least the good ones.

> A typical approach with JIT-compilation is to write relatively inefficient code and hope that the JIT compiler picks up on it and optimizes it for you. Their approach seems to instead be to say "if you generate particular sequences of instructions, we'll detect those and instead execute a more efficient version, every time".

I don't see the "instead" there. Those seem to be two ways of saying the same thing.

The difference is one of universality.

Let's say that my VM of choice has a tracing JIT, and it will attempt to optimize traces up to 1,000 instructions long. Let's further say that in the current version of my code, the body of my hot loop is 980 instructions long. Then in a new version I add another few operations which push it up to 1,010 instructions. Suddenly the JIT stops trying to optimize that portion of my code and performance tanks.

Meanwhile some other guy wrote his code using a VM which used this sort of "Jets" approach. It's probably not as fast or as versatile overall, but when he adds another few dozen instructions to a hot loop he can do so secure in the knowledge that all the preexisting code will continue to execute just like it did before.

(comment deleted)
This is really, really neat.

I really like the concepts in Avro and Urbit. Particularly interesting for me is the checkpoint/replay, distributed version control, and neighbours.

This is a really cool experiment!

You say addition is O(n^2), but I think you can write an O(n) addition with only increment, recursion, and equality testing.

In Python syntax:

  def add(a, b):
    return add_r(a, b, 0)

  def add_r(a, b, c):
    if b == c: 
      return a
    else:
      return add_r(a, b, c+1) +1
Yeah, it's true, the one in our kernel is O(n^2) though. Why? Because we're lame. But it hardly matters, as you'll never get anywhere with either O(n) or O(n^2) addition...
(comment deleted)
It's python, so it can't handle it either way, but by moving the final "+1" into the function call, it becomes tail-recursive.

  return add_r(a+1, b, c+1)
This is art.

"There is never a reason to program in Nock. Except to learn Nock." Classic

For a project ostensibly inspired by K&R C, the copy on this site is amazingly opaque and full of its own rhetoric. Recommendation: delete all the linguistic posturing and get down to the hard work of casting light on your ideas. Let that speak for itself.

By way of example, the K&R C book had a beautiful clarity and ability to fluidly move between the realms of reference, spec, and tutorial. If you're going to hold K&R C up as a model, you'd do well to mimic its documentation philosophy.

It seems like Urbit is art for art's sake. The fact that it executes is a side benefit.

(Oops, fyolnish beat me to it.)

That's an excellent criticism. Of course the problem is exacerbated by the HN link pointing to the philosophy doc. The greatest philosophy is to have no philosophy at all, but perhaps we're not quite there yet.

Actually the K&R equivalent for Hoon doesn't exist yet, and when it does it will be the first thing to read. Since it doesn't, the Arvo tutorial is the first thing to read:

http://www.urbit.org/2013/08/22/Chapter-1-arvo.html

But this itself is incomplete. Watch the video first:

http://www.urbit.org

Then build Arvo and use the sekrit code it generates to, basically, subscribe to our newsletter.

It's just a bad idea to document anything before it works completely, because you end up with doc that validates this criticism. The right way to build a language is to build it, use it, get comfortable with it, actually master it and become an expert of sorts... then document it. Sadly, not too many of us can live up to this ideal.

I for one love the whimsy. We need more LearnYouaThings and Shoes and runtimes that spit out lovecraftian quotes...
I really enjoyed reading this + a some of the pages.

Very mindbending, got up to watching the video.

Am thinking it looks like it could be quite fast, I guess it would make sense to implement something like ContextFree in it as a start.

I couldn't agree more. I don't want to know about how awesome the author is or how he's cunningly outsmarted everybody else. I'd like to see his ideas put forward without trashing other people's and with some theoretical context rather than just denunciations of PL theory.

Too much hot air.

I thought the style was a refreshing departure from the usual tone of expository technical documents. I actually enjoyed reading it, even though I disagreed with many of the assertions that were made.
Personally, I was reminded of the schizophrenic guy on HN who built his own OS.
I dig the Borges references riddled about.
From pedestal to pinnacle, all things are quantum, not classical. The metaphor that better avoids scaling obsolescence for your project is perhaps Bohmian, rather than Maxwellian.
(comment deleted)
With all that jargon I was expecting a set up for a punch line at the end. Don't nock it so hoon, it's not done jet. Ha!
Sigh, HN really is turning into - never mind. :-)
I love the project concept. A toy functional OS would be an admirable counterpart to e.g. MINIX. That said, I have one minor quibble:

A programming language is called a language for a reason - it should activate the human linguistic lobes.

Another programmer said this, a long time ago, and that's how we ended up with Perl. Please don't seek to emulate Larry Wall. Perl is great for quick automation, but anything complicated built with Perl quickly converges to unintelligible line noise (barring the exercise of zen-like discipline). If you're making something for beginners, please, please, give them the tools to build abstractions in a consistent and understandable manner.

Well, of course, Larry Wall is a god.

But that said, the main difference between Hoon line noise and Perl line noise is that most of the ASCII we use has a very regular structure, with a (relatively) limited set of exceptions. So it looks about equally alien at first, but the Hoon ideogram (digraph) set should be easier to learn. Unfortunately at present the set of people who know it is very small - so the theory really hasn't been tested.

It is what it is. But at least there's no Unicode. (Not that you can't have Unicode in strings, of course.)

And anyone who doesn't like line noise has to stand up for reserved words. Some of us welcome that conversation...

The unicode-in-strings but not in variables/etc bothers me about Java (coming from Go, where unicode is allowed in variables). It seems inconsistent to have two separate character sets for different semantic subsections of what is a single text file.

What about unicode in comments? If I put a string in a comment can it go there?

Restricting symbols to a strict subset, rather than a strict superset, of global keyboards in practice, is about cultural literacy in practice.

If you put unicode in variables, perhaps because you're using a national keyboard with special unicode powers, your code will be extremely hard to work with for programmers using a different national keyboard. Thus, even if you could do it, you shouldn't.

Now, the symbols on American programmers' keyboards are not all on every keyboard in the world - but pretty much every programmer in the world knows how to find them. Thus, sticking with ASCII is basically sensible use of Postel's Law in the language design context.

In comments - it should be ok but I think it breaks right now. Not a high priority bug, but definitely a bug.

I can search Google for reserved words. But I can't search Google for $@_{}
Hey, man, that's all on Google as I see it.

And besides, I can't Google for "go." And yet, Go seems to be doing just fine...

Larry Wall is a great man. And Perl was mighty force. An empire was built, and it may have crumbled, but all empires crumble.

One day you will be repeating these words, to a youngster that says the heroes of your Ruby palace, (or your conquering Pythonistas) were weak men of little vision, and laughs at you for following them. And when that day comes, I ask only that you think of me, and Wall, as I now think of one who followed Backus, and the mighty FORTRAN army.

Python is about as old as Perl
Larry Wall released Perl 1.0 in Dec 1987 - two years before Guido started writing Python. First usenet release of Python was Feb 1991, with 1.0 coming in 1994, with Java coming approx 1 more year later.
It's not age. C is older than Perl by decades, but I think C is a lovely little language. Lisp is as old as FORTRAN (almost) and I think it's probably the most elegant language invented yet. No, my quibble with Perl is that in throwing around implicit state everywhere (in an effort to make programming languages more like human languages) Perl is just bad as a system for building complex systems. It's not unique in this regard - Perl shares its weakness with the shell scripts it was supposed to replace.
> Hoon is a keyword-free language - any alphanumeric text in the program is part of the program. Where other languages have reserved words, Hoon has squiggles.

But... why?

You're saying, why are reserved words a bad idea? I think most defenders of the humble reserved word would consider it, at best, a hack. Maybe it's a necessary hack, maybe not.

With reserved words you are overloading two very different namespaces, the space of language primitives and the space of user functions/variables. Sure, you can get away with this. But do you want to? A language is a UI, and the potential for confusing the programmer is immense. If operators and functions are really different things - as they are in Hoon, anyway - it's very confusing to mush them together.

Lisp has no reserved words.
Yes, but Hoon would need them. Lisp gets a lot of things for free because it's based on the lambda calculus, which some regard as trivial but I don't.

So, for example, lambda in Hoon is not a primitive but a relatively high-level built-in macro. This means it is part of a larger family of lambda-like things, many of which are (IMHO) quite useful. On the other hand, all these things demand either reserved words, digraphs or Unicode glyphs.

The Lambda Calculus is so tiny how can you view it as anything but trivial?

Just 3 syntactic forms building up an expression tree:

  Expr = Lam Name Expr | Var Name | Apply Expr Expr
And one reduction rule:

  reduce (Apply (Lam name body) arg) = subst name arg body
At least assuming unique names (no shadowing nonsense), you can't get much simpler than this...
You can get rid of the whole name reduction system. Which is hardly trivial. If you assume it, though, it's true that everything else is trivial.

Getting symbol tables, functions, environments, free and bound variables, etc, etc, out of the fundamental automaton, frees you up to design them right at the higher layer where they (IMHO) belong.

This philosophical argument has serious practical ramifications, I think, because it leads directly to the Question of Why Lisp Failed. Why did Lisp fail? Many people say, because it couldn't be standardized properly.

Why couldn't it be standardized? Because the Lisp way is not to start with a simple core and build stuff on top of it, but to start with a simple core and grow hair on it. So you end up with a jungle of Lisps that are abstractly related, but not actually compatible in any meaningful sense. This is because the lambda calculus is an idea, not a layer.

Basically the point of Nock is to say: let's do axiomatic computing such that it's actually a layer in the OS sense. The way the JVM is a layer, but a lot simpler. Lambda isn't a layer in this sense, so it doesn't provide the useful abstraction control that a layer provides.

>I think, because it leads directly to the Question of Why Lisp Failed.

Lisp isn't a failure. You're commenting on a server that is powered by a Lisp.

>Why did Lisp fail? Many people say, because it couldn't be standardized properly.

There was a very good idea about how to standardize Common Lisp back in 1982. It divided documentation into 4 different parts, or 4 different "colored pages". It was eventually abandoned because of the time constraints. Read DLW's (one of the 5 main Common Lisp authors) news.yc post about it:

https://news.ycombinator.com/item?id=81258

Read more about it here:

http://www.saildart.org/ARPA.PRO%5BCOM,LSP%5D

http://xach.livejournal.com/319717.html

Lisp isn't really the only attempt to work with the lambda calculus.

Look at Haskell, Agda, and others, which are based on an a slightly extended form of LC. I doubt anyone would claim that these extensions are "hairy".

I'm not asking why reserved words are a bad idea, just opining that I think having 100 single- and double-character symbols might not be the best UI for a language. Why not have just names (neither reserved like keywords nor inscrutable like symbols?)

I don't know, I am similarly annoyed by mathematicians because they usually use single letters for variables. It's a little more excusable for them because math functions are usually very short and have few variables, but still I'd rather use words. But I digress.

It's a different approach to learning that I think favors the actual learning curve, not the perceived learning curve.

Your brain is actually built to memorize symbols like this. (I feel I know the learning process pretty well because I have toddler-aged kids who are also learning Chinese.) Of course, kids are not grownups, but even for grownups the process of binding symbol->meaning is easier than it looks like it should be.

Also, when you have name->meaning, the name inevitably is chosen for orthographic reasons and supplies its own meaning, which may mislead from the actual definition of the primitive. If you bind a symbol directly to a semantics, you lose this source of confusion. It is replaced (ideally) by an odd sense of "seeing the function," which I think is also present in experienced Perl ninjas.

The alternative, as I see it, is to let people add new keywords to the language from inside the language, so there's feature parity again.
Yes. And that's what many people find so elegant about Lisp.

But, one could argue, the "is it a function? or is it a macro?" confusion is a significant cognitive load on the Lisp programmer. These are really two different things, even though you can fit them into the same namespace.

Hoon has the different problem that you allude to - it is hard to extend the macro set at the user level. While this is fairly limiting, many FP languages, like Haskell, seem to do just fine without macro extensions. Perhaps typedness plays a role.

The bottom line on this problem is that there does remain a fair chunk of unused ASCII digraph space, so there is probably a way to put that in the programmer's power, but user-level macros are an unsolved problem in this relatively young language, nor is it one that obviously needs to be solved. But it would be nice if it does get solved.

In my view, CPU speed advances and a high-quality optimizing compiler mean there aren't many reasons to use macros in Haskell. People do, though; for examples of extensive Template Haskell use, see Yesod.
We are pretty much done with CPU speed advances and compiler optimizations. If you use an Intel i7 with the Intel C compiler, there might be a few percent left to optimize, but not much. Free lunch is over for a decade now.

You might get more cores at the same speed, but even that seems to be limited due to heat issues.

You can get more efficient CPU (e.g. SIMD instructions) but the compiler cannot optimize for them very well. Some people say implicit SIMD is a bad idea anyways.

So this is what moldbug does in his spare time.
I distinctly get the impression that the authors of this project will already know what Lojban is. This language (especially when you get to the part about reserved words, actually made up with special characters as runes, and how to pronounce them) made me think of the structure of Lojban right away.

For anyone who hasn't heard of it, http://www.tlg.uci.edu/~opoudjis/lojbanbrochure/lessons/

Urbit of course having the advantage that it can be programmed in... the video is very cool!

mi prami la lojban .ui
ge'edai
I googled, got 1/3 of the way through "Subsequent UI Cmavo", and gave up.

If you explained in lojban, I promise I'd struggle a few minutes longer before giving up :D

http://www.lojban.org/tiki/Subsequent+UI+Cmavo

I read Arabic fairly well but I did not understand Lojban, not having any framework to understand it in, whereas I took Arabic classes for basically four years of college.

I got "prami" to mean love, and .ui to mean ":)"

Why do you put .i at the beginning of some sentences?

Disclaimer: I'm no lojban expert myself, so this may be inaccurate.

{mi prami la lojban .ui} is pretty straightforward: I love lojban, plus the {.ui} attitudinal, which indicates happiness (or as you said, ":)").

The period {.} is an interesting part of lojban. It indicates a glottal stop. Most words in lojban start with a consonant, so glottal stops are placed before words that begin with a vowel (mainly just attitudinals and names). This is to prevent words from flowing into one another when speaking rapidly, which is important since one of the design goals of lojban is to avoid ambiguity.

{.i} is actually punctuation: it marks the boundary between sentences. All punctuation is pronounced in lojban. This may sound exhausting, but again, it reduces ambiguity.

{ge'edai} is intended to mean "I know that feel" -- {ge'e} meaning "unspecified emotion" and {dai} meaning "empathy" -- but I'm not sure if combining them is grammatically correct. Perhaps {dai} alone would be more accurate.

I know about . and it makes sense to me because of hamza in Arabic. It's the same. It's not a letter, it only serves to reduce ambiguity, but they wouldn't say it's punctuation either. Thanks for breaking it down for me!
The first time I have ever seen someone mention Lojban in the wild!!! How exciting!!
Next I'm going to bring up the name FactorCode because I like namedropping languages :)
(comment deleted)
Astonished.

Reminds me a bit of A+, however. :)

Congrats on the launch (even if teh Internets did it for you)!

    So if we had to read the above decrement...we’d say: 
    “luslus dec sigfas cen dec bartis a tis pat sigbar soq
    dec soq ketcab pat wutgal tis pel zero a per tislus b 
    tis pat barhep wutcol tis pel a lus pel b per per b buc 
    pel b lus pel b per per.”
Absolute brilliance.
Well, I've read most the docs, let's say _skimmed_ the code examples, and I think you're a very smart, competent engineer with a sense of what makes for good language syntax that is utterly, incomprehensibly alien to me. So I guess, martian-language mission accomplished?