HNHacker News
TopNewBestAskShowJobs

urbit

899 karma · joined September 16, 2013

https://github.com/urbit
submissionscomments
urbit··on The web of names, hashes and UUIDs
As concisely as possible: IPFS is a way to publish your data in the cloud (and the related Filecoin project is a way to host your cloud data), urbit is a way to publish and host your identity, computing and data.

As a more specialized project, you'd expect IPFS to be better at the part of the problem it solves, for the same reason a sprinter sprints faster than a decathlete. (Not to mention that JB is awesome.) On the other hand, not having an identity model other than public keys (or, to put it differently, not trying to square Zooko's triangle), imposes certain problems on IPFS that urbit doesn't have. For instance, with routable identities, you don't need a DHT, and so the idea of a hash-addressed namespace is less interesting.

That said, it would be easy to imagine a world in which urbit either could talk to IPFS, or even layered its own filesystem (which has a fairly ordinary git structure under the hood) over IPFS. Like I said, it's a cool project.

urbit··on The web of names, hashes and UUIDs
As Dr. Emilio Lizardo once put it... never mind. :-)
urbit··on Urbit: a personal cloud computer
If you look below I've made arguments for all these things, but let me try to address them here. Compare

  ++  add
    |=  [a=@ b=@]
    ^-  @
    ?:  =(0 a)  b
    $(a (dec a), b +(b))
to

   attribute add {
     function(left-operand: atom, right-operand: atom)
     produce atom
     if equals(0, left-operand) {
      right-operand
     } else {
        recurse(left-operand (decrement left-operand)), 
                right-operand (increment right-operand))
     }
   }
As for the variable names, I can think of very few programmers who would insist that "left-operand" and "right-operand" are better names, in this context, then "a" and "b".

Using "a" and "b" accurately expresses the simplicity of the algorithm, and nothing could be easier to read. OLV in "add" says: there is nothing interesting here. "left-operand" and "right-operand" says: there is some semantic meaning here, which you have to trouble your brain to understand. But actually, it's just pointless wordiness - in this case.

As for the syntax, you no doubt can read my wordy example better. But a programming language is a professional tool, not a toy. Anything new demands a genuine investment to learn - this investment has to be paid off by actual productivity.

And people are, as I've said, much better at learning random associations than they think. Again, we've taught this syntax to everyone from Haskell jocks to JS cruft-jockeys to innocent CS 101 victims. The biggest problem - and it is a problem - is not that it it is hard, but that it seems hard.

urbit··on Urbit: a personal cloud computer
They do - but arguably being forced to define the distinction between direct hierarchical references, and symbolic links, helps constrain your data model and make it more rigorous.

Note that relational databases don't have back pointers either. All references between tables are symbolic. Last century, people tried to make databases that were general pointer graphs (google "network database" or "object database") - broadly speaking, it was a disaster.

urbit··on Urbit: a personal cloud computer
That I was keeping my p - never mind.

It's amazing how quickly words you know lose their meanings, or rather acquire new and distinct ones, in a functional context. When the iPad was released, I remember distinctly the number of people who thought the name was funny, because it reminded them of a female hygiene product. It reminded me of a female hygiene product. But it doesn't anymore...

urbit··on Urbit: a personal cloud computer
+1 - I can't emphasize this too strongly.
urbit··on Urbit: a personal cloud computer
Don't worry - the test of a system is what it can do. If we were ready to show you what it can do, we'd have released it intentionally instead of unintentionally.

It's very difficult for a language, good or bad, to compete on its own merits or even demerits. C is a better language than Pascal, but people didn't start programming in C because of that - they started programming in C because the native language of Unix was C, and they wanted to program in Unix. Why did they want to program in Unix? Because, relative to its competitors in the minicomputer OS market, Unix was a better way to solve their problems. This is the normal way that new languages achieve adoption - they ride on the back of a new platform, which rides on the back of new solutions to (typically) new problems.

Today you see a lot of apps like Buffer and Slack, which are very successful in terms of userbase and even revenue. From a certain perspective, the value these apps are adding is very minimal - Buffer is... what, cron? And yet, there is a considerable distance between an AWS box in the cloud and a Buffer instance. A lot of value actually is being added.

Most of the code in a product of this type is actually the (usually somewhat) general framework that sits between the Linux ABI and the application logic/UI. Essentially there's a type of Greenspun's Law in play. If you build a layer like this, but as a true operating environment rather than an internal framework, the result is a VM in which the distance from a virgin instance to many of these kinds of apps is much smaller. In a familiar Valley pattern, they then become commoditized and have more trouble extracting rents.

If it's possible to provide this kind of value, which we certainly haven't yet demonstrated, I can assure you quite confidently that a flashcard or two is not an obstacle. I'm in my 40s, so I know how hard it is for a middle-aged dog to learn new tricks. But it's not that hard.

urbit··on Urbit: a personal cloud computer
Nock works perfectly, of course, but it's poorly optimized. The various "jets" (optimized implementations) in our runtime haven't been adequately tested and there are probably a few corner cases, errors, etc, where the behavior doesn't match. Even the new Nock runtime (I just rewrote more or less the whole interpreter) is probably a little too bound to Urbit specifically.

But the system has been self-hosting for quite some time, and there's certainly no doubt that the general approach works...

urbit··on Urbit: a personal cloud computer
Right. The way I'd put it is: in system software, the iron law is that you don't make the programmer pay for anything she doesn't need to buy.

What you pay (GC) for the privilege of having pointer cycles in your data is grossly disproportionate to the benefit. Yes, there are a lot of things that are O(k) with pointer cycles and O(log n) without them. If what you buy from this optimization is worth the cost of GC, you are doing a lot of these things... a lot.

urbit··on Urbit: a personal cloud computer
That's correct. :-)
urbit··on Urbit: a personal cloud computer
It's not ready for them yet. :-)
urbit··on Urbit: a personal cloud computer
I resemble this remark. We're making progress more than twice as fast than Xanadu!
urbit··on Urbit: a personal cloud computer
Yeah, it's probably not one of our better decisions.
urbit··on Urbit: a personal cloud computer
Frankly, it always surprises me that people are willing to randomly run other peoples' C code! It's really quite plausible that I'm just out to steal your Bitcoin wallet.

The above are all data structures - not even functions. So we say "a pimp" or "a marl" or whatever. For precision, we might say "slam a gate on a pimp," but everyone will understand you when you say "call a function on a pimp."

Then, we refer to the comments (written in English) to see what a pimp, etc, is. Documentation is admittedly a problem, but it's not any more or less a problem than in any other language, I feel. Obviously, we could have more of it!

urbit··on Urbit: a personal cloud computer
I definitely wouldn't endorse this description - it's a bit secondhand.

What I'd say is that Urbit is not designed to be a darknet. It is not Tor and it's not Bitcoin. Also, it is not designed for external governments, or even its mysterious and sketchy founders, to govern - it is designed to govern itself. (Through user-level reputation mechanisms which have yet to be built, but are relatively easy to build - because the limited supply of identities controls Sybil attacks.)

In particular, Urbit should be quite good at enabling anonymous free speech beyond the reach of governments. A self-hosted node in your closet is quite practical and effective. There is no anonymization / onion routing (and you can't trivially route Urbit over Tor, because Urbit uses UDP), but someone could build that.

Although I don't want them to. I want to enable anonymous, or better yet pseudonymous, free speech. I don't want to help people buy drug$ or childpron through the mail. Fortunately or unfortunately, there are already much better tools for that.

urbit··on Urbit: a personal cloud computer
If you s/is/could be/, I would agree. I would say s/is/should not be/. That is, it is possible to screw this up and create "intimacy" (high coupling), but obviously I recommend against it.

Put it this way: when it's properly done, the jets (specific optimizations) are coupled to your compiler and libraries about the way your display server is coupled to your graphics driver. As a programmer you can't, don't and shouldn't know what if any GPU is executing your GL. Or at least, if you do - mistakes have been made.

Added to this is the fact that it's possible to obtain at least decent performance just by using standard basic math, eg, decrement. Yes, you can roll your own decrement - but at this point you are just being perverse.

urbit··on Urbit: a personal cloud computer
Essentially, I'd say most peoples' brains are better at associative memory than they think they are.

When you see a digraph like -> or ?: in C, do you think "hyphen greater-than" or "question-colon"? Your brain long ago learned to treat these as individual symbols, not strings of two characters. And this despite not even having easy-to-say names for them. (In Hoon they are "hepgar" and "wutcol" respectively.)

urbit··on Urbit: a personal cloud computer
Three-letter variable, one-letter variable, http://www.merriam-webster.com/dictionary/lapidary.
urbit··on Urbit: a personal cloud computer
The latter. :-)
urbit··on Urbit: a personal cloud computer
TempleOS is a competitor, not a partner. Privately, between you and me - that guy is going down.
urbit··on Urbit: a personal cloud computer
I prefer to think of it as: you can be "free as in beer" or "free as in speech," but not both. Sith Lord Zuck has set you free as in beer, but not in speech. Urbit will set you free as in speech, but not as in beer.

The difference is simply that while there are a limited number of Urbit identities (or at least memorable identities, ie, 32-bit "destroyers") in the world, and therefore they can't possibly be made free as in beer, neither I nor my evil minions have any practical power over a destroyer once we create it.

Moreover, if you genuinely think of any individual or organization involved with Urbit as evil, there are plenty of independent carrier-holders you can get a destroyer from. (~del, for instance, will ship destroyers when we do, I think. He's some guy in Rochester whom I don't know from Adam. So, we'll let him serve the first 16 million people who want to escape from our evil dictatorship.)

Yes, by default the normal way to get onto Urbit will feel like the normal way to get onto Facebook. However, even if you are initially issued and hosted by us, you can move your image at any time to any other host, or to your own machine. Currently there's no way to stop using your issuing carrier for network services, such as firewall hole punching, but this is obviously a 1.0 feature. By design, there is no sort of leverage you can't escape from.

So Urbit strikes a sort of balance between governed and ungoverned networks. The limited address space will hopefully make it economically impractical to abuse the network for profit - a spammer is always a Sybil attacker. But as a destroyer you are not ruled by any master you can't easily escape from. The only thing you can't escape is your own reputation. Which you shouldn't be able to escape from.

We should probably highlight this difference a little more in the doc...

urbit··on Urbit: a personal cloud computer
Again, the contributor list in github is WAY misleading, because it accidentally somehow pulled in all the contributors of the libraries we bundled (eg, libuv). We need to fix this, I think.
urbit··on Urbit: a personal cloud computer
Yes, some people have made this criticism. We'll be thinking about it.
urbit··on Urbit: a personal cloud computer
Perhaps it makes a bit more sense if it's explained that the original goal was to keep the whole codebase (outside of the C support layer, which adds no semantics) at 10Kloc. Unfortunately this is now rapidly slipping toward 20.

Of course, Kloc is a deceptive measure of algorithmic simplicity in a functional language, if compared to procedural. Also there is about another 15Kloc of C in the interpreter and another 10K that wraps an event layer on libuv.

Bear in mind that Urbit can also be seen as an ACID database on the log-and-snapshot principle - events are transactions. You can of course export application state to some other storage system, but you don't have to. (If you change the source code, your app reloads - you do have to write a function that maps your old state to your new state, though.) So there is a lot of strange futzing around with mmap at the bottom.

urbit··on Urbit: a personal cloud computer
I'm quite confident that Eliezer would object strenuously to this characterization!
urbit··on Urbit: a personal cloud computer
I think the classic analogy is "grep." But they are commented, at least:

  ++  pimp              ::  traced request
    $:  ful=?           ::  | === HEAD
        fur=(unit mark) ::  type goal
        hen=duct        ::  event trace
        som=seam        ::  logical request
        pez=pest        ::  request state
        sip=marl        ::  injected scripts
    ==                  ::
I think this is not at all an unusual data structure for one to find in an HTTP server, no?

Now, this style (four-letter lapidary arm names, usually not nonsense strings but nonsense words) works in some places but not others. Frankly, %eyre is not exactly a triumph of the lapidary style...

urbit··on Urbit: a personal cloud computer
Why would you write a new Nock back-end at the same time as a compiler for a new language? Even if you did, you'd want to test the new interpreter with the old language, and the new language with the old interpreter, before going any further.

There is certainly no free lunch in this system. If your CPU is radiating heat, it is spending a bunch of time in Nock formulas which could be better optimized. For instance, maybe you rolled your own decrement, so the interpreter can't match it with the jet it uses for stock Hoon decrement.

That's okay, because the jet matching mechanism is not in any way specialized to the code. All you have to do is (a) get your compiler for the new language to emit a proper jet hint for your things-you-want-to-be-fast, (b) write correctly matched C implementations, and (c) add them to a static array.

Or to put it more briefly: a well-designed Nock implementation is not in any way coupled to the Hoon or Arvo layers.

One of the not-quite-finished things about our interpreter right now (other than that it interprets the tree directly and so gets about 1.5 Nock mips, which is pathetic) is that jets have to be compiled into the kernel and aren't opened by dlopen. Ideally we'd even load something like a PNACL/LLVM object, and we'd get it the same way we get the Hoon source, ie, via Urbit itself.

urbit··on Urbit: a personal cloud computer
Suppose we wrote this with keywords. I can't stomach a naked keyword so I'll put a colon on the front. We might write:

  :function lax {
    :object :tuple{her: ship dur: dore}  {
      :function cluy {
        :produce :tuple{p: life q: gens r: acru}
        :ifno lew.wod.dur  :error
        :unless (equals fak.ton r.i.lew.wod.dur) {
          :record :tuple{%client-wrong-fake her}
          :error
        } :then {
          :tuple {
             p.p.q.i.lew.wod.dur
             q.q.i.lew.wod.dur
             (haul r.q.i.lew.wod.dur)
          }
        }
      }
    }
  }
Is this better? Arguably, it's easier to learn. But I'm not sure I would regard it as better.

Also, for your convenience we've assigned CVC nonsense names to all the ASCII characters. Pasting from the source:

  ++  ace  (just ' ')
  ++  bar  (just '|')
  ++  bas  (just '\\')
  ++  buc  (just '$')
  ++  cab  (just '_')
  ++  cen  (just '%')
  ++  col  (just ':')
  ++  com  (just ',')
  ++  doq  (just '"')
  ++  dot  (just '.')
  ++  fas  (just '/')
  ++  gal  (just '<')
  ++  gar  (just '>')
  ++  hax  (just '#')
  ++  kel  (just '{')
  ++  ker  (just '}')
  ++  ket  (just '^')
  ++  lus  (just '+')
  ++  hep  (just '-')
  ++  pel  (just '(')
  ++  pam  (just '&')
  ++  per  (just ')')
  ++  pat  (just '@')
  ++  sel  (just '[')
  ++  sem  (just ';')
  ++  ser  (just ']')
  ++  sig  (just '~')
  ++  soq  (just '\'')
  ++  tar  (just '*')
  ++  tec  (just '`')
  ++  tis  (just '=')
  ++  wut  (just '?')
  ++  zap  (just '!')
One of the problems with using these handy little glyphs in syntax (and an even worse problem with using Unicode glyphs in programming, btw) is that "semicolon" is not convenient to say. The length of the vocalization matters a lot to how you think about a symbol, even if you don't often say it.
urbit··on Urbit: a personal cloud computer
Good lord, no! Hoon has no reserved words at all.

The nonsense words are all names. This is entirely a style choice. The actual name syntax is roughly Lisp's - for instance, (my-long-function arg1 arg2) does the same thing (roughly) in Hoon as in Lisp.

In the "lapidary" Hoon in which most of the kernel is written, facets (variable names, roughly) are meaningless TLV strings, usually CVC (consonant-variable-consonant).

The user experience is much the same as with Greek letters in math: you remember the binding between symbol and semantics if you know the code you're looking at. If you are learning the code, your first task is to learn that binding. Once you know the code, there is no quasi-semantic intermediary - a meaningful name - between the symbol and the concept.

I think our small sum of experience with this daring idea is that sometimes, it works better than other times. Basically, TLV naming is appropriate for code that is simple, but not trivial. (Trivial code, like "++add", is "ultralapidary" and gets OLV names - like "a" and "b".)

Ideally all of the Arvo kernel and Hoon self-compiler would meet the TLV standard of quality. All of it is written this way, though. In general, if you should be writing lapidary code, you know it, and if you don't know you shouldn't. (And should use more or less normal names as in any Lisp.)

urbit··on Urbit: a personal cloud computer
I wouldn't say it's based on SKI - just relatively similar. There are a lot of ways to skin this cat.

SKI is obviously a lot simpler mathematically, but I wouldn't want to try to use it as a compiler target...

← PreviousPage 3 of 6Next →