mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-11-11 04:48:00 +03:00
first draft of quickstart and partial network messages
This commit is contained in:
parent
d55da0ff39
commit
5927312f10
172
pub/docs/dev/hoon/top-down/0-quickstart.mdy
Normal file
172
pub/docs/dev/hoon/top-down/0-quickstart.mdy
Normal file
@ -0,0 +1,172 @@
|
||||
---
|
||||
next: true
|
||||
sort: 1
|
||||
title: Quickstart
|
||||
---
|
||||
|
||||
# Quickstart
|
||||
|
||||
If you're interested in programming in urbit, you've come to the
|
||||
right place. This is a jump-in, get-your-hands-dirty,
|
||||
roll-in-the-mud-and-figure-things-out intro to programming hoon
|
||||
on urbit.
|
||||
|
||||
The first thing to do, of course, is get an urbit up and running.
|
||||
The only ingredients are a Unix box and a pinch of courage, so
|
||||
check out the [installation
|
||||
instructions](http://urbit.org/docs/user/install) to get started.
|
||||
|
||||
Once urbit is installed, if you have an invitation, it's a planet
|
||||
like `~fintud-macrep` and a ticket like
|
||||
`~fortyv-tombyt-tabsen-sonres`. Run
|
||||
|
||||
bin/urbit -w fintud-macrep -t fortyv-tombyt-tabsen-sonres
|
||||
|
||||
(You can leave the `~` on, but it annoys some Unix shells.)
|
||||
|
||||
If you don't have an invitation, pick a nickname for your comet,
|
||||
like `mycomet`. Urbit will randomly generate a 128-bit plot:
|
||||
|
||||
bin/urbit -c mycomet
|
||||
|
||||
Either way, creating your urbit will take some time. Some of
|
||||
this time involves creating keys; some of it involves downloading
|
||||
code over Urbit itself.
|
||||
|
||||
If you turn off your pier at any time (either "nicely" with `^D`
|
||||
from talk or the dojo or by power-failure, oom-killer, or other
|
||||
calamity), then you can start it up again with the path to your
|
||||
pier directory (your planet name if you have an invitation,
|
||||
otherwise the name you chose after `-c`):
|
||||
|
||||
bin/urbit fintud-macrep
|
||||
|
||||
or
|
||||
|
||||
bin/urbit mycomet
|
||||
|
||||
## Basic operation
|
||||
|
||||
Out of the box, your urbit is running two default appliances,
|
||||
`:dojo` (a shell or REPL) and `:talk`. Switch between them with
|
||||
`^X`. Note that all apps share an output log, but `^X` switches
|
||||
the prompt.
|
||||
|
||||
`^D` from either default appliance exits the urbit process.
|
||||
|
||||
If your plot is `~fintud-macrep`, the dojo prompt is
|
||||
|
||||
~fintud-macrep:dojo>
|
||||
|
||||
Type any Hoon expression at the command line and see the result:
|
||||
|
||||
~fintud-macrep:dojo> (add 2 2)
|
||||
|
||||
You'll see:
|
||||
|
||||
> (add 2 2)
|
||||
4
|
||||
~fintud-macrep:dojo>
|
||||
|
||||
You can also run commands from the dojo. Unix users should
|
||||
recognize some of these (`%` means current working directory).
|
||||
|
||||
> +ls %
|
||||
ape/
|
||||
arvo/
|
||||
docs/
|
||||
elem/hook
|
||||
front/
|
||||
gen/
|
||||
index/hook
|
||||
lib/
|
||||
mar/
|
||||
pub/
|
||||
spec/nock/%/txt
|
||||
sur/
|
||||
tree/
|
||||
tree-gen/tree-include/hook
|
||||
try/readme/md
|
||||
> +cat %/try/readme
|
||||
/~nibrun-dozlyr-wictuc-folrex/home/~2015.11.17..21.22.58..ee8e/try/readme/md
|
||||
/=try=/
|
||||
|
||||
This is the try desk. Feel free to try out whatever you want here.
|
||||
|
||||
Often it's useful to edit urbit files from Unix. Use `|mount` to
|
||||
set up a Dropbox-style sync directory in your pier directory:
|
||||
|
||||
> |mount %
|
||||
>=
|
||||
> |unmount %
|
||||
>=
|
||||
|
||||
Look inside your pier directory to find your files, and edit them
|
||||
with your favorite Unix text editor.
|
||||
|
||||
Sometimes you want to get files from another urbit. There's two
|
||||
main commands to do this.
|
||||
|
||||
> |merge %my-examples ~wactex-ribmex %examples
|
||||
>=
|
||||
; ~wactex-ribmex is your neighbor
|
||||
; ~wactex-ribmex is your neighbor
|
||||
[time passes...]
|
||||
merged with strategy %init
|
||||
|
||||
This pulls a bunch of examples from `~wactex-ribmex`'s `%examples`
|
||||
desk and puts them in our `%my-examples` desk. A desk is a
|
||||
branch (in the git branch sense) of our filesystem.
|
||||
|
||||
You can, of course, merge the examples into your `%home`
|
||||
(default) desk if you wish. Merging into a new desk creates it,
|
||||
while merging into an existing desk does an intelligent git-style
|
||||
merge, with conflict resolution and stuff.
|
||||
|
||||
> |sync %my-examples ~wactex-ribmex %examples
|
||||
>=
|
||||
activated sync from %examples on ~wactex-ribmex to %my-examples
|
||||
sync succeeded from %examples on ~wactex-ribmex to %my-examples
|
||||
> |unsync %my-examples ~wactex-ribmex %examples
|
||||
ended autosync from %examples on ~wactex-ribmex to %my-examples
|
||||
|
||||
`|sync` does an initial `|merge`, then listens for changes on the
|
||||
foreign desk and runs `|merge` automatically whenever it changes.
|
||||
By default your `%home` desk is synced to your parent's `%kids`
|
||||
desk, so the entire network is upgraded at once. You may, of
|
||||
course, unsync it, but this voids your warranty.
|
||||
|
||||
You can change which desk is your current working directory with:
|
||||
|
||||
> =% /=my-examples
|
||||
|
||||
When you change your desk all commands will be using the files
|
||||
from that desk. Unfortunately, changing your working directory
|
||||
to anywhere but the top directory is currently
|
||||
[broken](http://github.com/urbit/urbit/issues/565). If this
|
||||
is fixed when you're reading this, please submit a pull request
|
||||
for this document explaining how to do it!
|
||||
|
||||
The last command we'll discuss in this quickstart is `+moon`,
|
||||
which only works on planets.
|
||||
|
||||
> +moon
|
||||
"moon: ~ramnec-rossug-fintud-macrep; ticket: ~holtyl-mognyl-dostyp-moslud"
|
||||
|
||||
This generates a random moon and ticket. A moon is a subidentity
|
||||
of your planet, so it's a separate urbit that's associated with
|
||||
your planet. If your planet is off, then your moon won't
|
||||
function very well over the network (it'll work just fine
|
||||
locally, of coures).
|
||||
|
||||
You can start up your moon with `bin/urbit -w moon-name -t
|
||||
ticket`. We recommend doing this for development because there
|
||||
are still some instabilities that have the potential to explode
|
||||
your planet if you develop on it. If this happens, then your
|
||||
planet will be unusable until the next continuity breach. If you
|
||||
tell us how you exploded your planet, we may give you a
|
||||
replacement, but it's still a hassle for you.
|
||||
|
||||
Don't worry too much about exploding your moons -- you have four
|
||||
billion of them, and they get replenished after every continuity
|
||||
breach. Still do file a bug, though.
|
188
pub/docs/dev/hoon/top-down/2-network.mdy
Normal file
188
pub/docs/dev/hoon/top-down/2-network.mdy
Normal file
@ -0,0 +1,188 @@
|
||||
---
|
||||
hide: true
|
||||
next: false
|
||||
sort: 3
|
||||
title: Network Messages
|
||||
---
|
||||
|
||||
Enough of pure hoonery. Let's get to the good stuff. Let's get
|
||||
our planets to talk to each other.
|
||||
|
||||
Of course, for talking to be of any use, we need someone
|
||||
listening. What we've written up until now are just shell
|
||||
commands that produce a value and then disappear. We need an
|
||||
actual app to listen for messages from another planet. Let's
|
||||
take a look at a very basic one.
|
||||
|
||||
```
|
||||
:: There is no love that is not an echo
|
||||
::
|
||||
:::: /hoon/echo/ape
|
||||
::
|
||||
/? 314
|
||||
|%
|
||||
++ move ,*
|
||||
--
|
||||
!:
|
||||
|_ [bowl state=~]
|
||||
++ poke-noun
|
||||
|= arg=*
|
||||
^- [(list move) _+>.$]
|
||||
~& [%argument arg]
|
||||
[~ +>.$]
|
||||
--
|
||||
```
|
||||
|
||||
This is a very simple app that does only one thing. If you poke
|
||||
it with a value it prints that out. You have to start the app,
|
||||
then you can poke it from the command line.
|
||||
|
||||
```
|
||||
> |start %echo
|
||||
>=
|
||||
> :echo 5
|
||||
[%argument 5]
|
||||
> :echo [1 2]
|
||||
[%argument [1 2]]
|
||||
```
|
||||
|
||||
Most of the app code should be simple enough to guess its
|
||||
function. The important part of this code is the definition of
|
||||
`++poke-noun`.
|
||||
|
||||
Once an app starts, it's always on in the background, and you
|
||||
interact with it by sending it messages. The most
|
||||
straightforward way to do that is to poke it from the command
|
||||
line. When you do that, `++poke-noun` is called from your app.
|
||||
|
||||
In our case, `++poke-noun` takes an argument `arg` and prints it
|
||||
out with `~&`. This is an unusual rune that formally "does
|
||||
nothing", but the interpreter detects it and printfs the first
|
||||
child. This is a slightly hacky way of printing to the console,
|
||||
and we'll get to the correct way later on.
|
||||
|
||||
But what does `++poke-noun` produce? The phrase to remember is
|
||||
"a list of moves and our state". Urbit is a message passing
|
||||
system, so whenver we want to do something that interacts with
|
||||
the rest of the system we send a message. Thus, the first thing
|
||||
that `++poke-noun` produces is a list of messages, called
|
||||
"moves". In this case, we don't actually want the system to do
|
||||
anything, so we produce the empty list, `~`.
|
||||
|
||||
The second thing `++poke-noun` produces is our state. `+>.$`
|
||||
refers to a particular address in our subject where our formal
|
||||
app state is stored. It'll become clear why this is later on,
|
||||
but for now pretend that `+>.$` is a magic invocation that means
|
||||
"app state".
|
||||
|
||||
---
|
||||
|
||||
But what is our app state, exactly? In Unix systems, application
|
||||
state is just a block of memory, which you need to serialize to
|
||||
disk if you want to keep it around for very long.
|
||||
|
||||
In urbit, app state is a single (usually complex) value. In our
|
||||
example, we don't have any special state, so we defined
|
||||
`state=~`, meaning that our state is null. Of course, `state` is
|
||||
just a name we're assigning to it, and you're free to use
|
||||
whatever name you want.
|
||||
|
||||
Since urbit is purely functional, we can't just implicitly "have"
|
||||
and "change" our state. Rather, it's explicitly passed to us, in
|
||||
the `|_ [bowl state=~]` line, and we produce the new state with
|
||||
`+>.$` in the `[~ +>.$]` line.
|
||||
|
||||
Two points you may be wondering about. Firstly, `bowl` is a set
|
||||
of general global state that is managed by the system. It
|
||||
includes things like `now` (current time), `our` (our urbit
|
||||
identity), and `eny` (256 bits of guaranteed-fresh entropy). For
|
||||
the full list of things in `++bowl`, search for `++ bowl` (note
|
||||
the double space) in `/arvo/zuse.hoon`.
|
||||
|
||||
> This is a very common technique in learning hoon. While some
|
||||
> documentation exists, often the easiest way to learn about an
|
||||
> identifier you see in code is to search in `/arvo/zuse.hoon`
|
||||
> and `/arvo/hoon.hoon` for it. These are our two "standard
|
||||
> libraries", and they're usually not hard to read. Since
|
||||
> urbit's codebase is relatively small (those two files are less
|
||||
> than 15000 lines of code combined, and besides the standard
|
||||
> library they include the hoon parser and compiler, plus the
|
||||
> /arvo microkernel), you can usually use the code and the
|
||||
> comments as reference doc.
|
||||
|
||||
Second point is that urbit needs no "serialize to disk" step.
|
||||
Everything you produce in the app state is persistent across
|
||||
calls to the app, restarts of the urbit, and even power failure.
|
||||
If you want to write to the filesystem, you can, but it's not
|
||||
needed for persistence. Urbit has transactional events, which
|
||||
makes it an ACID operating system. Persistence is just another
|
||||
one of those things you don't have to worry about when
|
||||
programming in urbit.
|
||||
|
||||
As fascinating as state is, we don't actually need any state to
|
||||
accomplish our immediate goal, which is to get apps on two urbits
|
||||
talking to each other. We'll discuss state more in a later
|
||||
chapter.
|
||||
|
||||
---
|
||||
|
||||
Anyway, that's a lot of theory, let's get back to coding. Let's
|
||||
say we want to only accept a number, and then print out the
|
||||
square of that number.
|
||||
|
||||
```
|
||||
/? 314
|
||||
|%
|
||||
++ move ,*
|
||||
--
|
||||
!:
|
||||
|_ [bowl state=~]
|
||||
::
|
||||
++ poke-atom
|
||||
|= arg=@
|
||||
^- [(list move) _+>.$]
|
||||
~& [%square (mul arg arg)]
|
||||
[~ +>.$]
|
||||
--
|
||||
```
|
||||
|
||||
A few things have changed. Firstly, we no longer accept
|
||||
arbitrary nouns because we can only square atoms. Thus, our
|
||||
argument is now `arg=@`. Secondly, it's `++poke-atom` rather
|
||||
than `++poke-noun`.
|
||||
|
||||
Are there other `++poke`s? Definitely. In fact, `noun` and
|
||||
`atom` are just two of arbitrarily many "marks". A mark is
|
||||
fundamentally a type definition, and each mark is defined in the
|
||||
`/mar` directory. Some marks have conversion routines to other
|
||||
marks, and some have diff, path, and merge algorithms. None of
|
||||
these are required for a mark to exist, though.
|
||||
|
||||
`noun` and `atom` are two of dozens of predefined marks, and the
|
||||
user may add more at will. The type associated with `noun` is
|
||||
`*`, and the type associated with `atom` is `@`.
|
||||
|
||||
Data constructed on the command line is by default marked with
|
||||
`noun`. In this case, the app is expecting an atom, so we have
|
||||
to explicitly mark the data with `atom`.
|
||||
|
||||
```
|
||||
> |start %square
|
||||
> :square 6
|
||||
gall: %square: no poke arm for noun
|
||||
> :square &atom 6
|
||||
[%square 36]
|
||||
```
|
||||
|
||||
Marks are powerful, and they're the backbone of urbit's data
|
||||
pipeline, so we'll be getting quite used to them.
|
||||
|
||||
Let's write our first network message!
|
||||
|
||||
-don't forget to explain new hoon concepts ([])
|
||||
-excercises
|
||||
-then walk through more in depth
|
||||
-move app state section to somewhere later
|
||||
-put in interactive code snippets and explain a lil (bowl)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user