take out docs

This commit is contained in:
Galen Wolfe-Pauly 2016-01-27 11:01:01 -08:00
parent 7ebefb7c5f
commit 2e72056fb5
210 changed files with 0 additions and 44467 deletions

View File

@ -1,24 +0,0 @@
---
anchor: none
layout: no-anchor
logo: black
---
<div class="short lead">
# Urbit documentation
The Urbit doc is divided into three parts: [user doc](docs/user),
[developer doc](docs/dev), and [theory](docs/theory) (whitepaper, essays,
videos, etc).
If you want to try Urbit, start with the user doc. If you want
to learn about Urbit, try the theory. Or just start with the
user doc; it doesn't assume any prior knowledge.
The most fun thing to do with Urbit is code, but the developer
doc remains under construction. Sorry. We'll have more soon.
<list dataSort="true" class="children"></list>
</div>

View File

@ -1,28 +0,0 @@
---
logo: black
sort: 2
title: Developer doc
---
<div class="short">
# Developer documentation
Urbit has three programming layers: [Nock](dev/nock) (combinator nano-VM),
[Hoon](dev/hoon) (strict functional language), and [Arvo](dev/arvo) (functional
OS).
To code in Urbit, the least you need to learn is Hoon, plus a
little bit of Arvo. Nock is a sort of functional assembly
language -- you don't need to know it, but it's useful to.
Nock is also the easiest thing in the world to learn.
You can program for Arvo without knowing much about Arvo
internals, but again it helps. But you need to know Hoon.
Don't worry, it's easier than it looks.
Alas, the developer doc is still under construction. We'll have
more soon.
<list></list>
</div>

View File

@ -1,13 +0,0 @@
---
logo: black
sort: 3
title: Arvo
---
<div class="short">
# Arvo
Arvo is a functional operating system. But hopefully you knew that! Sorry,
please watch this space for actual documentation.
</div>

View File

@ -1,11 +0,0 @@
---
hide: true
logo: black
sort: 4
title: Frontend tools
---
Frontend tools
==============
<list></list>

View File

@ -1,59 +0,0 @@
# `:tree`
`:tree` is the web filesystem interface. Odds are this file has been rendered for you by `:tree`.
`:tree` is a single-page app that uses a backend in `/home/tree` to load
contents from `%clay` as the user navigates around as `%json`. The frontend
lives in `/home/pub/tree` and is a fairly straightforward
[React](https://facebook.github.io/react/) /
[Flux](https://facebook.github.io/flux/) app.
## Frontend
The frontend code for `:tree` can be found in `/home/pub/tree/src/`.
### CSS
The CSS is written in [Stylus](https://learnboost.github.io/stylus/). The main entry point is `main.styl` and can be compiled with `stylus main.styl` which should output a `main.css`
### JS
The JS is written in [CoffeeScript](http://coffeescript.org/) and packaged with
[Browserify](http://browserify.org/). The main entry point is `main.coffee` and
is compiled with `browserify -t coffeeify main.coffee > main.js`. You'll need
to `npm install` first.
Each page is loaded as JSON and then rendered using React on the page. This
allows us to write JSX in our markdown to implement simple components. Check
out `/home/pub/tree/src/js/components` to see the component library.
You'll notice that some of these doc pages use things like `<list>` in the raw markdown files.
## JSON API
Async provides loading by schema
`{path name sein sibs next prev}` are all immediately accesible from the store
a `getPath` method, if present (defaulting to current url), is used to determine the query root node.
## JSON Internals
### `/[desk]/tree/{path}.json`
`tree/json.hook` accepts a query string schema `q` in light noun encoding
++ schema (dict ,[term $|(mark schema)])
++ dict |*(a=_,* $&([a (dict a)] a))
which is normalized and type-checked to a `query` list of
- `[%kids query]`, the only recursive value, which executes for all subpaths
XX descent is only currently supported to a single level as a performance optimization
- `[%name %t]`, the node name
- `[%path %t]`, the current path
- `[%snip %r]`, a snippet, extracted via `react-snip-json`
- `[%head %r]`, the first `<h1/>`, extracted via `react-head-json`
- `[%body %r]`, the `react-json` body
- `[%meta %j]`, json frontmatter per the `mdy` mark definition
The request types above are `%t` text, `%r` html-derived tree, and `%j`
arbitrary json; an example query, used by the main content renderer, is
`"q=body.r__kids_name.t"` (`body:'r' kids:{name:'t'}` )

View File

@ -1,213 +0,0 @@
---
sort: 6
title: Contributing
---
# Contributing to urbit
Thank you for your interest in contributing to urbit.
## Development practice
You may have an identity on the live network, but doing all your
development on the live network would be cumbersome and unnecessary.
Standard practice in urbit development is to work on a fake `~zod`. A
fake `~zod` will get its initial files from the `urb/zod/` directory
rather than trying to sync them over the network, which is invaluable
for working in Hoon. Also, a fake `~zod` or any fake urbit instances you
start do not talk to the live network, but to a fake network that exists
only on your computer.
To start a fake `~zod`, the command is:
bin/urbit -F -I zod -c [pier directory]
To resume one that was already created, just as on the live network,
remove `-c` (but leave the rest of the options there). `-F` uses the
fake network, and `-I` starts an "imperial" instance - that is, an 8-bit
galaxy.
## Kernel development
Working on either C or non-kernel Hoon should not bring any surprises,
but the Hoon kernel (anything under `urb/zod/arvo/`) is bootstrapped
from `urbit.pill` in `urb/`, and must be manually recompiled if any
changes are made. The command to manually recompile the kernel and
install the new kernel is `|reset` in `dojo`. This rebuilds from the
`arvo` directory in the `home` desk in `%clay`. Currently, `|reset`
does not reload apps like `dojo` itself, which will still reference the
old kernel. To force them to reload, make a trivial edit to their main
source file (under the `ape` directory) in `%clay`.
If you do any kernel development, be sure to read the section below about
pills.
## Git practice
Since we use the GitHub issue tracker, it is helpful to contribute via a
GitHub pull request. If you already know what you are doing, skip down
to the Style section.
Start by cloning the repository on your work machine:
git clone https://github.com/urbit/urbit
And, additionally, fork the repository on GitHub by clicking the "Fork"
button. Add your fork as a remote:
git remote add [username] https://github.com/[username]/urbit
and set it as the default remote to push to:
git config --local remote.pushDefault [username]
This is good practice for any project that uses git. You will pull
upstream branches from urbit/urbit and push to your personal urbit fork
by default.
Next, check out `test`, which is the mainline development branch, and
base a new branch on it to do your work on:
git checkout test
git checkout -b [branch name]
Now you are free to do your work on this branch. When finished, you may
want to clean up your commits:
git rebase -i test
Then you can push to your public fork with `git push` and make a pull
request via the GitHub UI. Make sure you request to merge your branch
into `test`, not `master`.
After your changes are merged upstream, you can delete your branch (via
github UI or `git push :[branch]` remotely, and with `git branch -d`
locally).
## Style
The urbit project uses two-space indentation and avoids tab characters.
In C code, it should not be too difficult to mimic the style of the code
around you, which is just fairly standard K&R with braces on every
compound statement. One thing to watch out for is top-level sections in
source files that are denoted by comments and are actually indented one
level.
Hoon will be a less familiar language to many contributors. Some of our
less obvious stylistic rules are:
- Keep your source files 80 characters or less wide. Many urbit
developers use 80 character terminals/tmux panes/&c.
- Tab characters are actually a syntax error, so be extra sure your
editor is not inserting any. Trailing whitespace is *usually* not a
syntax error, but avoiding it is encouraged.
- The kernel convention is that line comments start at column 57 with
the `::` followed by 2 spaces. This leaves 20 characters for the
comment. Outside the kernel, things are less strict.
- Tall arms within a core are conventionally separated by empty comments
(just `::`) at the same indentation level as the initial `++` or `+-`.
The last arm in a core is not followed by an empty comment, because it
is visually closed by the `--` that closes the core. The empty comment
is also sometimes omitted in data structure definitions.
## The kernel and pills
urbit bootstraps itself using a binary blob called `urbit.pill`, which
we do indeed keep in version control. This creates some special
requirements. If you are not changing anything in the kernel (everything
under `urb/zod/arvo/`) then you can skim this section (please do not
skip it entirely, though). If you *are* working there, then this
section is critically important!
The procedure for creating `urbit.pill` is often called "soliding". It
is somewhat similar to `|reset`, but instead of replacing your running
kernel, it writes the compiled kernel to a file. The command to solid
is, on a fakezod:
.urbit/pill +solid
When the compilation finishes, your `urbit.pill` will be found in the
`[pier]/.urb/put/` directory. Copy it into `urb/` and add it to your
commit.
The requirement here is that every commit that changes the kernel must
come with an `urbit.pill` built from the same code in `urb/zod/arvo/`
for that commit. (Only changing the actual Hoon code counts, so a change
to a jet with no corresponding Hoon change does not require a new pill.)
This is so that checking out an arbitrary revision and starting up a
fakezod actually works as expected. However you do this is fine, but I
like to do it as part of my committing process - just before `git
commit`, I fire up a new fakezod. This will use the previous
`urbit.pill`, but the kernel code in `%clay` will be copied from
`urb/zod/arvo/`, so `+solid` will compile it. Then I copy `urbit.pill`
into `urb/` and make my commit.
If you rebase or interactive rebase your commits, be sure to preserve
this property on all the commits you end up with. If multiple people
were collaborating on your branch, you may end up with conflicts in
`urbit.pill` and have to merge the branch into itself to resolve them.
Just do the same procedure to create a new, merged pill before
committing the merge. Otherwise, just make sure to use the correct
`urbit.pill` for each commit.
## Debug urbit with `gdb`
Follow the build instructions in README.md but run `make` with argument `DEBUG=yes`:
(If you've already built urbit first run `make clean`.)
make DEBUG=yes
Run `gdb`, while loading `bin/urbit` and its symbol table:
gdb bin/urbit
Set a breakpoint on `main()` (optional):
break main
Run your urbit comet `mycomet`:
run mycomet
Continue from the breakpoint on `main()`:
continue
## What to work on
If you are not thinking of contributing with a specific goal in mind,
the GitHub issue tracker is the first place you should look for ideas.
Issues are tagged with a priority and a difficulty. A good place to
start is on either a low-difficulty issue or a low-priority issue.
Higher priority issues are likely to be assigned to someone - if this is
the case, then contacting that person to coordinate before starting to
work is probably a good idea.
There is also a "help wanted" tag for things that we are especially
eager to have outside contributions on. Check here first!
## Staying in touch
The urbit developers communicate on urbit itself. Joining the
`~doznec/urbit-meta` channel on `talk` is highly recommended.
Subscribing to `urbit-dev` on Google Groups is also recommended, since
this is where continuity breach notifications are sent.
You can also contact one of the following people:
- Philip Monk
email: philip.monk@tlon.io
urbit: `~wictuc-folrex`
GitHub: [@philipcmonk](https://github.com/philipcmonk/)
- Raymond Pasco
email: ray@the.ug
urbit: `~ramtev-wisbyt`
GitHub: [@juped](https://github.com/juped/)

View File

@ -1,24 +0,0 @@
---
logo: black
sort: 2
title: Hoon
---
<div class="short">
# Hoon
Hoon is a strict, typed, pure functional language. This site is
served by an urbit written in Hoon.
If you're interested in learning the fundamentals of Hoon from
the bottom up, start with [Principles of
Hoon](hoon/principles).
If you want to jump into building things right away and prefer to
learn from the top down, check out [Leap into
Hoon](hoon/leap-in/1-basic).
Both of these are under active development.
</div>

View File

@ -1,8 +0,0 @@
---
hide: false
next: false
sort: 1
title: Leap into Hoon
---
<list></list>

View File

@ -1,421 +0,0 @@
---
logo: black
sort: 1
next: true
title: Basic Hoon
---
# Basic Hoon
Our goal is to get you programming interesting and useful things
as soon as possible. To get there we have to quickly cover some
of the fundamentals of hoon. To do this we'll walk through two
simple programs: the first [Project
Euler](https://projecteuler.net/) problem and
[fizzbuzz](https://en.wikipedia.org/wiki/Fizz_buzz).
To run this code, you'll need an urbit, and you'll need the
`%examples` desk from `~wactex-ribmex`. If you haven't installed
urbit yet, check out the [installation
instructions](http://urbit.org/docs/user/install). Once urbit is
intalled, take a look at the [basic
operation](http://urbit.org/docs/user/basic) of your urbit.
If you haven't pulled the examples desk from `~wactex-ribmex`, do
so now:
~fintud-macrep:dojo> |merge %examples ~wactex-ribmex %examples
>=
; ~wactex-ribmex is your neighbor
; ~wactex-ribmex is your neighbor
[time passes...]
merged with strategy %init
The merge could take several minutes; you'll know it's done when
"merged with strategy %init" is printed. Mount the new files to
your Unix pier directory:
~fintud-macrep:dojo> |mount /=examples=
Switch desks to run commands from the `%examples` desk:
~fintud-macrep:dojo> =dir /=examples=
=% /~fintud-macrep/examples/~2015.11.13..02.25.00..41e9/
Run an example:
~fintud-macrep:dojo> +euler1
233.168
## Euler 1
Let's check out the code for Euler 1. First, the problem:
```
If we list all the natural numbers below 10 that are multiples of
3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.
```
Here is the hoon solution (which should be in your pier directory
under `/examples/gen/euler1.hoon`):
```
:: project euler 1
:: https://projecteuler.net/problem=1
:: run in dojo with +euler1
::
:::: /hoon/euler1/gen
::
:- %say |= *
:- %noun
=< (sum 1.000)
::
:::: ~fintud-macrep
::
|%
++ three
|= a=@
=| b=@
|- ^- @u
?: (lth a b)
0
(add b $(b (add 3 b)))
++ five
|= a=@
=| b=@
|- ^- @
?: (lte a b)
0
?: =((mod b 3) 0)
$(b (add b 5))
(add b $(b (add b 5)))
++ sum
|= a=@u
(add (five a) (three a))
--
```
> Hoon is not generally whitespace sensitive, but we do have two
> different kinds of whitespace: a single space and a gap, which
> is two or more spaces or a linebreak. Tabs are taboo. Do not
> use them. Really. For a more detailed explanation of when to
> use spaces vs. gaps, see the syntax section before the first
> excercises.
### Lines 1-11:
Any line that begins with `::` is a comment.
:- %say |= *
:- %noun
=< (sum 1.000)
All you need to know about the lines above is that they call the
`++sum` function with an argument of `1.000`. We'll cover them in
more detail later.
### How to form expressions
Hoon does not use reserved words to form expressions. Instead,
expressions are formed with runes, which are diagraphs of two
ascii symbols. Each rune takes a specific number of
children--either expressions formed by other runes or literals
that produce their own value.
For example, the rune `?:` from line 17 is the classic
'if-then-else' statement, and thus takes three children:
?: (lth a b) :: if first child evals to true
0 :: then produce result of second
(add b $(b (add 3 b))) :: else, produce result of third
Since runes are such a fundamental structure in Hoon, we found
ourselves speaking them out loud frequently. It quickly grew
cumbersome to have to say "question mark, colon" to describe
`?:`. To alleviate this problem, we came up with our own naming
scheme: each ascii glyph has a single syllable pronunciation
phonetically designed to be both easily remembered and easily
pronounced in conjunction with the other glyphs (when forming a
rune).
See the entire naming schema below/or link to it:
```
ace [1 space] gal < pel (
bar | gap [>1 space, nl] per )
bas \ gar > sel [
buc $ hax # sem ;
cab _ hep - ser ]
cen % kel { soq '
col : ker } tar *
com , ket ^ tec `
doq " lus + tis =
dot . pam & wut ?
fas / pat @ zap !
```
Using our naming scheme `?:` is said 'wut col'.
### Lines 12-34
Now let's quickly walk through this code line-by-line. Lines
12-34 are wrapped in a `|%` (pronounced 'bar cen'), which
produces a core, a fundamental datatype in hoon similar to a
struct, class, or object. A core is just a map of names
to any kind of code, whether it be functions or data. Each
element in this map begins with a `++` followed by the name and
the corresponding code. Since `|%` takes an arbitrary number of
children, it needs to be closed with a `--`.
> `++` is not technically a rune, since it is only used in core
> syntax as shown above
Let's step into each of the three arms within our core.
### `++ sum`
++ sum
|= a=@
(add (five a) (three a))
--
`|=` produces a function, much like a lambda in lisp. It takes two children:
- A set of argument(s). In this case our argument set only
contains one: `a` which is required to be an atom or natural
number, denoted by `@`.
- The body of the function itself, which is executed when the
function is called (in this case, with `(sum 1.000)`). This
particular function adds the results of evaluating the gates `++
five` and `++three` with each of their respective input
parameters set to `a`.
### ++ three
++ three
|= a=@
=| b=@
|- ^- @u
?: (lth a b)
0
(add b $(b (add 3 b)))
As above, `++three` takes an integer argument, `a`, and then
executes the remainder of the code with `a` set to the actual
arguments.
Similarly, `=|` pushes its first child, `b` into our context (in
other words, it declares a variable `b`) and executes the
remainder of the code. However, `b` is not an argument; `=|`
sets `b` to the default value of whatever type it is declared as.
Since the default value of an atom is `0`, b is set to `0`.
So now we have two variables: `a` is set to our input, and `b` is
initialized to `0`.
The easiest way to think about `|-` that it lays down a recursion
point. More on this later.
`^-` is just a cast that sets the result of the remainder of the
code to an unsigned integer, `@u`.
In pseudocode, the last three lines read like this: if `a` is
less than `b`, produce zero. Else, add `b` to the result of
rerunning the segment of the function following the `|-` with the
value of `b` changed to `b` plus three.
The only thing that should look completely unfamiliar to you here
is the `$(b (add 3 b))`, which causes us to recurse back to our
last recursion point with the value of `b` set to `(add 3 b)`.
Note that we only specify what changes (`b` in this case). If
you recurse by an actual function call, then you have to specify
every argument.
> If you're familiar with Clojure, `|-` is `loop` and `$()` is
> recur.
## Excercises
Please tweak your code to complete the following excercises.
There are a few runes and some syntax that we have yet to cover that
you will need to complete the excercises below. For these, please
refer to our cheatsheat at the bottom.
1. Read and understand `++five` line by line.
2. Change `++sum` to accept two variables, `a` and `b`. Pass `a`
to three and `b` to five. Then run the code with `a` set to
`1.000` and b set to `2.000`.
3. Check if this new result is under one thousand. If it is,
return the string 'result is less than one thousand'. If not,
return 'result is greater than or equal to one thousand'.
```
Review
|% start core (collection of named ++ arms)
|= define function
=| define variable from type with default value
|- drop a recursion point
^- cast
?: if-then-else
=(a b) test equality
(function args ...) call function
New material
- :- make a cell of values. The irregular wide form of this is
[a b] with two expressions separated by a single space.
- Cords are one datatype for text in hoon. They're just a big
atom formed from adjacent unicode bytes -- a "c string". To
produce a cord enclose text within single quotes. To set the type
of an argument to a cord, use @t.
- There are two syntaxes for writing Hoon: tall form and wide
form.
In tall form, expressions are formed with either two spaces or
a line break separating both a rune from its children and each
of its children from one another. We use tall form when writing
multiline expressions.
For more concise expressions, we use wideform, which is always
a single line. Wideform can be used inside tall form
expressions, but not vice versa.
Wideform expressions are formed with a rune followed by ()
containing its children, all of which are separated by a
single space. For example to make a cell of two elements:
:-(a b)
We've already seen wideform in action, for example with
=((mod b 3) 0). In this case = is actually an irregular form
of .=, which tests its two children for equality.
Another irregular form is [a b] for :-(a b)
Surrounding a function with () is an irregular wide form
syntax for calling a function with n arguments.
```
## The subject
Now we're going to cover the boiler plate that we skimmed over
earlier.
:- %say |= *
:- %noun
=< (sum [1.000 2.000])
This program is a cell of two elements: the first, `%say`, tells
the interpreter what to produce--in this case a value.
The second element is `|=`, which we know produces a function.
`|=`'s first child is its argument(s), which in this case is any
noun (`*`). Its second child is the remainder of the program.
Similarly, the rest of the program is a cell of the literal
`%noun`, which tells the shell that we're producing a value of
type `noun`, and the second child contains the code that we run
to actually produce our value of the type `noun`.
`=<` is a rune that takes two children. The second child is the
context against which we run the first child. So in this case, we
are running the expression `(sum 1.000)` against everything
contained within the `|%`. In Hoon, we call the code executed the
"formula" and its context the "subject".
```
::::::::::::::::::::::::::::::
=< (sum 1.000) :: formula
::::::::::::::::::::::::::::::
|% ::
++ three ::
|= a=@ ::
=| b=@ ::
|- ^- @u ::
?: (lth a b) ::
0 ::
(add b $(b (add 3 b))) ::
::
++ five ::
|= a=@ :: subject
=| b=@ ::
|- ^- @ ::
?: (lte a b) ::
0 ::
?: =((mod b 3) 0) ::
$(b (add b 5)) ::
(add b $(b (add b 5))) ::
::
++ sum ::
|= a=@u ::
(add (five a) (three a)) ::
-- ::
::::::::::::::::::::::::::::::
```
In nearly every language there is a similar concept of a
"context" in which expressions are executed. For example, in C
this includes things like the call stack, stack variables, and so
on.
Hoon is unique in that this context is a first-class value.
Scheme allows a sort of reification of the context through
continutations, and some may see a parallel to Forth's stack, but
Hoon takes takes the concept one step further.
Our starting subject is the standard library, which is defined in
`/arvo/hoon.hoon` and `/arvo/zuse.hoon`. This is where functions
like `add` are defined. When we define a core with `|%`, we
don't throw away the subject (i.e. the standard library); rather,
we stack the new core on top of the old subject so that both are
accessible.
## Exercises:
4. Pass `++sum` its arguments (`2000` and `3000`) from the
commandline.
5. Comment out all of the arms of the `|%`. Now add another arm
and call it `++add`, have it accept two arguments and procduce
42 (regardless of input). Change the `=<` line to `[(add 5 7)
(^add 5 7)]`. Can you recognize what's happening?
6. Write fizbuzz:
Write a program that prints the numbers from 1 to 100
(entered from the command line). But for multiples of three
print 'Fizz' instead of the number and for the multiples of
five print 'Buzz'. For numbers which are multiples of both
three and five print 'FizzBuzz'.
Cheatsheet:
- To pass arguments from the command line to a program, you
replace the `*` in the first line of the boiler plate to
`[^ [[arg=TYPE ~] ~]]` where `TYPE` is replaced with the
type of argument you're expecting. Then `+euler1 a` from
the dojo sets `arg` to `a`.
- A list of strings is of type `(list ,@t)`, so the result of
the fizzbuzz function is of this type (hint: you'll need to
use `^-`)
- The empty list is `~`
- Lisp-style cons (construct a cell/prepend an element) is
`[new-element list]`
- For example, the first three positive integers are `[1 2 3
~]`
- `gte` tests whether `a` is greater than or equal to `b`.
- `mod` runs the modulo operation on two atoms.
- See the [basic math section]() for more info.

View File

@ -1,335 +0,0 @@
---
next: false
sort: 2
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
!:
|_ [bowl state=~]
++ poke-noun
|= arg=*
^- [(list) _+>.$]
~& [%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 with the following
commands:
```
~fintud-macrep:dojo> |start %echo
>=
~fintud-macrep:dojo> :echo 5
[%argument 5]
>=
~fintud-macrep:dojo> :echo [1 2]
[%argument [1 2]]
>=
```
> There is currently a bug where the `%argument` lines are
> printed *above* the line you entered, so your output may not
> look exactly like this.
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? Recall that `^-` casts to a
type. In this case, it's declaring that end result of the
function will be of type `[(list) _+>.$]`. But what does this
mean?
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, a move is arvo's equivalent of a syscall. 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, `~` (in the `[~ +>.$]`
line).
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".
Let's look at another example. Say we want to only accept a
number, and then print out the square of that number.
```
/? 314
!:
|_ [bowl state=~]
::
++ poke-atom
|= arg=@
^- [(list) _+>.$]
~& [%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, but accessible at the arvo
level. Each mark is defined in the `/mar` directory. Some marks
have conversion routines to other marks, and some have diff,
patch, 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`. Try the following
commands:
```
~fintud-macrep:dojo> |start %square
>=
~fintud-macrep:dojo> :square 6
gall: %square: no poke arm for noun
~fintud-macrep:dojo> :square &atom 6
[%square 36]
>=
```
> Recall the bug where `%square` may get printed above the input
> line.
Marks are powerful, and they're the backbone of urbit's data
pipeline, so we'll be getting quite used to them.
**Exercises**:
- Write an app that computes fizzbuzz on its input (as in the
previous section).
- One way of representing strings is with double quoted strings
called "tapes". The hoon type is `tape`, and there is a
corresponding mark with the same name. Write an app that
accepts a tape and prints out `(flop argument)`, where
`argument` is the input. What does this do?
Let's write our first network message! Here's `/ape/pong.hoon`:
```
/? 314
|%
++ move ,[bone term path *]
--
!:
|_ [bowl state=~]
::
++ poke-urbit
|= to=@p
^- [(list move) _+>.$]
[[[ost %poke /sending [to %pong] %atom 'howdy'] ~] +>.$]
::
++ poke-atom
|= arg=@
^- [(list move) _+>.$]
~& [%receiving (,@t arg)]
[~ +>.$]
::
++ coup |=(* [~ +>.$])
--
```
Run it with these commands:
```
~fintud-macrep:dojo> |start %pong
>=
~fintud-macrep:dojo> :pong &urbit ~sampel-sipnym
>=
```
Replace `~sampel-sipnym` with another urbit. Don't forget to
start the `%pong` app on that urbit too. You should see, on the
foreign urbit, this output:
```
[%receiving 'howdy']
```
Most of the code should be straightforward. In `++poke-atom`,
the only new thing is the expression `(,@t arg)`. As we already
know, `@t` is the type of "cord" text strings. `,` is an
operator that turns a type into a validator function -- that is,
a function whose domain is all nouns and range is the given type,
and which is identity when the domain is restricted to the given
type. In simpler terms, it's a function that coerces any value
to the given type. We call this `,@t` function on the argument.
This coerces the argument to text, so that we can print it out
prettily.
The more interesting part is in `++poke-urbit`. The `urbit` mark
is an urbit identity, and the hoon type associated with it is
`@p` (the "p" stands for "phonetic base").
Recall that in a `++poke` arm we produce "a list of moves and our
state". Until now, we've left the list of moves empty, since we
haven't wanted to tell arvo to do anything in particular. Now we
want to send a message to another urbit. Thus, we produce a list
with one element:
```
[ost %poke /sending [to %pong] %atom 'howdy']
```
The general form of a move is
`[bone term path *]`
If you look up `++bone` in `hoon.hoon`, you'll see that it's a
number (`@ud`), and that it's an opaque reference to a duct.
`++duct` in hoon.hoon is a list of `wire`s, where `wire` is an
alias for `path`. `++path` is a list of `span`s, which are ASCII
text. Thus, a duct is a list of paths, and a bone is an opaque
reference to that duct (in the same way that a Unix file
descriptor is an opaque reference to a file structure). Thus,
the center of all this is the concept of a "duct".
A duct is stack of causes, represented as paths. At the bottom
of every duct is a unix event, such as a keystroke, network
packet, file change, or timer event. When arvo is given this
event, it routes the event to appropriate kernel module for
handling.
Sometimes, the module can immediately handle the event and
produce any necessary results. Otherwise, it asks other kernel
modules or applications to do certain things, and produces the
result from that. When it sends a message to another kernel
module or application, it sends it "along" the duct it was given,
plus with a new path. Arvo pushes the new path onto the duct.
Now the duct has two entries, with the unix even on the bottom
and the kernel module that handled it next. This process can
continue indefinitely, adding more and more layers onto the duct.
When an entity produces a result, a layer is popped off the duct.
In effect, a duct is an arvo-level call stack. The duct system
creates a structured message-passing system. It's worth noting
that while in traditional call stacks a function call happens
synchronously and returns exactly once, in arvo multiple moves
can be sent at once, they are evaluated asynchronously, and each
one may be responded to zero or more times.
Anyhow, the point is that whatever caused `++poke-urbit` to be
called is also the root cause for the network message we're
trying to send. Thus, we say to send the network message along
the given bone `ost`. Of course, we have to push a layer to the
duct. This layer can have any data we want in it, but we don't
need anything specific here, so we just use `/sending`. If we
were expecting a response (which we're not), it would come back
along the `/sending` path. It's a good idea for debugging
purposes to make the path human-readable, but it's not necessary.
Looking back at the general form of a move, there is a `term`,
which in this case is `%poke`. This is the name of the
particular kind of move we're sending. If you think of a move as
a syscall (which you should), then this `term` is the name of the
syscall. Common ones include: `%poke`, to message an app;
`%warp`, to read from the filesystem; `%wait`, to set a timer;
and `%them`, to send an http request.
The general form ends with `*` since each type of move takes
different data. In our case, a `%poke` move takes a target
(urbit and app) and marked data and pokes that app on that urbit
with that data. `[to %pong]` is the target urbit and app,
`%atom` is the mark`, and `'howdy'` is the data.
When arvo receives a `%poke` move, it calls the appropriate
`++poke`. The same mechanism is used for sending messages
between apps on the same urbit as for sending messages between
apps on different urbits.
> We said earlier that we're not expecting a response. This is
> not entirely true: the `++coup` is called when we receive
> acknowledgment that the `++poke` was called. We don't do
> anything with this information right now, but we could.
**Exercises**:
- Extend either of the apps in the first two exercises to accept
input over the network in the same way as `pong`.
- Modify `pong` to print out a message when it receives an ack.
- Write two apps, `even` and `odd`. When you pass an atom to
`even`, check whether it's even. If so, divide it by two and
recurse; otherwise, poke `odd` with it. When `odd` recieves
an atom, check whether it's equal to one. If so, terminate,
printing "%success". Otherwise, check whether it's odd. If
so, multiply it by three, add one, and recurse; otherwise, poke
`even` with it. multiply it by three and add one. When either
app receives a number, print it out along with the name of the
app. In the end, you should be able to watch Collatz's
conjecture play out between the two apps. Sample output:
```
~fintud-macrep:dojo> :even &atom 18
[%even 18]
[%odd 9]
[%even 28]
[%even 14]
[%odd 7]
[%even 22]
[%odd 11]
[%even 34]
[%odd 17]
[%even 52]
[%even 26]
[%odd 13]
[%even 40]
[%even 20]
[%even 10]
[%odd 5]
[%even 16]
[%even 8]
[%even 4]
[%even 2]
%success
```
- Put `even` and `odd` on two separate ships and pass the
messages over the network.

View File

@ -1,55 +0,0 @@
---
hide: true
next: false
sort: 3
title: Advanced Applications
---
XXX PLACEHOLDER
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.

View File

@ -1,7 +0,0 @@
Library
========
<list dataPreview="true" titlesOnly="true"></list>
<search/>

View File

@ -1,37 +0,0 @@
volume 0, Kelvin Versioning.
===========================
### `++hoon`
++ hoon %164 :: version stub
Declares the current Hoon version number in degrees Kelvin.
When normal people release normal software, they count by fractions, and
they count up. Thus, they can keep extending and revising their systems
incrementally. This is generally considered a good thing. It generally
is.
In some cases, however, specifications needs to be permanently frozen.
This requirement is generally found in the context of standards. Some
standards are extensible or versionable, but some are not. ASCII, for
instance, is perma-frozen. So is IPv4 (its relationship to IPv6 is
little more than nominal - if they were really the same protocol, they'd
have the same ethertype). Moreover, many standards render themselves
incompatible in practice through excessive enthusiasm for extensibility.
They may not be perma-frozen, but they probably should be.
The true, Martian way to perma-freeze a system is what I call Kelvin
versioning. In Kelvin versioning, releases count down by integer degrees
Kelvin. At absolute zero, the system can no longer be changed. At 1K,
one more modification is possible. And so on. For instance, Nock is at
5K. It might change, though it probably won't. Nouns themselves are at
0K - it is impossible to imagine changing anything about their three
sentence definition.
------------------------------------------------------------------------
~zod/try=> stub
164
------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@ -1,450 +0,0 @@
chapter 2a, basic unsigned math
===============================
### `++add`
Add
++ add :: add
~/ %add
|= [a=@ b=@]
^- @
?: =(0 a) b
$(a (dec a), b +(b))
::
Produces the sum of `a` and `b` as an atom.
`a` is an [atom]().
`b` is an [atom]().
~zod/try=> (add 2 2)
4
~zod/try=> (add 1 1.000.000)
1.000.001
~zod/try=> (add 1.333 (mul 2 2))
1.337
------------------------------------------------------------------------
### `++cap`
Tree head
++ cap :: tree head
~/ %cap
|= a=@
^- ?(%2 %3)
?- a
%2 %2
%3 %3
?(%0 %1) !!
* $(a (div a 2))
==
::
Tests whether an `a` is in the head or tail of a noun. Produces the
[cube]() `%2` if it is within the head, or the [cube]() `%3` if is is
within the tail.
`a` is an [atom]().
~zod/try=> (cap 4)
%2
~zod/try=> (cap 6)
%3
~zod/try=> (cap (add 10 9))
%2
------------------------------------------------------------------------
### `++dec`
Decrement
++ dec :: decrement
~/ %dec
|= a=@
~| %decrement-underflow
?< =(0 a)
=+ b=0
|- ^- @
?: =(a +(b)) b
$(b +(b))
::
Produces `a-1` as an atom.
`a` is an [atom]().
~zod/try=> (dec 7)
6
~zod/try=> (dec 0)
! decrement-underflow
! exit
------------------------------------------------------------------------
### `++div`
Divide
++ div :: divide
~/ %div
|= [a=@ b=@]
^- @
~| 'div'
?< =(0 b)
=+ c=0
|-
?: (lth a b) c
$(a (sub a b), c +(c))
::
Computes `a` divided by `b`, producing an atom.
`a` is an [atom]().
`b` is an [atom]().
~zod/try=> (div 4 2)
2
~zod/try=> (div 17 8)
2
~zod/try=> (div 20 30)
0
------------------------------------------------------------------------
### `++fac`
Factorial
++ fac :: factorial
~/ %fac
|= a=@
^- @
?: =(0 a) 1
(mul a $(a (dec a)))
::
Computes the factorial of `a`, producing an atom.
`a` is an [atom]().
~zod/try=> (fac 3)
6
~zod/try=> (fac 0)
1
~zod/try=> (fac 11)
39.916.800
------------------------------------------------------------------------
### `++gte`
Greater-than/equal
++ gte :: greater-equal
~/ %gte
|= [a=@ b=@]
^- ?
!(lth a b)
::
Tests whether `a` is greater than a number `b`, producing a loobean.
`a` is an [atom]().
`b` is an [atom]().
~zod/try=> (gte 100 10)
%.y
~zod/try=> (gte 4 4)
%.y
~zod/try=> (gte 3 4)
%.n
------------------------------------------------------------------------
### `++gth`
Greater-than
++ gth :: greater-than
~/ %gth
|= [a=@ b=@]
^- ?
!(lte a b)
::
Tests whether `a` is greater than `b`, producing a loobean.
`a` is an [atom]().
`b` is an [atom]().
~zod/try=> (gth 'd' 'c')
%.y
~zod/try=> (gth ~h1 ~m61)
%.n
------------------------------------------------------------------------
### `++lte`
Less-than/equal
++ lte :: less-equal
~/ %lte
|= [a=@ b=@]
|(=(a b) (lth a b))
::
Tests whether `a` is less than or equal to `b`, producing a loobean.
`a` is an [atom]().
`b` is an [atom]().
~zod/try=> (lte 4 5)
%.y
~zod/try=> (lte 5 4)
%.n
~zod/try=> (lte 5 5)
%.y
~zod/try=> (lte 0 0)
%.y
------------------------------------------------------------------------
### `++lth`
Less-than
++ lth :: less-than
~/ %lth
|= [a=@ b=@]
^- ?
?& !=(a b)
|-
?| =(0 a)
?& !=(0 b)
$(a (dec a), b (dec b))
== == ==
::
Tests whether `a` is less than `b`, producing a loobean.
`a` is an [atom]().
`b` is an [atom]().
~zod/try=> (lth 4 5)
%.y
~zod/try=> (lth 5 4)
%.n
~zod/try=> (lth 5 5)
%.n
~zod/try=> (lth 5 0)
%.n
------------------------------------------------------------------------
### `++mas`
Axis within head/tail
++ mas :: tree body
~/ %mas
|= a=@
^- @
?- a
1 !!
2 1
3 1
* (add (mod a 2) (mul $(a (div a 2)) 2))
==
::
Computes the axis of `a` within the head or the tail, producing an atom.
`a` is an [atom]().
~zod/try=> (mas 3)
1
~zod/try=> (mas 4)
2
~zod/try=> (mas 5)
3
~zod/try=> (mas 6)
2
~zod/try=> (mas 0)
! exit
~zod/try=> (mas 1)
! exit
------------------------------------------------------------------------
### `++max`
Maximum
++ max :: maximum
~/ %max
|= [a=@ b=@]
^- @
?: (gth a b) a
b
::
Computes the maximum of `a` and `b`, producing an atom.
`a` is an [atom]().
`b` is an [atom]().
~zod/try=> (max 10 100)
100
~zod/try=> (max 10.443 9)
10.443
~zod/try=> (max 0 1)
1
------------------------------------------------------------------------
### `++min`
Minimum
++ min :: minimum
~/ %min
|= [a=@ b=@]
^- @
?: (lth a b) a
b
::
Computes the minimum of `a` and `b`, producing an atom.
`a` is an [atom]().
`b` is an [atom]().
~zod/try=> (min 10 100)
10
~zod/try=> (min 10.443 9)
9
~zod/try=> (min 0 1)
0
------------------------------------------------------------------------
### `++mod`
Modulus
++ mod :: remainder
~/ %mod
|= [a=@ b=@]
^- @
?< =(0 b)
(sub a (mul b (div a b)))
::
Computes the remainder of dividing `a` by `b`, producing an atom.
`a` is an [atom]().
`b` is an [atom]().
------------------------------------------------------------------------
### `++mul`
Multiply
++ mul :: multiply
~/ %mul
|= [a=@ b=@]
^- @
=+ c=0
|-
?: =(0 a) c
$(a (dec a), c (add b c))
::
Multiplies `a` by `b`, producing an atom.
`a` is an [atom]().
`b` is an [atom]().
~zod/try=> (mul 3 4)
12
~zod/try=> (mul 0 1)
0
------------------------------------------------------------------------
### `++peg`
Axis within axis
++ peg :: tree connect
~/ %peg
|= [a=@ b=@]
^- @
?- b
1 a
2 (mul a 2)
3 +((mul a 2))
* (add (mod b 2) (mul $(b (div b 2)) 2))
==
::
Computes the axis of `b` within axis `a`, producing an atom.
`a` is an [atom]().
`b` is an [atom]().
~zod/try=> (peg 4 1)
4
~zod/try=> (peg 4 2)
8
~zod/try=> (peg 8 45)
269
------------------------------------------------------------------------
### `++sub`
Subtract
++ sub :: subtract
~/ %sub
|= [a=@ b=@]
~| %subtract-underflow
^- @
?: =(0 b) a
$(a (dec a), b (dec b))
Subtracts `b` from `a`, producing an atom.
`a` is an [atom]().
`b` is an [atom]().
~zod/try=> (sub 10 5)
5
~zod/try=> (sub 243 44)
199
~zod/try=> (sub 5 0)
5
~zod/try=> (sub 0 5)
! subtract-underflow
! exit
------------------------------------------------------------------------

View File

@ -1,907 +0,0 @@
chapter 2b, basic containers
============================
Section 2bA, units
------------------
### `++biff`
Unit as argument
++ biff :: apply
|* [a=(unit) b=$+(* (unit))]
?~ a ~
(b u.a)
Applies a gate that produces a unit, `b`, to the value (`u.a`) of a unit
`a`. If `a` is empty, `~` is produced.
`a` is a [unit]().
`b` is a [gate]() that accepts a noun and produces a unit.
~zod/try=> (biff (some 5) |=(a=@ (some (add a 2))))
[~ u=7]
~zod/try=> (biff ~ |=(a=@ (some (add a 2))))
~
------------------------------------------------------------------------
### `++bind`
Bind
++ bind :: argue
|* [a=(unit) b=gate]
?~ a ~
[~ u=(b u.a)]
Applies a function `b` to the value (`u.a`) of a unit `a`, producing a
unit.
`a` is a [unit]()
`b` is a [gate]().
~zod/try=> (bind ((unit ,@) [~ 97]) ,@t)
[~ `a`]
~zod/try=> =a |=(a=@ (add a 1))
~zod/try=> (bind ((unit ,@) [~ 2]) a)
[~ 3]
------------------------------------------------------------------------
### `++bond`
Replace null
++ bond :: replace
|* a=trap
|* b=(unit)
?~ b $:a
u.b
Replaces an empty unit `b` with the product of a kicked trap `a`. If the
unit is not empty, then the original unit is produced.
`a` is a [trap]().
`b` is a [unit]().
~zod/try=> (bex 10)
1.024
~zod/try=> ((bond |.((bex 10))) ~)
1.024
~zod/try=> ((bond |.((bex 10))) (slaw %ud '123'))
123
------------------------------------------------------------------------
### `++both`
Group unit values
++ both :: all the above
|* [a=(unit) b=(unit)]
?~ a ~
?~ b ~
[~ u=[u.a u.b]]
Produces a unit whose value is a cell of the values of two input units
`a` and `b`. If either of the two units are empty, `~` is produced.
`a` is a [unit]().
`b` is a [unit]().
~zod/try=> (both (some 1) (some %b))
[~ u=[1 %b]]
~zod/try=> (both ~ (some %b))
~
------------------------------------------------------------------------
### `++clap`
Apply gate to two units
++ clap :: combine
|* [a=(unit) b=(unit) c=_|=(^ +<-)]
?~ a b
?~ b a
[~ u=(c u.a u.b)]
Applies a binary operation `c` which produces a unit to the values of
two units `a` and `b`.
`a` is a [unit]().
`b` is a [unit]().
`c` is a [gate]() that performs a binary operation.
~zod/try=> =u ((unit ,@t) [~ 'a'])
~zod/try=> =v ((unit ,@t) [~ 'b'])
~zod/try=> (clap u v |=([a=@t b=@t] (welp (trip a) (trip b))))
[~ u="ab"]
~zod/try=> =a ((unit ,@u) [~ 1])
~zod/try=> =b ((unit ,@u) [~ 2])
~zod/try=> =c |=([a=@ b=@] (add a b))
~zod/try=> (clap a b c)
[~ 3]
------------------------------------------------------------------------
### `++drop`
Unit list
++ drop :: enlist
|* a=(unit)
?~ a ~
[i=u.a t=~]
Produces a [list]() of the value from a unit `a`.
`a` is a [unit]().
~zod/try=> =a ((unit ,@) [~ 97])
~zod/try=> (drop a)
[i=97 t=~]
~zod/try=> =a ((unit ,@) [~])
~zod/try=> (drop a)
~
------------------------------------------------------------------------
### `++fall`
Default unit
++ fall :: default
|* [a=(unit) b=*]
?~(a b u.a)
Produces a default value `b` for a unit `a` in cases where the unit is
null.
`a` is a [unit]().
`b` is a [noun]() used as the default value.
~zod/try=> (fall ~ `a`)
`a`
~zod/try=> (fall [~ u=0] `a`)
0
------------------------------------------------------------------------
### `++lift`
Fmap
++ lift :: lift gate (fmap)
|* a=gate :: flipped
|* b=(unit) :: curried
(bind b a) :: bind
Similar to `fmap` in Haskell: accepts a gate `a` that accepts and
produces an unwrapped value, passes it the value of a unit `b`, and then
produces a unit value.
`a` is a [gate]().
`b` is a [unit]().
~zod/try=> ((lift dec) `(unit ,@)`~)
~
~zod/try=> ((lift dec) `(unit ,@)`[~ 20])
[~ 19]
------------------------------------------------------------------------
### `++mate`
Choose
++ mate :: choose
|* [a=(unit) b=(unit)]
?~ b a
?~ a b
?.(=(u.a u.b) ~|('mate' !!) a)
Accepts two units `a` and `b` whose values are expected to be
equivalent. If either is empty, then the value of the other is produced.
If neither are empty, it asserts that both values are the same and
produces that value. If the assertion fails, `++mate` crashes with
`'mate'` in the stack trace.
`a` is a [unit]().
`b` is a [unit]().
~zod/try=> =a ((unit ,@) [~ 97])
~zod/try=> =b ((unit ,@) [~ 97])
~zod/try=> (mate a b)
[~ 97]
~zod/try=> =a ((unit ,@) [~ 97])
~zod/try=> =b ((unit ,@) [~])
~zod/try=> (mate a b)
[~ 97]
~zod/try=> =a ((unit ,@) [~ 97])
~zod/try=> =b ((unit ,@) [~ 98])
~zod/try=> (mate a b)
! 'mate'
! exit
------------------------------------------------------------------------
### `++need`
Unwrap
++ need :: demand
|* a=(unit)
?~ a !!
u.a
Retrieve the value from a unit and crash if the unit is null.
`a` is a [unit]().
~zod/try=> =a ((unit ,[@t @t]) [~ ['a' 'b']])
~zod/try=> (need a)
['a' 'b']
~zod/try=> =a ((unit ,@ud) [~ 17])
~zod/try=> (need a)
17
~zod/try=> =a ((unit ,@) [~])
~zod/try=> (need a)
! exit
------------------------------------------------------------------------
### `++some`
Unify
++ some :: lift (pure)
|* a=*
[~ u=a]
Takes any atom `a` and produces a unit with the value set to `a`.
`a` is a [noun]().
~zod/try=> (some [`a` `b`])
[~ u=[`a` `b`]]
~zod/try=> (some &)
[~ u=%.y]
------------------------------------------------------------------------
section 2bB, lists
------------------
### `++flop`
Reverse
++ flop :: reverse
~/ %flop
|* a=(list)
=> .(a (homo a))
^+ a
=+ b=`_a`~
|-
?~ a b
$(a t.a, b [i.a b])
Produces the list `a` in reverse order.
`a` is a [list]().
~zod/try=> =a (limo [1 2 3 ~])
~zod/try=> (flop a)
~[3 2 1]
------------------------------------------------------------------------
### `++homo`
Homogenize
++ homo :: homogenize
|* a=(list)
^+ =< $
|% +- $ ?:(_? ~ [i=(snag 0 a) t=$])
--
a
Produces a list whose type is a fork of all the contained types in the
list `a`.
`a` is a [list]().
~zod/try=> lyst
[i=1 t=[i=97 t=[i=2 t=[i=98 t=[i=[~ u=10] t=~]]]]]
~zod/try=> (homo lyst)
~[1 97 2 98 [~ u=10]]
~zod/try=> =a (limo [1 2 3 ~])
~zod/try=> a
[i=1 t=[i=2 t=[i=3 t=~]]]
~zod/try=> (homo a)
~[1 2 3]
------------------------------------------------------------------------
### `++limo`
List Constructor
++ limo :: listify
|* a=*
^+ =< $
|% +- $ ?~(a ~ ?:(_? i=-.a t=$ $(a +.a)))
--
a
Turns a null-terminated tuple into a list.
`a` is a null-terminated tuple.
~zod/try=> (limo [1 2 3 ~])
[i=1 t=[i=2 t=[i=3 t=~]]]
------------------------------------------------------------------------
### `++lent`
List length
++ lent :: length
~/ %lent
|= a=(list)
^- @
=+ b=0
|-
?~ a b
$(a t.a, b +(b))
Produces the length of any list `a` as an atom.
`a` is a [list]().
~zod/try=> (lent (limo [1 2 3 4 ~]))
4
~zod/try=> (lent (limo [1 'a' 2 'b' (some 10) ~]))
5
------------------------------------------------------------------------
### `++levy`
"and" to list
++ levy
~/ %levy :: all of
|* [a=(list) b=_|=(p=* .?(p))]
|- ^- ?
?~ a &
?. (b i.a) |
$(a t.a)
Produces the Boolean "and" of the result of every element in list `a`
passed to gate `b`.
`a` is a [list]().
`b` is a [gate]().
~zod/try=> =a |=(a=@ (lte a 1))
~zod/try=> (levy (limo [0 1 2 1 ~]) a)
%.n
~zod/try=> =a |=(a=@ (lte a 3))
~zod/try=> (levy (limo [0 1 2 1 ~]) a)
%.y
------------------------------------------------------------------------
### `++lien`
"or" to list
++ lien :: some of
~/ %lien
|* [a=(list) b=$+(* ?)]
|- ^- ?
?~ a |
?: (b i.a) &
$(a t.a)
Produces the Boolean "or" of the result of every element in list `a`
passed to gate `b`.
`a` is a [list]().
`b` is a [gate]().
~zod/try=> =a |=(a=@ (gte a 1))
~zod/try=> (lien (limo [0 1 2 1 ~]) a)
%.y
~zod/try=> =a |=(a=@ (gte a 3))
~zod/try=> (lien (limo [0 1 2 1 ~]) a)
%.n
------------------------------------------------------------------------
### `++murn`
Maybe transform
++ murn :: maybe transform
|* [a=(list) b=$+(* (unit))]
|-
?~ a ~
=+ c=(b i.a)
?~ c
$(a t.a)
[i=u.c t=$(a t.a)]
Passes each member of list `a` to gate `b`, which must produce a unit.
Produces a new list with all the results that do not produce `~`.
`a` is a [list]().
`b` is a [gate]() that produces a [unit]().
~zod/try=> =a |=(a=@ ?.((gte a 2) ~ (some (add a 10))))
~zod/try=> (murn (limo [0 1 2 3 ~]) a)
[i=12 t=[i=13 t=~]]
------------------------------------------------------------------------
### `++reap`
Replicate
++ reap :: replicate
|* [a=@ b=*]
|- ^- (list ,_b)
?~ a ~
[b $(a (dec a))]
Replicate: produces a list containing `a` copies of `b`.
`a` is an [atom]()
`b` is a [noun]()
~zod/try=> (reap 20 %a)
~[%a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a]
~zod/try=> (reap 5 ~s1)
~[~s1 ~s1 ~s1 ~s1 ~s1]
~zod/try=> `@dr`(roll (reap 5 ~s1) add)
~s5
------------------------------------------------------------------------
### `++reel`
Right fold
++ reel :: right fold
~/ %reel
|* [a=(list) b=_|=([* *] +<+)]
|- ^+ +<+.b
?~ a
+<+.b
(b i.a $(a t.a))
Right fold: moves right to left across a list `a`, recursively slamming
a binary gate `b` with an element from `a` and an accumulator, producing
the final value of the accumulator.
`a` is a [list]().
`b` is a binary [gate]().
~zod/try=> =sum =|([p=@ q=@] |.((add p q)))
~zod/try=> (reel (limo [1 2 3 4 5 ~]) sum)
15
~zod/try=> =a =|([p=@ q=@] |.((sub p q)))
~zod/try=> (reel (limo [6 3 1 ~]) a)
4
~zod/try=> (reel (limo [3 6 1 ~]) a)
! subtract-underflow
! exit
------------------------------------------------------------------------
### `++roll`
Left fold
++ roll :: left fold
~/ %roll
|* [a=(list) b=_|=([* *] +<+)]
|- ^+ +<+.b
?~ a
+<+.b
$(a t.a, b b(+<+ (b i.a +<+.b)))
Left fold: moves left to right across a list `a`, recursively slamming a
binary gate `b` with an element from the list and an accumulator,
producing the final value of the accumulator.
`a` is a [list]().
`b` is a binary [gate]().
~zod/try=> =sum =|([p=@ q=@] |.((add p q)))
~zod/try=> (roll (limo [1 2 3 4 5 ~]) sum)
q=15
~zod/try=> =a =|([p=@ q=@] |.((sub p q)))
~zod/try=> (roll (limo [6 3 1 ~]) a)
! subtract-underflow
! exit
~zod/try=> (roll (limo [1 3 6 ~]) a)
q=4
------------------------------------------------------------------------
### `++skid`
Separate
++ skid :: separate
|* [a=(list) b=$+(* ?)]
|- ^+ [p=a q=a]
?~ a [~ ~]
=+ c=$(a t.a)
?:((b i.a) [[i.a p.c] q.c] [p.c [i.a q.c]])
Seperates a list `a` into two lists - Those elements of `a` who produce
true when slammed to gate `b` and those who produce `%.n`.
`a` is a [list]().
`b` is a [gate]() that accepts one argument and produces a loobean.
~zod/try=> =a |=(a=@ (gth a 1))
~zod/try=> (skid (limo [0 1 2 3 ~]) a)
[p=[i=2 t=[i=3 t=~]] q=[i=0 t=[i=1 t=~]]]
------------------------------------------------------------------------
### `++skim`
Suffix
++ skim :: only
~/ %skim
|* [a=(list) b=_|=(p=* .?(p))]
|-
^+ a
?~ a ~
?:((b i.a) [i.a $(a t.a)] $(a t.a))
Cycles through the members of a list `a`, passing them to a gate `b` and
producing a list of all of the members that produce `%.y`. Inverse of
`++skip`.
`a` is a [list]().
`b` is a [gate]() that accepts one argument and produces a loobean.
~zod/try=> =a |=(a=@ (gth a 1))
~zod/try=> (skim (limo [0 1 2 3 ~]) a)
[i=2 t=[i=3 t=~]]
------------------------------------------------------------------------
### `++skip`
Except
++ skip :: except
~/ %skip
|* [a=(list) b=_|=(p=* .?(p))]
|-
^+ a
?~ a ~
?:((b i.a) $(a t.a) [i.a $(a t.a)])
Cycles through the members of a list `a`, passing them to a gate `b` and
producing a list of all of the members that produce `%.n`. Inverse of
`++skim`.
`a` is a [list]().
`b` is a [gate]() that accepts one argument and produces a loobean.
~zod/try=> =a |=(a=@ (gth a 1))
~zod/try=> (skip (limo [0 1 2 3 ~]) a)
[i=0 t=[i=1 t=~]]
------------------------------------------------------------------------
### `++scag`
Prefix
++ scag :: prefix
~/ %scag
|* [a=@ b=(list)]
|- ^+ b
?: |(?=(~ b) =(0 a)) ~
[i.b $(b t.b, a (dec a))]
Accepts an atom `a` and list `b`, producing the first `a` elements of
the front of the list.
`a` is an [atom]().
`b` is a [list]().
~zod/try=> (scag 2 (limo [0 1 2 3 ~]))
[i=0 t=[i=1 t=~]]
~zod/try=> (scag 10 (limo [1 2 3 4 ~]))
[i=1 t=[i=2 t=[i=3 t=[i=4 t=~]]]]
------------------------------------------------------------------------
### `++slag`
Suffix
++ slag :: suffix
~/ %slag
|* [a=@ b=(list)]
|- ^+ b
?: =(0 a) b
?~ b ~
$(b t.b, a (dec a))
Accepts an atom `a` and list `b`, producing the remaining elements from
`b` starting at `a`.
`a` is an [atom]().
`b` is a [list]().
~zod/try=> (slag 2 (limo [1 2 3 4 ~]))
[i=3 t=[i=4 t=~]]
~zod/try=> (slag 1 (limo [1 2 3 4 ~]))
[i=2 t=[i=3 t=[i=4 t=~]]]
------------------------------------------------------------------------
### `++snag`
Index
++ snag :: index
~/ %snag
|* [a=@ b=(list)]
|-
?~ b
~|('snag-fail' !!)
?: =(0 a) i.b
$(b t.b, a (dec a))
Accepts an atom `a` and a list `b`, producing the element at the index
of `a`and failing if the list is null. Lists are 0-indexed.
`a` is an [atom]().
`b` is a [list]().
~zod/try=> (snag 2 "asdf")
~~d
~zod/try=> (snag 0 `(list ,@ud)`~[1 2 3 4])
1
------------------------------------------------------------------------
### `++sort`
Quicksort
++ sort :: quicksort
~/ %sort
|* [a=(list) b=$+([* *] ?)]
=> .(a ^.(homo a))
|- ^+ a
?~ a ~
%+ weld
$(a (skim t.a |=(c=_i.a (b c i.a))))
^+ t.a
[i.a $(a (skim t.a |=(c=_i.a !(b c i.a))))]
Quicksort: accepts a list `a` and a gate `b` which accepts two nouns and
produces a loobean. `++sort` then produces a list of the elements of `a`
sorted according to `b`.
`a` is an [atom]().
`b` is a [gate]() which accepts two nouns and produces a loobean.
~zod/try=> =a =|([p=@ q=@] |.((gth p q)))
~zod/try=> (sort (limo [0 1 2 3 ~]) a)
~[3 2 1 0]
------------------------------------------------------------------------
### `++swag`
Infix
++ swag :: infix
|* [[a=@ b=@] c=(list)]
(scag b (slag a c))
Similar to `substr` in JavaScript: extracts a string infix, beginning at
inclusive index `a`, producing `b` number of characters.
`a` and `b` are [atom]()s.
`c` is a [list]().
~zod/try=> (swag [2 5] "roly poly")
"ly po"
~zod/try=> (swag [2 2] (limo [1 2 3 4 ~]))
[i=3 t=[i=4 t=~]]
------------------------------------------------------------------------
### `++turn`
Gate to list
++ turn :: transform
~/ %turn
|* [a=(list) b=_,*]
|-
?~ a ~
[i=(b i.a) t=$(a t.a)]
Accepts a list `a` and a gate `b`. Produces a list with the gate applied
to each element of the original list.
`a` is a [list]().
`b` is a [gate]().
~zod/try=> (turn (limo [104 111 111 110 ~]) ,@t)
<|h o o n|>
~zod/try=> =a |=(a=@ (add a 4))
~zod/try=> (turn (limo [1 2 3 4 ~]) a)
~[5 6 7 8]
------------------------------------------------------------------------
### `++weld`
Concatenate
++ weld :: concatenate
~/ %weld
|* [a=(list) b=(list)]
=> .(a ^.(homo a), b ^.(homo b))
|- ^+ b
?~ a b
[i.a $(a t.a)]
Concatenate two lists `a` and `b`.
`a` and `b` are [list]()s.
~zod/try=> (weld "urb" "it")
~[~~u ~~r ~~b ~~i ~~t]
~zod/try=> (weld (limo [1 2 ~]) (limo [3 4 ~]))
~[1 2 3 4]
------------------------------------------------------------------------
### `++welp`
Perfect weld
++ welp :: perfect weld
=| [* *]
|%
+- $
?~ +<-
+<-(. +<+)
+<-(+ $(+<- +<->))
--
Concatenate two lists `a` and `b` without losing their type information
to homogenization.
`a` and `b` are [list]()s.
~zod/try=> (welp "foo" "bar")
"foobar"
~zod/arvo=/hoon/hoon> (welp ~[60 61 62] ~[%a %b %c])
[60 61 62 %a %b %c ~]
~zod/arvo=/hoon/hoon> :type; (welp ~[60 61 62] ~[%a %b %c])
[60 61 62 %a %b %c ~]
[@ud @ud @ud %a %b %c %~]
~zod/arvo=/hoon/hoon> (welp [sa/1 so/2 ~] si/3)
[[%sa 1] [%so 2] %si 3]
------------------------------------------------------------------------
### `++wild`
XXDELETE
++ wild :: concatenate
|* [a=(list) b=(list)]
=> .(a ^.(homo a), b ^.(homo b))
|-
?~ a b
[i=i.a $(a t.a)]
Concatenates two lists `a` and `b`, homogenizing their types
individually.
`a` and `b` are [list]()s.
~zod/try=> (wild (limo ~[1 2 3]) (limo [4]~))
~[1 2 3 4]
~zod/try=> (wild (limo 60 61 62 ~) (limo %a %b %c ~))
[i=60 [i=61 [i=62 ~[%a %b %c]]]]
~zod/try=> (weld (limo 60 61 62 ~) (limo %a %b %c ~))
! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[10.000 15].[10.016 57]>
! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[10.001 15].[10.016 57]>
! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[10.002 15].[10.016 57]>
! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[10.004 15].[10.016 57]>
! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[10.006 15].[10.016 57]>
! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[10.006 29].[10.006 44]>
! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[10.056 3].[10.061 13]>
! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[10.058 3].[10.061 13]>
! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[10.059 3].[10.061 13]>
! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[10.060 5].[10.060 47]>
! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[9.826 7].[9.844 35]>
! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[9.827 7].[9.844 35]>
! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[9.827 11].[9.838 13]>
! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[9.828 11].[9.838 13]>
! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[9.829 13].[9.831 47]>
! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[9.830 13].[9.831 47]>
! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[9.706 7].[9.712 25]>
! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[9.707 7].[9.712 25]>
! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[9.708 7].[9.712 25]>
! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[9.712 7].[9.712 25]>
! /~zod/arvo/~2014.10.2..22.58.23..5af9/hoon/:<[9.712 8].[9.712 25]>
! exit
------------------------------------------------------------------------
### `++zing`
Cons
++ zing :: promote
=| *
|%
+- $
?~ +<
+<
(welp +<- $(+< +<+))
--
Turns a list of lists into a single list by promoting the elements of
each sublist into the higher.
Accepts a [list]() of lists.
~zod/try=> (zing (limo [(limo ['a' 'b' 'c' ~]) (limo ['e' 'f' 'g' ~]) (limo ['h' 'i' 'j' ~]) ~]))
~['a' 'b' 'c' 'e' 'f' 'g' 'h' 'i' 'j']
~zod/try=> (zing (limo [(limo [1 'a' 2 'b' ~]) (limo [3 'c' 4 'd' ~]) ~]))
~[1 97 2 98 3 99 4 100]
------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@ -1,437 +0,0 @@
section 2dA, sets
=================
### `++apt`
Set verification
++ apt :: set invariant
|= a=(tree)
?~ a
&
?& ?~(l.a & ?&((vor n.a n.l.a) (hor n.l.a n.a)))
?~(r.a & ?&((vor n.a n.r.a) (hor n.a n.r.a)))
==
::
Produces a loobean indicating whether `a` is a set or not.
`a` is a [tree]().
~zod/try=> =b (sa `(list ,@t)`['john' 'bonita' 'daniel' 'madeleine' ~])
~zod/try=> (apt b)
%.y
~zod/try=> =m (mo `(list ,[@t *])`[['a' 1] ['b' [2 3]] ['c' 4] ['d' 5] ~])
~zod/try=> m
{[p='d' q=5] [p='a' q=1] [p='c' q=4] [p='b' q=[2 3]]}
~zod/try=> (apt m)
%.y
------------------------------------------------------------------------
### `++in`
Set operations
++ in :: set engine
~/ %in
|/ a=(set)
Input arm.
~zod/try=> ~(. in (sa "asd"))
<13.evb [nlr(^$1{@tD $1}) <414.fvk 101.jzo 1.ypj %164>]>
`a` is a [set]()
### `+-all:in`
Logical AND
+- all :: logical AND
~/ %all
|* b=$+(* ?)
|- ^- ?
?~ a
&
?&((b n.a) $(a l.a) $(a r.a))
::
Computes the logical AND on every element in `a` slammed with `b`,
producing a loobean.
`a` is a [set]().
`b` is a [wet gate]() that accepts a noun and produces a loobean.
~zod/try=> =b (sa `(list ,[@t *])`[['a' 1] ['b' [2 3]] ~])
~zod/try=> (~(all in b) |=(a=* ?@(+.a & |)))
%.n
~zod/try=> =b (sa `(list ,@t)`['john' 'bonita' 'daniel' 'madeleine' ~])
~zod/try=> (~(all in b) |=(a=@t (gte a 100)))
%.y
------------------------------------------------------------------------
### `+-any:in`
Logical OR
+- any :: logical OR
~/ %any
|* b=$+(* ?)
|- ^- ?
?~ a
|
?|((b n.a) $(a l.a) $(a r.a))
::
Computes the logical OR on every element of `a` slammed with `b`.
`a` is a [set]().
`b` is a [gate]() that accepts a noun and produces a loobean.
~zod/try=> =b (sa `(list ,[@t *])`[['a' 1] ['b' [2 3]] ~])
~zod/try=> (~(any in b) |=(a=* ?@(+.a & |)))
%.y
~zod/try=> =b (sa `(list ,@t)`['john' 'bonita' 'daniel' 'madeleine' ~])
~zod/try=> (~(any in b) |=(a=@t (lte a 100)))
%.n
------------------------------------------------------------------------
### `+-del:in`
Remove noun
+- del :: b without any a
~/ %del
|* b=*
|- ^+ a
?~ a
~
?. =(b n.a)
?: (hor b n.a)
[n.a $(a l.a) r.a]
[n.a l.a $(a r.a)]
|- ^- ?(~ _a)
?~ l.a r.a
?~ r.a l.a
?: (vor n.l.a n.r.a)
[n.l.a l.l.a $(l.a r.l.a)]
[n.r.a $(r.a l.r.a) r.r.a]
::
Removes `b` from the set `a`.
`a` is a [set]().
`b` is a [noun]().
~zod/try=> =b (sa `(list ,@t)`['a' 'b' 'c' ~])
~zod/try=> (~(del in b) 'a')
{'c' 'b'}
~zod/try=> =b (sa `(list ,@t)`['john' 'bonita' 'daniel' 'madeleine' ~])
~zod/try=> (~(del in b) 'john')
{'bonita' 'madeleine' 'daniel'}
~zod/try=> (~(del in b) 'susan')
{'bonita' 'madeleine' 'daniel' 'john'}
------------------------------------------------------------------------
### `+-dig:in`
Axis a in b
+- dig :: axis of a in b
|= b=*
=+ c=1
|- ^- (unit ,@)
?~ a ~
?: =(b n.a) [~ u=(peg c 2)]
?: (gor b n.a)
$(a l.a, c (peg c 6))
$(a r.a, c (peg c 7))
::
Produce the axis of `b` within `a`.
`a` is a [set]().
`b` is a [noun]().
~zod/try=> =a (sa `(list ,@)`[1 2 3 4 5 6 7 ~])
~zod/try=> a
{5 4 7 6 1 3 2}
~zod/try=> -.a
n=6
~zod/try=> (~(dig in a) 7)
[~ 12]
~zod/try=> (~(dig in a) 2)
[~ 14]
~zod/try=> (~(dig in a) 6)
[~ 2]
------------------------------------------------------------------------
### `+-gas:in`
Concatenate
+- gas :: concatenate
~/ %gas
|= b=(list ,_?>(?=(^ a) n.a))
|- ^+ a
?~ b
a
$(b t.b, a (put(+< a) i.b))
::
Insert the elements of a list `b` into a set `a`.
`a` is a [set]().
`b` is a [list]().
~zod/try=> b
{'bonita' 'madeleine' 'rudolf' 'john'}
~zod/try=> (~(gas in b) `(list ,@t)`['14' 'things' 'number' '1.337' ~])
{'1.337' '14' 'number' 'things' 'bonita' 'madeleine' 'rudolf' 'john'}
~zod/try=> (~(gas in s) `(list ,@t)`['1' '2' '3' ~])
{'1' '3' '2' 'e' 'd' 'a' 'c' 'b'}
------------------------------------------------------------------------
### `+-has:in`
b in a?
+- has :: b exists in a check
~/ %has
|* b=*
|- ^- ?
?~ a
|
?: =(b n.a)
&
?: (hor b n.a)
$(a l.a)
$(a r.a)
::
Checks if `b` is an element of `a`, producing a loobean.
`a` is a [set]().
`b` is a [noun]().
~zod/try=> =a (~(gas in `(set ,@t)`~) `(list ,@t)`[`a` `b` `c` ~])
~zod/try=> (~(has in a) `a`)
%.y
~zod/try=> (~(has in a) 'z')
%.n
------------------------------------------------------------------------
### `+-int:in`
Intersection
+- int :: intersection
~/ %int
|* b=_a
|- ^+ a
?~ b
~
?~ a
~
?. (vor n.a n.b)
$(a b, b a)
?: =(n.b n.a)
[n.a $(a l.a, b l.b) $(a r.a, b r.b)]
?: (hor n.b n.a)
%- uni(+< $(a l.a, b [n.b l.b ~])) $(b r.b)
%- uni(+< $(a r.a, b [n.b ~ r.b])) $(b l.b)
Produces a set of the intersection between two sets of the same type,
`a` and `b`.
`a` is a [set]().
`b` is a [set]().
~zod/try=> (~(int in (sa "ac")) (sa "ha"))
{~~a}
~zod/try=> (~(int in (sa "acmo")) ~)
{}
~zod/try=> (~(int in (sa "acmo")) (sa "ham"))
{~~a ~~m}
~zod/try=> (~(int in (sa "acmo")) (sa "lep"))
{}
------------------------------------------------------------------------
### `+-put:in`
Put b in a
+- put :: puts b in a
~/ %put
|* b=*
|- ^+ a
?~ a
[b ~ ~]
?: =(b n.a)
a
?: (hor b n.a)
=+ c=$(a l.a)
?> ?=(^ c)
?: (vor n.a n.c)
[n.a c r.a]
[n.c l.c [n.a r.c r.a]]
=+ c=$(a r.a)
?> ?=(^ c)
?: (vor n.a n.c)
[n.a l.a c]
[n.c [n.a l.a l.c] r.c]
::
Add an element `b` to the set `a`.
`a` is a [set]().
`b` is a [noun]().
~zod/try=> =a (~(gas in `(set ,@t)`~) `(list ,@t)`[`a` `b` `c` ~])
~zod/try=> =b (~(put in a) `d`)
~zod/try=> b
{`d` `a` `c` `b`}
~zod/try=> -.l.+.b
n=`d`
------------------------------------------------------------------------
### `+-rep:in`
Accumulate
+- rep :: replace by tile
|* [b=* c=_,*]
|-
?~ a b
$(a r.a, b $(a l.a, b (c n.a b)))
::
Accumulate the elements of `a` using a gate `c` and an accumulator `b`.
`a` is a [set]().
`b` is a [noun]() that accepts a noun and produces a loobean.
`c` is a [gate]().
~zod/try=> =a (~(gas in *(set ,@)) [1 2 3 ~])
~zod/try=> a
{1 3 2}
~zod/try=> (~(rep in a) 0 |=([a=@ b=@] (add a b)))
6
------------------------------------------------------------------------
### `+-tap:in`
Set to list
+- tap :: list tiles a set
~/ %tap
|= b=(list ,_?>(?=(^ a) n.a))
^+ b
?~ a
b
$(a r.a, b [n.a $(a l.a)])
::
Flatten the set `a` into a list.
`a` is an [set]().
`a` is a [set]().
`b` is a [list]().
~zod/try=> =s (sa `(list ,@t)`['a' 'b' 'c' 'd' 'e' ~])
~zod/try=> s
{'e' 'd' 'a' 'c' 'b'}
~zod/try=> (~(tap in s) `(list ,@t)`['1' '2' '3' ~])
~['b' 'c' 'a' 'd' 'e' '1' '2' '3']
~zod/try=> b
{'bonita' 'madeleine' 'daniel' 'john'}
~zod/try=> (~(tap in b) `(list ,@t)`['david' 'people' ~])
~['john' 'daniel' 'madeleine' 'bonita' 'david' 'people']
------------------------------------------------------------------------
### `+-uni:in`
Union
+- uni :: union
~/ %uni
|* b=_a
|- ^+ a
?~ b
a
?~ a
b
?: (vor n.a n.b)
?: =(n.b n.a)
[n.b $(a l.a, b l.b) $(a r.a, b r.b)]
?: (hor n.b n.a)
$(a [n.a $(a l.a, b [n.b l.b ~]) r.a], b r.b)
$(a [n.a l.a $(a r.a, b [n.b ~ r.b])], b l.b)
?: =(n.a n.b)
[n.b $(b l.b, a l.a) $(b r.b, a r.a)]
?: (hor n.a n.b)
$(b [n.b $(b l.b, a [n.a l.a ~]) r.b], a r.a)
$(b [n.b l.b $(b r.b, a [n.a ~ r.a])], a l.a)
Produces a set of the union between two sets of the same type, `a` and
`b`.
`a` is a [set]().
`b` is a [set]().
~zod/try=> (~(uni in (sa "ac")) (sa "ha"))
{~~a ~~c ~~h}
~zod/try=> (~(uni in (sa "acmo")) ~)
{~~a ~~c ~~m ~~o}
~zod/try=> (~(uni in (sa "acmo")) (sa "ham"))
{~~a ~~c ~~m ~~o ~~h}
~zod/try=> (~(uni in (sa "acmo")) (sa "lep"))
{~~e ~~a ~~c ~~m ~~l ~~o ~~p}
------------------------------------------------------------------------
### `+-wyt:in`
Set size
+- wyt :: size of set
|- ^- @
?~(a 0 +((add $(a l.a) $(a r.a))))
Produce the number of elements in set `a` as an atom.
`a` is an [set]().
~zod/try=> =a (~(put in (~(put in (sa)) 'a')) 'b')
~zod/try=> ~(wyt in a)
2
~zod/try=> b
{'bonita' 'madeleine' 'daniel' 'john'}
~zod/try=> ~(wyt in b)
4
------------------------------------------------------------------------

View File

@ -1,813 +0,0 @@
section 2dB, maps
=================
### `++ept`
Map invariant.
++ ept :: map invariant
|= a=(tree ,[p=* q=*])
?~ a
&
?& ?~(l.a & ?&((vor p.n.a p.n.l.a) (hor p.n.l.a p.n.a)))
?~(r.a & ?&((vor p.n.a p.n.r.a) (hor p.n.a p.n.r.a)))
==
Computes whether `a` is a [map](), producing a loobean.
`a` is a [tree]().
~zod/try=> m
{[p='d' q=5] [p='a' q=1] [p='c' q=4] [p='b' q=[2 3]]}
~zod/try=> (ept m)
%.y
~zod/try=> b
{'bonita' 'madeleine' 'daniel' 'john'}
~zod/try=> (ept b)
! type-fail
! exit
------------------------------------------------------------------------
### `++ja`
Jar engine
++ ja :: jar engine
|/ a=(jar)
A container arm for `++jar` operation arms. A `++jar` is a `++map` of
`++list`s. The contained arms inherit the [sample]() jar.
`a` is a [jar]().
~zod/try=> ~(. ja (mo (limo a/"ho" b/"he" ~)))
<2.dgz [nlr([p={%a %b} q=""]) <414.fvk 101.jzo 1.ypj %164>]>
------------------------------------------------------------------------
### `+-get:ja`
Grab value by key
+- get :: grab value by key
|* b=*
=+ c=(~(get by a) b)
?~(c ~ u.c)
Produces a list retrieved from jar `a` using the key `b`.
`a` is a [`++jar`](/doc/hoon/library/1#++jar).
`b` is a key of the same type as the keys in `a`.
~zod/try=> =l (mo `(list ,[@t (list ,@)])`[['a' `(list ,@)`[1 2 3 ~]] ['b' `(list ,@)`[4 5 6 ~]] ~])
~zod/try=> l
{[p='a' q=~[1 2 3]] [p='b' q=~[4 5 6]]}
~zod/try=> (~(get ja l) 'a')
~[1 2 3]
~zod/try=> (~(get ja l) 'b')
~[4 5 6]
~zod/try=> (~(get ja l) 'c')
~
------------------------------------------------------------------------
### `+-add:ja`
Prepend to list
+- add :: adds key-list pair
|* [b=* c=*]
=+ d=(get(+< a) b)
(~(put by a) b [c d])
Produces jar `a` with value `c` prepended to the list located at key
`b`.
`a` is a [jar]().
`b` is a key of the same type as the keys in `a`.
`c` is a value of the same type as the values in `a`.
~zod/try=> =l (mo `(list ,[@t (list ,@)])`[['a' `(list ,@)`[1 2 3 ~]] ['b' `(list ,@)`[4 5 6 ~]] ~])
~zod/try=> l
{[p='a' q=~[1 2 3]] [p='b' q=~[4 5 6]]}
~zod/try=> (~(add ja l) 'b' 7)
{[p='a' q=~[1 2 3]] [p='b' q=~[7 4 5 6]]}
~zod/try=> (~(add ja l) 'a' 100)
{[p='a' q=~[100 1 2 3]] [p='b' q=~[4 5 6]]}
~zod/try=> (~(add ja l) 'c' 7)
{[p='a' q=~[1 2 3]] [p='c' q=~[7]] [p='b' q=~[4 5 6]]}
~zod/try=> (~(add ja l) 'c' `(list ,@)`[7 8 9 ~])
! type-fail
! exit
------------------------------------------------------------------------
### `++ju`
Jug operations
++ ju :: jug engine
|/ a=(jug)
Container arm for jug operation arms. A `++jug` is a `++map` of
`++sets`. The contained arms inherit its [sample]() jug, `a`.
`a` is a [jug]().
~zod/try=> ~(. ju (mo (limo a/(sa "ho") b/(sa "he") ~)))
<2.dgz [nlr([p={%a %b} q={nlr(^$1{@tD $1}) nlr(^$3{@tD $3})}]) <414.fvk 101.jzo 1.ypj %164>]>
### `+-del:ju`
Remove
+- del :: delete at key b
|* [b=* c=*]
^+ a
=+ d=(get(+< a) b)
=+ e=(~(del in d) c)
?~ e
(~(del by a) b)
(~(put by a) b e)
Produces jug `a` with value `c` removed from set located at key `b`.
`a` is a [jug]().
`b` is a key of the same type as the keys in `a`.
`c` is the value of the same type of the keys in `a` that is to be
removed.
~zod/try=> s
{[p='a' q={1 3 2}] [p='b' q={5 4 6}]}
~zod/try=> (~(del ju s) 'a' 1)
{[p='a' q={3 2}] [p='b' q={5 4 6}]}
~zod/try=> (~(del ju s) 'c' 7)
{[p='a' q={1 3 2}] [p='b' q={5 4 6}]}
------------------------------------------------------------------------
### `+-get:ju`
Retrieve set
+- get :: gets set by key
|* b=*
=+ c=(~(get by a) b)
?~(c ~ u.c)
Produces a set retrieved from jar `a` using key `b`.
`a` is a [jar]().
`b` is a key of the same type as the keys in `a`.
~zod/try=> s
{[p='a' q={1 3 2}] [p='b' q={5 4 6}]}
~zod/try=> (~(get ju s) 'a')
{1 3 2}
~zod/try=> (~(get ju s) 'b')
{5 4 6}
~zod/try=> (~(get ju s) 'c')
~
------------------------------------------------------------------------
### `+-has:ju`
Check contents
+- has :: existence check
|* [b=* c=*]
^- ?
(~(has in (get(+< a) b)) c)
Computes whether a value `c` exists within the set located at key `b`
with jar `a`. Produces a loobean.
`a` is a [set]().
`b` is a key as a [noun]().
`c` is a value as a [noun]().
~zod/try=> s
{[p='a' q={1 3 2}] [p='b' q={5 4 6}]}
~zod/try=> (~(has ju s) 'a' 3)
%.y
~zod/try=> (~(has ju s) 'b' 6)
%.y
~zod/try=> (~(has ju s) 'a' 7)
%.n
~zod/try=> (~(has jus s) 'c' 7)
! -find-limb.jus
! find-none
! exit
~zod/try=> (~(has ju s) 'c' 7)
%.n
------------------------------------------------------------------------
### `+-put:ju`
Add key-set pair
+- put :: adds key-element pair
|* [b=* c=*]
^+ a
=+ d=(get(+< a) b)
(~(put by a) b (~(put in d) c))
Produces jar `a` with `c` added to the set value located at key `b`.
`a` is a [set]().
`b` is a key as a [noun]().
`c` is a [value]().
~zod/try=> s
{[p='a' q={1 3 2}] [p='b' q={5 4 6}]}
~zod/try=> (~(put ju s) 'a' 7)
{[p='a' q={7 1 3 2}] [p='b' q={5 4 6}]}
~zod/try=> (~(put ju s) 'a' 1)
{[p='a' q={1 3 2}] [p='b' q={5 4 6}]}
~zod/try=> (~(put ju s) 'c' 7)
{[p='a' q={1 3 2}] [p='c' q={7}] [p='b' q={5 4 6}]}
------------------------------------------------------------------------
### `++by`
Map operations
++ by :: map engine
~/ %by
|/ a=(map)
Container arm for map operation arms. A map is a set of key, value
pairs. The contained arms inherit it's [sample]() [map](), `a`.
`a` is a [map]().
~zod/try=> ~(. by (mo (limo [%a 1] [%b 2] ~)))
<19.irb [nlr([p={%a %b} q=@ud]) <414.rvm 101.jzo 1.ypj %164>]>
------------------------------------------------------------------------
### `+-all:by`
Logical AND
+- all :: logical AND
~/ %all
|* b=$+(* ?)
|- ^- ?
?~ a
&
?&((b q.n.a) $(a l.a) $(a r.a))
Computes the logical AND on the results of slamming every element in map
`a` with gate `b`. Produces a loobean.
`a` is a [map]().
`b` is a [wet gate]().
~zod/try=> =b (mo `(list ,[@t *])`[['a' 1] ['b' [2 3]] ~])
~zod/try=> (~(all by b) |=(a=* ?@(a & |)))
%.n
~zod/try=> =a (mo `(list ,[@t @u])`[['a' 1] ['b' 2] ['c' 3] ['d' 4] ['e' 5] ~])
~zod/try=> (~(all by a) |=(a=@ (lte a 6)))
%.y
~zod/try=> (~(all by a) |=(a=@ (lte a 4)))
%.n
------------------------------------------------------------------------
### `+-any:by`
Logical OR
+- any :: logical OR
~/ %any
|* b=$+(* ?)
|- ^- ?
?~ a
|
?|((b q.n.a) $(a l.a) $(a r.a))
Computes the logical OR on the results of slamming every element with
gate `b`. Produces a loobean.
`a` is a [map]().
`b` is a [wet gate]().
~zod/try=> =b (mo `(list ,[@t *])`[['a' 1] ['b' [2 3]] ~])
~zod/try=> (~(all by b) |=(a=* ?@(a & |)))
%.y
~zod/try=> =a (mo `(list ,[@t @u])`[['a' 1] ['b' 2] ['c' 3] ['d' 4] ['e' 5] ~])
~zod/try=> (~(any by a) |=(a=@ (lte a 4)))
%.y
------------------------------------------------------------------------
### `+-del:by`
Delete
+- del :: delete at key b
~/ %del
|* b=*
|- ^+ a
?~ a
~
?. =(b p.n.a)
?: (gor b p.n.a)
[n.a $(a l.a) r.a]
[n.a l.a $(a r.a)]
|- ^- ?(~ _a)
?~ l.a r.a
?~ r.a l.a
?: (vor p.n.l.a p.n.r.a)
[n.l.a l.l.a $(l.a r.l.a)]
[n.r.a $(r.a l.r.a) r.r.a]
Produces map `a` with the element located at key `b` removed.
`a` is a [map]().
`b` is a key as a [noun]().
~zod/try=> =b (mo `(list ,[@t *])`[['a' 1] ['b' [2 3]] ~])
~zod/try=> (~(del by b) `a`)
{[p=`b` q=[2 3]]}
------------------------------------------------------------------------
### `+-dig:by`
Axis of key
+- dig :: axis of key
|= b=*
=+ c=1
|- ^- (unit ,@)
?~ a ~
?: =(b p.n.a) [~ u=(peg c 2)]
?: (gor b p.n.a)
$(a l.a, c (peg c 6))
$(a r.a, c (peg c 7))
Produce the axis of key `b` within map `a`.
`a` is a [map]().
`b` is a key as a [noun]().
~zod/try=> =b (mo `(list ,[@t *])`[['a' 1] ['b' [2 3]] ~])
~zod/try=> (~(dig by b) `b`)
[~ 2]
------------------------------------------------------------------------
### `+-gas:by`
Concatenate
+- gas :: concatenate
~/ %gas
|* b=(list ,[p=* q=*])
=> .(b `(list ,_?>(?=(^ a) n.a))`b)
|- ^+ a
?~ b
a
$(b t.b, a (put(+< a) p.i.b q.i.b))
Insert a list of key-value pairs `b` into map `a`.
`a` is a [map]().
`b` is a [list]() of [cells]() of key-value nouns `p` and `q`.
~zod/try=> =a (mo `(list ,[@t *])`[[`a` 1] [`b` 2] ~])
~zod/try=> =b `(list ,[@t *])`[[`c` 3] [`d` 4] ~]
~zod/try=> (~(gas by a) b)
{[p=`d` q=4] [p=`a` q=1] [p=`c` q=3] [p=`b` q=2]}
------------------------------------------------------------------------
### `+-get:by`
Grab unit value
+- get :: unit value by key
~/ %get
|* b=*
|- ^- ?(~ [~ u=_?>(?=(^ a) q.n.a)])
?~ a
~
?: =(b p.n.a)
[~ u=q.n.a]
?: (gor b p.n.a)
$(a l.a)
$(a r.a)
Produce the unit value of the value located at key `b` within map `a`.
`a` is a [map]()
`b` is a [key]() as a [noun]()
~zod/try=> =b (mo `(list ,[@t *])`[['a' 1] ['b' [2 3]] ~])
~zod/try=> (~(get by b) `b`)
[~ [2 3]]
------------------------------------------------------------------------
### `+-got:by`
Assert
+- got
|* b=*
%- need
%- get(+< a) b
Produce the value located at key `b` within map `a`. Crash if key `b`
does not exist.
`a` is a [map]().
`b` is a [key]().
~zod/try=> =m (mo `(list ,[@t *])`[['a' 1] ['b' 2] ~])
~zod/try=> m
{[p='a' q=1] [p='b' q=2]}
~zod/try=> (~(get by m) 'a')
[~ 1]
~zod/try=> (~(got by m) 'a')
1
~zod/try=> (~(got by m) 'c')
! exit
------------------------------------------------------------------------
### `+-has:by`
Key existence check
+- has :: key existence check
~/ %has
|* b=*
!=(~ (get(+< a) b))
Checks whether map `a` contains an element with key `b`, producing a
loobean.
`a` is a [map]().
`b` is a key as a [noun]().
~zod/try=> =b (mo `(list ,[@t *])`[['a' 1] ['b' [2 3]] ~])
~zod/try=> (~(has by b) `b`)
%.y
~zod/try=> (~(has by b) `c`)
%.n
------------------------------------------------------------------------
### `+-int:by`
Intersection
+- int :: intersection
~/ %int
|* b=_a
|- ^+ a
?~ b
~
?~ a
~
?: (vor p.n.a p.n.b)
?: =(p.n.b p.n.a)
[n.b $(a l.a, b l.b) $(a r.a, b r.b)]
?: (hor p.n.b p.n.a)
%- uni(+< $(a l.a, b [n.b l.b ~])) $(b r.b)
%- uni(+< $(a r.a, b [n.b ~ r.b])) $(b l.b)
?: =(p.n.a p.n.b)
[n.b $(b l.b, a l.a) $(b r.b, a r.a)]
?: (hor p.n.a p.n.b)
%- uni(+< $(b l.b, a [n.a l.a ~])) $(a r.a)
%- uni(+< $(b r.b, a [n.a ~ r.a])) $(a l.a)
Produces a map of the (key) intersection between two maps of the same
type, `a` and `b`. If both maps have an identical key that point to
different values, the element from map `b` is used.
`a` is a [map]().
`b` is a [map]().
~zod/try=> =n (mo `(list ,[@t *])`[['a' 1] ['c' 3] ~])
~zod/try=> n
{[p='a' q=1] [p='c' q=3]}
~zod/try=> m
{[p='a' q=1] [p='b' q=2]}
~zod/try=> (~(int by m) n)
{[p='a' q=1]}
~ravpel-holber/try=> =p (mo `(list ,[@t *])`[['a' 2] ['b' 2] ~])
~zod/try=> p
{[p='a' q=2] [p='b' q=2]}
~zod/try=> (~(int by p) n)
{[p='a' q=2]}
~zod/try=> =q (mo `(list ,[@t *])`[['a' 2] ['c' 2] ~])
~zod/try=> q
{[p='a' q=2] [p='b' q=2]}
~zod/try=> (~(int by p) q)
{[p='a' q=2] [p='b' q=2]}
~zod/try=> =o (mo `(list ,[@t *])`[['c' 3] ['d' 4] ~])
~zod/try=> (~(int by m) o)
{}
------------------------------------------------------------------------
### `+-mar:by`
Assert and Add
+- mar :: add with validation
|* [b=_?>(?=(^ a) p.n.a) c=(unit ,_?>(?=(^ a) q.n.a))]
?~ c
(del b)
(put b u.c)
Produces map `a` with the addition of a key-value pair, where the value
is a nonempty unit.
Accept a noun and a unit of a noun of the type of the map's keys and
values, respectively. Validate that the value is not null and put the
pair in the map. If the value is null, delete the key.
XX This arm is broken, asana task 15186618346453
~zod/try=> m
{[p='a' q=1] [p='b' q=2]}
~zod/try=> (~(mar by m) 'c' (some 3))
! -find-limb.n
! find-none
! exit
~zod/try=> (~(mar by m) 'c' ~)
! -find-limb.n
! find-none
! exit
~zod/try=> (~(mar by m) 'b' ~)
! -find-limb.n
! find-none
! exit
------------------------------------------------------------------------
### `+-put:by`
Add key-value pair
+- put :: adds key-value pair
~/ %put
|* [b=* c=*]
|- ^+ a
?~ a
[[b c] ~ ~]
?: =(b p.n.a)
?: =(c q.n.a)
a
[[b c] l.a r.a]
?: (gor b p.n.a)
=+ d=$(a l.a)
?> ?=(^ d)
?: (vor p.n.a p.n.d)
[n.a d r.a]
[n.d l.d [n.a r.d r.a]]
=+ d=$(a r.a)
?> ?=(^ d)
?: (vor p.n.a p.n.d)
[n.a l.a d]
[n.d [n.a l.a l.d] r.d]
Produces `a` with the addition of the key-value pair of `b` and `c`.
`a` is a [map]().
`b` is a key of the same type as the keys in `a`.
`c` is a value of the same type of the values in `a`.
~zod/try=> m
{[p='a' q=1] [p='b' q=2]}
~zod/try=> (~(put by m) 'c' 3)
{[p='a' q=1] [p='c' q=3] [p='b' q=2]}
~zod/try=> (~(put by m) "zod" 26)
! type-fail
! exit
~zod/try=> (~(put by m) 'a' 2)
{[p='a' q=2] [p='b' q=2]}
------------------------------------------------------------------------
### `+-rep:by`
+- rep :: replace by product
|* [b=* c=_,*]
|-
?~ a b
$(a r.a, b $(a l.a, b (c q.n.a b)))
Accumulate using gate from values in map
XX interface changing.
------------------------------------------------------------------------
### `+-rib:by`
+- rib :: transform + product
|* [b=* c=_,*]
|- ^+ [b a]
?~ a [b ~]
=+ d=(c n.a b)
=. n.a +.d
=+ e=$(a l.a, b -.d)
=+ f=$(a r.a, b -.e)
[-.f [n.a +.e +.f]]
Replace values with accumulator
XX interface changing, possibly disappearing
------------------------------------------------------------------------
### `+-run:by`
Transform values
+- run :: turns to tuples
|* b=_,*
|-
?~ a a
a(n (b q.n.a), l $(a l.a), r $(a r.a))
Iterates over every value in set `a` using gate `b`. Produces a map.
`a` is a [map]().
`b` is a [wet gate]().
~zod/try=> m
{[p='a' q=1] [p='b' q=2]}
~zod/try=> ^+(m (~(run by m) dec))
{[p='a' q=0] [p='b' q=1]}
~zod/try=> `(map ,@tas ,@t)`(~(run by m) (cury scot %ux))
{[p=%a q='0x1'] [p=%b q='0x2']}
------------------------------------------------------------------------
### `+-tap:by`
Listify pairs
+- tap :: listify pairs
~/ %tap
|= b=(list ,_?>(?=(^ a) n.a))
^+ b
?~ a
b
$(a r.a, b [n.a $(a l.a)])
Produces the list of all elements in map `a` that is prepended to list
`b`, which is empty by default.
`a` is a [map]().
`b` is a [list]().
{[p='a' q=1] [p='b' q=2]}
~zod/try=> `*`m
[[98 2] [[97 1] 0 0] 0]
~zod/try=> (~(tap by m))
~[[p='b' q=2] [p='a' q=1]]
~zod/try=> `*`(~(tap by m))
[[98 2] [97 1] 0]
------------------------------------------------------------------------
### `+-uni:by`
Union
+- uni :: union, merge
~/ %uni
|* b=_a
|- ^+ a
?~ b
a
?~ a
b
?: (vor p.n.a p.n.b)
?: =(p.n.b p.n.a)
[n.b $(a l.a, b l.b) $(a r.a, b r.b)]
?: (hor p.n.b p.n.a)
$(a [n.a $(a l.a, b [n.b l.b ~]) r.a], b r.b)
$(a [n.a l.a $(a r.a, b [n.b ~ r.b])], b l.b)
?: =(p.n.a p.n.b)
[n.b $(b l.b, a l.a) $(b r.b, a r.a)]
?: (hor p.n.a p.n.b)
$(b [n.b $(b l.b, a [n.a l.a ~]) r.b], a r.a)
$(b [n.b l.b $(b r.b, a [n.a ~ r.a])], a l.a)
Produces a map of the union between the keys of `a` and `b`. If `b`
shares a key with `a`, the tuple from `a` is preserved.
`a` is a [map]().
`b` is a [map]().
~zod/try=> m
{[p='a' q=1] [p='b' q=2]}
~zod/try=> o
{[p='d' q=4] [p='c' q=3]}
~zod/try=> (~(uni by m) o)
{[p='d' q=4] [p='a' q=1] [p='c' q=3] [p='b' q=2]}
~zod/try=> (~(uni by m) ~)
{[p='a' q=1] [p='b' q=2]}
~zod/try=> n
{[p='a' q=1] [p='c' q=9]}
~zod/try=> (~(uni by o) n)
{[p='d' q=4] [p='a' q=1] [p='c' q=3]}
~zod/try=> =n (mo `(list ,[@t *])`[['a' 1] ['c' 9] ~])
~zod/try=> n
{[p='a' q=1] [p='c' q=9]}
~zod/try=> (~(uni by o) n)
{[p='d' q=4] [p='a' q=1] [p='c' q=9]}
------------------------------------------------------------------------
### `+-urn:by`
Turn (with key)
+- urn :: turn
|* b=$+([* *] *)
|-
?~ a ~
[n=[p=p.n.a q=(b p.n.a q.n.a)] l=$(a l.a) r=$(a r.a)]
Iterates over every value in map `a` using gate `b`, which accepts both
the key and the value of each element as its sample.
`a` is a [map]().
`b` is a [wet gate]() that accepts two nouns (a key and a value) and
produces a noun (the new value).
~zod/try=> m
{[p='a' q=1] [p='b' q=2]}
~zod/try=> (~(urn by m) |=(a=[p=* q=*] q.a))
{[p='a' q=1] [p='b' q=2]}
~zod/try=> (~(urn by m) |=(a=[p=* q=*] 7))
{[p='a' q=7] [p='b' q=7]}
~zod/try=> (~(urn by m) |=(a=[p=* q=*] p.a))
{[p='a' q=97] [p='b' q=98]}
------------------------------------------------------------------------
### `+-wyt:by`
Depth
+- wyt :: depth of map
|- ^- @
?~(a 0 +((add $(a l.a) $(a r.a))))
Produce the depth of the tree map `a`.
`a` is a [map]().
~zod/try=> m
{[p='a' q=1] [p='b' q=2]}
~zod/try=> o
{[p='d' q=4] [p='c' q=3]}
~zod/try=> ~(wyt by m)
2
~zod/try=> ~(wyt by o)
2
~zod/try=> ~(wyt by (~(uni by m) o))
4
------------------------------------------------------------------------

View File

@ -1,221 +0,0 @@
section 2dC, queues
===================
### `++to`
Queue engine
++ to :: queue engine
|/ a=(qeu)
Container arm for queue operation arms. The contained arms inherit its
[sample]() `++qeu` `a`.
`a` is a queue, [++qeu]().
### `+-bal:to`
Balance
+- bal
|- ^+ a
?~ a ~
?. |(?=(~ l.a) (vor n.a n.l.a))
$(a [n.l.a l.l.a $(a [n.a r.l.a r.a])])
?. |(?=(~ r.a) (vor n.a n.r.a))
$(a [n.r.a $(a [n.a l.a l.r.a]) r.r.a])
a
::
Vertically rebalances queue `a`.
`a` is a [queue]().
~zod/try=> `(qeu tape)`["a" ~ "b" ~ "c" ~ "d" ~ "e" ~ "f" ~ "g" ~ ~]
{"a" "b" "c" "d" "e" "f" "g"}
~zod/try=> `*`["a" ~ "b" ~ "c" ~ "d" ~ "e" ~ "f" ~ "g" ~ ~]
[[97 0] 0 [98 0] 0 [99 0] 0 [100 0] 0 [101 0] 0 [102 0] 0 [103 0] 0 0]
~zod/try=> ~(bal to `(qeu tape)`["a" ~ "b" ~ "c" ~ "d" ~ "e" ~ "f" ~ "g" ~ ~])
{"a" "b" "c" "d" "e" "f" "g"}
~zod/try=> `*`~(bal to `(qeu tape)`["a" ~ "b" ~ "c" ~ "d" ~ "e" ~ "f" ~ "g" ~ ~])
[[100 0] [[99 0] [[98 0] [[97 0] 0 0] 0] 0] [101 0] 0 [102 0] 0 [103 0] 0 0]
------------------------------------------------------------------------
### `+-dep:to`
Maximum Depth
+- dep :: max depth of queue
|- ^- @
?~ a 0
+((max $(a l.a) $(a r.a)))
::
Produces the maximum depth of leaves (r.a and l.a) in queue `a`.
`a` is a [queue]().
~zod/try=> =a (~(gas to `(qeu ,@)`~) `(list ,@)`[1 2 3 4 5 6 7 ~])
~zod/try=> ~(dep to a)
4
~zod/try=> =a (~(gas to `(qeu ,@)`~) `(list ,@)`[1 2 3 4 ~])
~zod/try=> ~(dep to a)
3
~zod/try=> =a (~(gas to `(qeu ,@)`~) `(list ,@)`[1 2 ~])
~zod/try=> ~(dep to a)
2
~zod/try=> ~(dep to `(qeu tape)`["a" ~ "b" ~ "c" ~ "d" ~ "e" ~ "f" ~ "g" ~ ~])
7
~zod/try=> ~(dep to ~(bal to `(qeu tape)`["a" ~ "b" ~ "c" ~ "d" ~ "e" ~ "f" ~ "g" ~ ~]))
4
------------------------------------------------------------------------
### `+-gas`
Push list
+- gas :: insert list to queue
|= b=(list ,_?>(?=(^ a) n.a))
|- ^+ a
?~(b a $(b t.b, a (put(+< a) i.b)))
::
Push all elements of list `b` into the queue.
`a` is a [queue]().
`b` is a list.
~zod/try=> (~(gas to `(qeu ,@)`~) `(list ,@)`[1 2 3 ~])
{3 2 1}
~zod/try=> =a (~(gas to `(qeu ,@)`~) `(list ,@)`[1 2 3 ~])
~zod/try=> =b `(list ,@)`[4 5 6 ~]
~zod/try=> (~(gas to a) b)
{6 5 4 3 2 1}
------------------------------------------------------------------------
### `+-get:to`
Pop
+- get :: head-tail pair
|- ^+ [p=?>(?=(^ a) n.a) q=a]
?~ a
!!
?~ r.a
[n.a l.a]
=+ b=$(a r.a)
:- p.b
?: |(?=(~ q.b) (vor n.a n.q.b))
[n.a l.a q.b]
[n.q.b [n.a l.a l.q.b] r.q.b]
::
Produces the head and tail queue of `a`.
`a` is a [queue]().
~zod/try=> =s (~(gas to *(qeu ,@)) `(list ,@)`~[1 2 3])
~zod/try=> ~(get to s)
[p=1 q={3 2}]
~zod/try=> ~(get to ~)
! exit
------------------------------------------------------------------------
### `+-nap:to`
Remove last in
+- nap :: removes head
?> ?=(^ a)
?: =(~ l.a) r.a
=+ b=get(+< l.a)
bal(+< ^+(a [p.b q.b r.a]))
::
Removes the head of queue `a`, producing the resulting queue.
`a` is a [queue]().
~zod/try=> =a (~(gas to `(qeu ,@)`~) `(list ,@)`[1 2 3 4 5 6 ~])
~zod/try=> -.a
n=6
~zod/try=> =b ~(nap to a)
~zod/try=> -.b
n=2
~zod/try=> b
{5 4 3 2 1}
~zod/try=> a
{6 5 4 3 2 1}
------------------------------------------------------------------------
### `+-put:to`
Insert
+- put :: insert new tail
|* b=*
|- ^+ a
?~ a
[b ~ ~]
bal(+< a(l $(a l.a)))
::
Accept any noun `b` and adds to queue `a` as the head, producing the
resulting queue.
`a` is a [queue]().
`b` is any noun.
~zod/try=> (~(gas to `(qeu ,@)`~) `(list ,@)`[3 1 2 4 5 6 ~])
~zod/try=> (~(put to a) 7)
{7 6 5 4 2 1 3}
------------------------------------------------------------------------
### `+-tap:to`
Queue to list
+- tap :: queue to list
|= b=(list ,_?>(?=(^ a) n.a))
^+ b
?~ a
b
$(a r.a, b [n.a $(a l.a)])
::
Produces queue `a` as a list from front to back.
`a` is a [queue]().
~zod/try=> =a (~(gas to `(qeu ,@)`~) `(list ,@)`[3 1 2 4 5 6 ~])
~zod/try=> `*`a
[6 0 2 [4 [5 0 0] 0] 1 0 3 0 0]
~zod/try=> (~(tap to a) `(list ,@)`[99 100 101 ~])
~[3 1 2 4 5 6 99 100 101]
------------------------------------------------------------------------
### `+-top:to`
+- top :: produces head
|- ^- (unit ,_?>(?=(^ a) n.a))
?~ a ~
?~(r.a [~ n.a] $(a r.a))
Produces the head of queue `a` as a unit (an empty queue has no head).
`a` is a [queue]().
~zod/try=> =a (~(gas to `(qeu ,@)`~) `(list ,@)`[1 2 3 4 5 6 ~])
~zod/try=> ~(top to a)
[~ 1]
------------------------------------------------------------------------

View File

@ -1,69 +0,0 @@
section 2dD, casual containers
==============================
### `++mo`
Map from list
++ mo :: map from list
|* a=(list)
=> .(a `_(homo a)`a)
=> .(a `(list ,[p=_-<.a q=_->.a])`a)
=+ b=*(map ,_?>(?=(^ a) p.i.a) ,_?>(?=(^ a) q.i.a))
(~(gas by b) a)
::
Produces a map of key-value pairs from the left-right cell pairs of list
`a`.
`a` is a [list]().
~zod/try=> (mo `(list ,[@t *])`[[`a` 1] [`b` 2] ~])
{[p=`a` q=1] [p=`b` q=2]}
------------------------------------------------------------------------
### `++sa`
Set from list
++ sa :: set from list
|* a=(list)
=> .(a `_(homo a)`a)
=+ b=*(set ,_?>(?=(^ a) i.a))
(~(gas in b) a)
::
Produces a set of the elements in list `a`.
`a` is a [list]().
~zod/try=> (sa `(list ,@)`[1 2 3 4 5 ~])
{5 4 1 3 2}
~zod/try=> (sa `(list ,[@t *])`[[`a` 1] [`b` 2] ~])
{[`a` 1] [`b` 2]}
------------------------------------------------------------------------
### `++qu`
Queue from list
++ qu :: queue from list
|* a=(list)
=> .(a `_(homo a)`a)
=+ b=*(qeu ,_?>(?=(^ a) i.a))
(~(gas to b) a)
Produces a queue from list `a`.
`a` is a [list]().
~zod/try=> (qu `(list ,@ud)`~[1 2 3 5])
{5 3 2 1}
~zod/try=> (qu "sada")
{'a' 'd' 'a' 's'}
~zod/try=> ~(top to (qu "sada"))
[~ 's']
------------------------------------------------------------------------

View File

@ -1,162 +0,0 @@
section 2eA, packing
====================
### `++cue`
Unpack atom to noun
++ cue :: unpack atom to noun
~/ %cue
|= a=@
^- *
=+ b=0
=+ m=`(map ,@ ,*)`~
=< q
|- ^- [p=@ q=* r=_m]
?: =(0 (cut 0 [b 1] a))
=+ c=(rub +(b) a)
[+(p.c) q.c (~(put by m) b q.c)]
=+ c=(add 2 b)
?: =(0 (cut 0 [+(b) 1] a))
=+ u=$(b c)
=+ v=$(b (add p.u c), m r.u)
=+ w=[q.u q.v]
[(add 2 (add p.u p.v)) w (~(put by r.v) b w)]
=+ d=(rub c a)
[(add 2 p.d) (need (~(get by m) q.d)) m]
::
Produces a noun unpacked from atom `a`. The inverse of jam.
`a` is an [atom]().
~zod/try=> (cue 12)
1
~zod/try=> (cue 817)
[1 1]
~zod/try=> (cue 4.657)
[1 2]
~zod/try=> (cue 39.689)
[0 19]
------------------------------------------------------------------------
### `++jam`
++ jam :: pack
~/ %jam
|= a=*
^- @
=+ b=0
=+ m=`(map ,* ,@)`~
=< q
|- ^- [p=@ q=@ r=_m]
=+ c=(~(get by m) a)
?~ c
=> .(m (~(put by m) a b))
?: ?=(@ a)
=+ d=(mat a)
[(add 1 p.d) (lsh 0 1 q.d) m]
=> .(b (add 2 b))
=+ d=$(a -.a)
=+ e=$(a +.a, b (add b p.d), m r.d)
[(add 2 (add p.d p.e)) (mix 1 (lsh 0 2 (cat 0 q.d q.e))) r.e]
?: ?&(?=(@ a) (lte (met 0 a) (met 0 u.c)))
=+ d=(mat a)
[(add 1 p.d) (lsh 0 1 q.d) m]
=+ d=(mat u.c)
[(add 2 p.d) (mix 3 (lsh 0 2 q.d)) m]
::
Produces an atom unpacked from noun `a`. The inverse of cue.
`a` is a [noun]().
~zod/try=> (jam 1)
12
~zod/try=> (jam [1 1])
817
~zod/try=> (jam [1 2])
4.657
~zod/try=> (jam [~ u=19])
39.689
------------------------------------------------------------------------
### `++mat`
Length-encode
++ mat :: length-encode
~/ %mat
|= a=@
^- [p=@ q=@]
?: =(0 a)
[1 1]
=+ b=(met 0 a)
=+ c=(met 0 b)
:- (add (add c c) b)
(cat 0 (bex c) (mix (end 0 (dec c) b) (lsh 0 (dec c) a)))
Produces a cell whose tail `q` is atom `a` with a bit representation of
its length prepended to it (as the least significant bits). The head `p`
is the length of `q` in bits.
`a` is an atom.
~zod/try=> (mat 0xaaa)
[p=20 q=699.024]
~zod/try=> (met 0 q:(mat 0xaaa))
20
~zod/try=> `@ub`q:(mat 0xaaa)
0b1010.1010.1010.1001.0000
~zod/try=> =a =-(~&(- -) `@ub`0xaaa)
0b1010.1010.1010
~zod/try=> =b =-(~&(- -) `@ub`(xeb a))
0b1100
~zod/try=> =b =-(~&(- -) `@ub`(met 0 a))
0b1100
~zod/try=> =c =-(~&(- -) (xeb b))
4
~zod/try=> [`@ub`a `@ub`(end 0 (dec c) b) `@ub`(bex c)]
[0b1010.1010.1010 0b100 0b1.0000]
------------------------------------------------------------------------
### `++rub`
Length-decode
++ rub :: length-decode
~/ %rub
|= [a=@ b=@]
^- [p=@ q=@]
=+ ^= c
=+ [c=0 m=(met 0 b)]
|- ?< (gth c m)
?. =(0 (cut 0 [(add a c) 1] b))
c
$(c +(c))
?: =(0 c)
[1 0]
=+ d=(add a +(c))
=+ e=(add (bex (dec c)) (cut 0 [d (dec c)] b))
[(add (add c c) e) (cut 0 [(add d (dec c)) e] b)]
The inverse of `++mat`. Accepts a cell of index `a` and a bitstring `b`
and produces the cell whose tail `q` is the decoded atom at index `a`
and whose head is the length of the encoded atom `q`, by which the
offset `a` is advanced. Only used internally as a helper cue.
`a` is an atom.
`b` is a bitstring as an atom.
~zod/try=> `@ub`(jam 0xaaa)
0b1.0101.0101.0101.0010.0000
~zod/try=> (rub 1 0b1.0101.0101.0101.0010.0000)
[p=20 q=2.730]
~zod/try=> `@ux`q:(rub 1 0b1.0101.0101.0101.0010.0000)
0xaaa
------------------------------------------------------------------------

View File

@ -1,63 +0,0 @@
section 2eB, parsing (tracing)
==============================
### `++last`
Farther trace
++ last |= [zyc=hair naz=hair] :: farther trace
^- hair
?: =(p.zyc p.naz)
?:((gth q.zyc q.naz) zyc naz)
?:((gth p.zyc p.naz) zyc naz)
::
Compares two line-column pairs, `zyc` and `naz`, and produces whichever
[hair]() is farther along.
`zyc` is a [hair]().
`naz` is a [hair]().
~zod/try=> (last [1 1] [1 2])
[p=1 q=2]
~zod/try=> (last [2 1] [1 2])
[p=2 q=1]
~zod/try=> (last [0 0] [99 0])
[p=99 q=0]
~zod/try=> (last [7 7] [7 7])
[p=7 q=7]
------------------------------------------------------------------------
### `++lust`
Detect newline
++ lust |= [weq=char naz=hair] :: detect newline
^- hair
?:(=(10 weq) [+(p.naz) 1] [p.naz +(q.naz)])
Advances the hair `naz` by a row if the char `weq` is a newline, or by a
column if `weq` is any other character.
`weq` is a [char]().
`naz` is a [hair]().
~zod/try=> (lust `a` [1 1])
[p=1 q=2]
~zod/try=> (lust `@t`10 [1 1])
[p=2 q=1]
~zod/try=> (lust '9' [10 10])
[p=10 q=11]
/~zod/try=> (roll "maze" [.(+<+ [1 1])]:lust)
[1 5]
/~zod/try=> %- roll :_ [.(+<+ [1 1])]:lust
"""
Sam
lokes
"""
[2 6]
------------------------------------------------------------------------

View File

@ -1,652 +0,0 @@
section 2eC, parsing (custom rules)
===================================
### `++cold`
Replace with constant
++ cold :: replace w/ constant
~/ %cold
|* [cus=* sef=_rule]
~/ %fun
|= tub=nail
=+ vex=(sef tub)
?~ q.vex
vex
[p=p.vex q=[~ u=[p=cus q=q.u.q.vex]]]
::
Parser modifier. Accepts a rule `sef` and produces a parser that
produces a constant `cus`, if `sef` is successful.
`cus` is a constant [noun]().
`sef` is a [`++rule`]().
~zod/try=> ((cold %foo (just 'a')) [[1 1] "abc"])
[p=[p=1 q=2] q=[~ u=[p=%foo q=[p=[p=1 q=2] q="bc"]]]]
~zod/try=> ((cold %foo (just 'a')) [[1 1] "bc"])
[p=[p=1 q=1] q=~]
------------------------------------------------------------------------
### `++cook`
Apply gate
++ cook :: apply gate
~/ %cook
|* [poq=_,* sef=_rule]
~/ %fun
|= tub=nail
=+ vex=(sef tub)
?~ q.vex
vex
[p=p.vex q=[~ u=[p=(poq p.u.q.vex) q=q.u.q.vex]]]
::
Parser modifier. Produces a parser that takes a (successful) result of a
rule `sef` and slams it through `poq`.
`poq` is a [gate]().
`sef` is a [`++rule`]().
~zod/try=> ((cook ,@ud (just 'a')) [[1 1] "abc"])
[p=[p=1 q=2] q=[~ u=[p=97 q=[p=[p=1 q=2] q="bc"]]]]
~zod/try=> ((cook ,@tas (just 'a')) [[1 1] "abc"])
[p=[p=1 q=2] q=[~ u=[p=%a q=[p=[p=1 q=2] q="bc"]]]]
~zod/try=> ((cook |=(a=@ +(a)) (just 'a')) [[1 1] "abc"])
[p=[p=1 q=2] q=[~ u=[p=98 q=[p=[p=1 q=2] q="bc"]]]]
~zod/try=> ((cook |=(a=@ `@t`+(a)) (just 'a')) [[1 1] "abc"])
[p=[p=1 q=2] q=[~ u=[p='b' q=[p=[p=1 q=2] q="bc"]]]]
------------------------------------------------------------------------
### `++easy`
Always parse
++ easy :: always parse
~/ %easy
|* huf=*
~/ %fun
|= tub=nail
^- (like ,_huf)
[p=p.tub q=[~ u=[p=huf q=tub]]]
::
Parser generator. Produces a parser that succeeds with given noun `huf`
without consuming any text.
~zod/try=> ((easy %foo) [[1 1] "abc"])
[p=[p=1 q=1] q=[~ [p=%foo q=[p=[p=1 q=1] q="abc"]]]]
~zod/try=> ((easy %foo) [[1 1] "bc"])
[p=[p=1 q=1] q=[~ [p=%foo q=[p=[p=1 q=1] q="bc"]]]]
~zod/try=> ((easy 'a') [[1 1] "bc"])
[p=[p=1 q=1] q=[~ [p='a' q=[p=[p=1 q=1] q="bc"]]]]
------------------------------------------------------------------------
### `++fail`
Never parse
++ fail |=(tub=nail [p=p.tub q=~]) :: never parse
Produces an [edge]() at the same text position ([hair]()) with a failing
result (`q=~`).
`tub` is a [`++nail`]().
~zod/try=> (fail [[1 1] "abc"])
[p=[p=1 q=1] q=~]
~zod/try=> (fail [[p=1.337 q=70] "Parse me, please?"])
[p=[p=1.337 q=70] q=~]
------------------------------------------------------------------------
### `++full`
Parse to end
++ full :: parse to end
|* sef=_rule
|= tub=nail
=+ vex=(sef tub)
?~(q.vex vex ?:(=(~ q.q.u.q.vex) vex [p=p.vex q=~]))
::
Accepts a [`++nail`](), `tub`, and produces a parser that succeeds only
when a `tub` success consumes the remainder of the [tape]().
`sef` is a [`++rule`]().
~zod/try=> ((full (just 'a')) [[1 1] "ab"])
[p=[p=1 q=2] q=~]
~zod/try=> ((full (jest 'ab')) [[1 1] "ab"])
[p=[p=1 q=3] q=[~ u=[p='ab' q=[p=[p=1 q=3] q=""]]]]
~zod/try=> ((full ;~(plug (just 'a') (just 'b'))) [[1 1] "ab"])
[p=[p=1 q=3] q=[~ u=[p=[~~a ~~b] q=[p=[p=1 q=3] q=""]]]]
------------------------------------------------------------------------
### `++funk`
Add to tape
++ funk :: add to tape first
|* [pre=tape sef=_rule]
|= tub=nail
(sef p.tub (weld pre q.tub))
::
Parser modifier: prepend text to tape before applying parser.
`pre` is a [`++tape`]()
`sef` is a [`++rule`]()
~zod/try=> ((funk "abc prefix-" (jest 'abc')) [[1 1] "to be parsed"])
[p=[p=1 q=4] q=[~ [p='abc' q=[p=[p=1 q=4] q=" prefix-to be parsed"]]]]
~zod/try=> ((funk "parse" (just 'a')) [[1 4] " me"])
[p=[p=1 q=4] q=~]
------------------------------------------------------------------------
### `++here`
Place-based apply
++ here :: place-based apply
~/ %here
|* [hez=_|=([a=pint b=*] [a b]) sef=_rule]
~/ %fun
|= tub=nail
=+ vex=(sef tub)
?~ q.vex
vex
[p=p.vex q=[~ u=[p=(hez [p.tub p.q.u.q.vex] p.u.q.vex) q=q.u.q.vex]]]
::
Parser modifier. Similar to [`++cook`](), produces a parser that takes a
(successful) result of `sef` and slams it through `hez`. `hez` accepts a
[`++pint`]() `a` and a noun `b`, which is what the parser parsed.
`hez` is a [gate]().
`sef` is a [`++rule`]()
~zod/try=> (scan "abc" (star alf))
"abc"
~zod/try=> (scan "abc" (here |*(^ +<) (star alf)))
[[[p=1 q=1] p=1 q=4] "abc"]
~zod/try=> (scan "abc" (star (here |*(^ +<) alf)))
~[[[[p=1 q=1] p=1 q=2] ~~a] [[[p=1 q=2] p=1 q=3] ~~b] [[[p=1 q=3] p=1 q=4] ~~c]]
------------------------------------------------------------------------
### `++inde`
Indentation block
++ inde |* sef=_rule :: indentation block
|= nail ^+ (sef)
=+ [har tap]=[p q]:+<
=+ lev=(fil 3 (dec q.har) ' ')
=+ eol=(just `@t`10)
=+ =- roq=((star ;~(pose prn ;~(sfix eol (jest lev)) -)) har tap)
;~(simu ;~(plug eol eol) eol)
?~ q.roq roq
=+ vex=(sef har(q 1) p.u.q.roq)
=+ fur=p.vex(q (add (dec q.har) q.p.vex))
?~ q.vex vex(p fur)
=- vex(p fur, u.q -)
:+ &3.vex
&4.vex(q.p (add (dec q.har) q.p.&4.vex))
=+ res=|4.vex
|- ?~ res |4.roq
?. =(10 -.res) [-.res $(res +.res)]
(welp [`@t`10 (trip lev)] $(res +.res))
::
Apply rule to indented block starting at current column number, omitting
the leading whitespace.
`sef` is a [`++rule`]()
~zod/try=> (scan "abc" (inde (star ;~(pose prn (just `@`10)))))
"abc"
~zod/try=> (scan "abc" (star ;~(pose prn (just `@`10))))
"abc"
~zod/try=> (scan " abc\0ade" ;~(pfix ace ace (star ;~(pose prn (just `@`10)))))
"abc
de"
~zod/try=> (scan " abc\0ade" ;~(pfix ace ace (inde (star ;~(pose prn (just `@`10))))))
! {1 6}
! exit
~zod/try=> (scan " abc\0a de" ;~(pfix ace ace (inde (star ;~(pose prn (just `@`10))))))
"abc
de"
------------------------------------------------------------------------
### `++jest`
Match a cord
++ jest :: match a cord
|= daf=@t
|= tub=nail
=+ fad=daf
|- ^- (like ,@t)
?: =(0 daf)
[p=p.tub q=[~ u=[p=fad q=tub]]]
?: |(?=(~ q.tub) !=((end 3 1 daf) i.q.tub))
(fail tub)
$(p.tub (lust i.q.tub p.tub), q.tub t.q.tub, daf (rsh 3 1 daf))
::
Match and consume a cord.
`daf` is a `@t`
~zod/try=> ((jest 'abc') [[1 1] "abc"])
[p=[p=1 q=4] q=[~ [p='abc' q=[p=[p=1 q=4] q=""]]]]
~zod/try=> (scan "abc" (jest 'abc'))
'abc'
~zod/try=> (scan "abc" (jest 'acb'))
! {1 2}
! 'syntax-error'
! exit
~zod/try=> ((jest 'john doe') [[1 1] "john smith"])
[p=[p=1 q=6] q=~]
~zod/try=> ((jest 'john doe') [[1 1] "john doe"])
[p=[p=1 q=9] q=[~ [p='john doe' q=[p=[p=1 q=9] q=""]]]]
------------------------------------------------------------------------
### `++just`
Match a char
++ just :: XX redundant, jest
~/ %just :: match a char
|= daf=char
~/ %fun
|= tub=nail
^- (like char)
?~ q.tub
(fail tub)
?. =(daf i.q.tub)
(fail tub)
(next tub)
::
Match and consume a single character.
`daf` is a [`++char`]()
~zod/try=> ((just 'a') [[1 1] "abc"])
[p=[p=1 q=2] q=[~ [p=~~a q=[p=[p=1 q=2] q="bc"]]]]
~zod/try=> (scan "abc" (just 'a'))
! {1 2}
! 'syntax-error'
! exit
~zod/try=> (scan "a" (just 'a'))
~~a
~zod/try=> (scan "%" (just '%'))
~~~25.
------------------------------------------------------------------------
### `++knee`
Recursive parsers
++ knee :: callbacks
|* [gar=* sef=_|.(rule)]
|= tub=nail
^- (like ,_gar)
((sef) tub)
::
Used for recursive parsers, which would otherwise be infinite when
compiled.
`gar` is a noun.
`sef` is a [gate]() that accepts a [`++rule`]()
~zod/try=> |-(;~(plug prn ;~(pose $ (easy ~))))
! rest-loop
! exit
~zod/try=> |-(;~(plug prn ;~(pose (knee *tape |.(^$)) (easy ~))))
< 1.obo
[ c=c=tub=[p=[p=@ud q=@ud] q=""]
b
< 1.bes
[ c=tub=[p=[p=@ud q=@ud] q=""]
b=<1.tnv [tub=[p=[p=@ud q=@ud] q=""] <1.ktu [daf=@tD <414.fvk 101.jzo 1.ypj %164>]>]>
a=<1.fvg [tub=[p=[p=@ud q=@ud] q=""] <1.khu [[les=@ mos=@] <414.fvk 101.jzo 1.ypj %164>]>]>
v=<414.fvk 101.jzo 1.ypj %164>
]
>
a
... 450 lines omitted ...
]
>
~zod/try=> (scan "abcd" |-(;~(plug prn ;~(pose (knee *tape |.(^$)) (easy ~)))))
[~~a "bcd"]
------------------------------------------------------------------------
### `++mask`
Match char
++ mask :: match char in set
~/ %mask
|= bud=(list char)
~/ %fun
|= tub=nail
^- (like char)
?~ q.tub
(fail tub)
?. (lien bud |=(a=char =(i.q.tub a)))
(fail tub)
(next tub)
::
Parser generator. Matches the next character if it is in a list of
characters.
`bud` is a list of [`++char`]()
~zod/try=> (scan "a" (mask "cba"))
~~a
~zod/try=> ((mask "abc") [[1 1] "abc"])
[p=[p=1 q=2] q=[~ [p=~~a q=[p=[p=1 q=2] q="bc"]]]]
~zod/try=> ((mask "abc") [[1 1] "bbc"])
[p=[p=1 q=2] q=[~ [p=~~b q=[p=[p=1 q=2] q="bc"]]]]
~zod/try=> ((mask "abc") [[1 1] "dbc"])
[p=[p=1 q=1] q=~]
------------------------------------------------------------------------
### `++next`
Consume char
++ next :: consume a char
|= tub=nail
^- (like char)
?~ q.tub
(fail tub)
=+ zac=(lust i.q.tub p.tub)
[zac [~ i.q.tub [zac t.q.tub]]]
::
Consume any character, producing it as a result.
`tub` is a [`++nail`]()
~zod/try=> (next [[1 1] "ebc"])
[p=[p=1 q=2] q=[~ [p=~~e q=[p=[p=1 q=2] q="bc"]]]]
~zod/try=> (next [[1 1] "john jumps jones"])
[p=[p=1 q=2] q=[~ [p=~~j q=[p=[p=1 q=2] q="ohn jumps jones"]]]]
------------------------------------------------------------------------
### `++sear`
Conditional `++cook`
++ sear :: conditional cook
|* [pyq=_|=(* *(unit)) sef=_rule]
|= tub=nail
=+ vex=(sef tub)
?~ q.vex
vex
=+ gey=(pyq p.u.q.vex)
?~ gey
[p=p.vex q=~]
[p=p.vex q=[~ u=[p=u.gey q=q.u.q.vex]]]
::
Conditional [`++cook`](). Slams the result through a gate that produces
a unit; if that unit is empty, fail.
`tub` is a [`++nail`](/doc/hoon/library/1#++nail)
~zod/try=> ((sear |=(a=* ?@(a (some a) ~)) (just `a`)) [[1 1] "abc"])
[p=[p=1 q=2] q=[~ u=[p=97 q=[p=[p=1 q=2] q="bc"]]]]
~zod/try=> ((sear |=(* ~) (just 'a')) [[1 1] "abc"])
[p=[p=1 q=2] q=~]
------------------------------------------------------------------------
### `++shim`
Char in range
++ shim :: match char in range
~/ %shim
|= [les=@ mos=@]
~/ %fun
|= tub=nail
^- (like char)
?~ q.tub
(fail tub)
?. ?&((gte i.q.tub les) (lte i.q.tub mos))
(fail tub)
(next tub)
::
Match characters within a range.
`les` and `mos` are atoms, `@`.
~zod/try=> ((shim 'a' 'z') [[1 1] "abc"])
[p=[p=1 q=2] q=[~ [p=~~a q=[p=[p=1 q=2] q="bc"]]]]
~zod/try=> ((shim 'a' 'Z') [[1 1] "abc"])
[p=[p=1 q=1] q=~]
~zod/try=> ((shim 'a' 'Z') [[1 1] "Abc"])
[p=[p=1 q=2] q=[~ [p=~~~41. q=[p=[p=1 q=2] q="bc"]]]]
------------------------------------------------------------------------
### `++stag`
Add label
++ stag :: add a label
~/ %stag
|* [gob=* sef=_rule]
~/ %fun
|= tub=nail
=+ vex=(sef tub)
?~ q.vex
vex
[p=p.vex q=[~ u=[p=[gob p.u.q.vex] q=q.u.q.vex]]]
::
Add a label to an edge parsed by a rule.
`gob` is a noun.
`sef` is a rule.
~zod/try=> ((stag %foo (just 'a')) [[1 1] "abc"])
[p=[p=1 q=2] q=[~ u=[p=[%foo ~~a] q=[p=[p=1 q=2] q="bc"]]]]
~zod/try=> ((stag "xyz" (jest 'abc')) [[1 1] "abc"])
[p=[p=1 q=4] q=[~ u=[p=["xyz" 'abc'] q=[p=[p=1 q=4] q=""]]]]
~zod/try=> ((stag 10.000 (shim 0 100)) [[1 1] "abc"])
[p=[p=1 q=2] q=[~ u=[p=[10.000 ~~a] q=[p=[p=1 q=2] q="bc"]]]]
------------------------------------------------------------------------
### `++stet`
Add faces
++ stet
|* leh=(list ,[?(@ [@ @]) _rule])
|-
?~ leh
~
[i=[p=-.i.leh q=+.i.leh] t=$(leh t.leh)]
::
Add `[p q]` faces to range-parser pairs in a list.
`leh` is a list of range-parsers.
~zod/try=> (stet (limo [[5 (just 'a')] [1 (jest 'abc')] [[1 1] (shim 0 200)]
[[1 10] (cold %foo (just 'a'))]~]))
~[
[p=5 q=<1.lrk [tub=[p=[p=@ud q=@ud] q=""] <1.nqy [daf=@tD <394.imz 97.kdz 1.xlc %164>]>]>]
[p=1 q=<1.lrk [tub=[p=[p=@ud q=@ud] q=""] <1.nqy [daf=@tD <394.imz 97.kdz 1.xlc %164>]>]>]
[p=[1 1] q=<1.lrk [tub=[p=[p=@ud q=@ud] q=""] <1.nqy [daf=@tD <394.imz 97.kdz 1.xlc %164>]>]>]
[p=[1 10] q=<1.lrk [tub=[p=[p=@ud q=@ud] q=""] <1.nqy [daf=@tD <394.imz 97.kdz 1.xlc %164>]>]>]
]
~zod/try=> [[[1 1] (just 'a')] [[2 1] (shim 0 200)] ~]
[ [[1 1] <1.tnv [tub=[p=[p=@ud q=@ud] q=""] <1.ktu [daf=@tD <414.fvk 101.jzo 1.ypj %164>]>]>]
[[2 1] <1.fvg [tub=[p=[p=@ud q=@ud] q=""] <1.khu [[les=@ mos=@] <414.fvk 101.jzo 1.ypj %164>]>]>]
~
]
~zod/try=> (stet (limo [[[1 1] (just 'a')] [[2 1] (shim 0 200)] ~]))
~[
[p=[1 1] q=<1.lrk [tub=[p=[p=@ud q=@ud] q=""] <1.nqy [daf=@tD <394.imz 97.kdz 1.xlc %164>]>]>]
[p=[2 1] q=<1.lrk [tub=[p=[p=@ud q=@ud] q=""] <1.nqy [daf=@tD <394.imz 97.kdz 1.xlc %164>]>]>]
]
------------------------------------------------------------------------
### `++stew`
Switch by first
++ stew :: switch by first char
~/ %stew
|* leh=(list ,[p=?(@ [@ @]) q=_rule]) :: char/range keys
=+ ^= wor :: range complete lth
|= [ort=?(@ [@ @]) wan=?(@ [@ @])]
?@ ort
?@(wan (lth ort wan) (lth ort -.wan))
?@(wan (lth +.ort wan) (lth +.ort -.wan))
=+ ^= hel :: build parser map
=+ hel=`(tree $_(?>(?=(^ leh) i.leh)))`~
|- ^+ hel
?~ leh
~
=+ yal=$(leh t.leh)
|- ^+ hel
?~ yal
[i.leh ~ ~]
?: (wor p.i.leh p.n.yal)
=+ nuc=$(yal l.yal)
?> ?=(^ nuc)
?: (vor p.n.yal p.n.nuc)
[n.yal nuc r.yal]
[n.nuc l.nuc [n.yal r.nuc r.yal]]
=+ nuc=$(yal r.yal)
?> ?=(^ nuc)
?: (vor p.n.yal p.n.nuc)
[n.yal l.yal nuc]
[n.nuc [n.yal l.yal l.nuc] r.nuc]
~% %fun ..^$ ~
|= tub=nail
?~ q.tub
(fail tub)
|-
?~ hel
(fail tub)
?: ?@ p.n.hel
=(p.n.hel i.q.tub)
?&((gte i.q.tub -.p.n.hel) (lte i.q.tub +.p.n.hel))
:: (q.n.hel [(lust i.q.tub p.tub) t.q.tub])
(q.n.hel tub)
?: (wor i.q.tub p.n.hel)
$(hel l.hel)
$(hel r.hel)
::
Parser generator. From an associative list of characters or character
ranges to rules, construct a map, and parse tapes only with rules
associated with a range the tape's first character falls in.
------------------------------------------------------------------------
### `++stir`
Parse repeatedly
++ stir :: parse repeatedly
~/ %stir
|* [rud=* raq=_|*([a=* b=*] [a b]) fel=_rule]
~/ %fun
|= tub=nail
^- (like ,_rud)
=+ vex=(fel tub)
?~ q.vex
[p.vex [~ rud tub]]
=+ wag=$(tub q.u.q.vex)
?> ?=(^ q.wag)
[(last p.vex p.wag) [~ (raq p.u.q.vex p.u.q.wag) q.u.q.wag]]
::
Parse with rule as many times as possible, and fold over results with a
binary gate.
`rud` is a noun.
`raq` is a gate that takes two nouns and produces a cell.
`fel` is a rule.
~zod/try=> (scan "abc" (stir *@ add prn))
294
~zod/try=> (roll "abc" add)
b=294
------------------------------------------------------------------------
### `++stun`
Parse several times
++ stun :: parse several times
|* [[les=@ mos=@] fel=_rule]
|= tub=nail
^- (like (list ,_(wonk (fel))))
?: =(0 mos)
[p.tub [~ ~ tub]]
=+ vex=(fel tub)
?~ q.vex
?: =(0 les)
[p.vex [~ ~ tub]]
vex
=+ ^= wag %= $
les ?:(=(0 les) 0 (dec les))
mos ?:(=(0 mos) 0 (dec mos))
tub q.u.q.vex
==
?~ q.wag
wag
[p.wag [~ [p.u.q.vex p.u.q.wag] q.u.q.wag]]
Parse bounded number of times.
`[les=@ mos=@]` is a cell of atoms indicating the bounds.
`fel` is a rule.
~zod/try=> ((stun [5 10] prn) [1 1] "aquickbrownfoxran")
[p=[p=1 q=11] q=[~ [p="aquickbrow" q=[p=[p=1 q=11] q="nfoxran"]]]]
~zod/try=> ((stun [5 10] prn) [1 1] "aquickbro")
[p=[p=1 q=10] q=[~ [p="aquickbro" q=[p=[p=1 q=10] q=""]]]]
~zod/try=> ((stun [5 10] prn) [1 1] "aqui")
[p=[p=1 q=5] q=~]
------------------------------------------------------------------------

View File

@ -1,289 +0,0 @@
section 2eD
===========
### `++bend`
Conditional composer
++ bend :: conditional comp
~/ %bend
|* raq=_|*([a=* b=*] [~ u=[a b]])
~/ %fun
|* [vex=edge sab=_rule]
?~ q.vex
vex
=+ yit=(sab q.u.q.vex)
=+ yur=(last p.vex p.yit)
?~ q.yit
[p=yur q=q.vex]
=+ vux=(raq p.u.q.vex p.u.q.yit)
?~ vux
[p=yur q=q.vex]
[p=yur q=[~ u=[p=u.vux q=q.u.q.yit]]]
::
Parsing composer: connects the edge `vex` with the subsequent rule `sab`
as an optional suffix, using the gate `raq` to compose or reject its
result. If there is no suffix, or if the suffix fails to be composed
with the current result, the current result is produced. Used to map a
group of rules to a specified output.
`raq` is a [gate]().
`sab` is a [rule]().
`vex` is an [edge]().
~zod/try=> (;~((bend |=([a=char b=char] ?.(=(a b) ~ (some +(a))))) prn prn) [1 1] "qs")
[p=[p=1 q=3] q=[~ u=[p=~~q q=[p=[p=1 q=2] q="s"]]]]
~zod/try=> (;~((bend |=([a=char b=char] ?.(=(a b) ~ (some +(a))))) prn prn) [1 1] "qqq")
[p=[p=1 q=3] q=[~ u=[p=~~r q=[p=[p=1 q=3] q="q"]]]]
~zod/try=> (scan "aa" ;~((bend |=([a=char b=char] ?.(=(a b) ~ (some +(a))))) prn prn))
~~b
~zod/try=> (scan "ba" ;~((bend |=([a=char b=char] ?.(=(a b) ~ (some +(a))))) prn prn))
! {1 3}
! exit
~zod/try=> `(unit ,@tas)`(scan "" ;~((bend) (easy ~) sym))
~
~zod/try=> `(unit ,@tas)`(scan "sep" ;~((bend) (easy ~) sym))
[~ %sep]
------------------------------------------------------------------------
### `++comp`
Arbitrary compose
++ comp
~/ %comp
|* raq=_|*([a=* b=*] [a b]) :: arbitrary compose
~/ %fun
|* [vex=edge sab=_rule]
?~ q.vex
vex
=+ yit=(sab q.u.q.vex)
=+ yur=(last p.vex p.yit)
?~ q.yit
[p=yur q=q.yit]
[p=yur q=[~ u=[p=(raq p.u.q.vex p.u.q.yit) q=q.u.q.yit]]]
::
Parsing composer: connects the edge `vex` with a following rule `sab`,
combining the contents of `vex` with the result of `sab` using a binary
gate `raq`. Used to fold over the results of several rules.
`raq` is a [gate]() that accepts a cell of two nouns, `a` and `b`, and
produces a cell of two nouns.
`sab` is a [rule]().
`vex` is an [edge]().
~zod/try=> (scan "123" ;~((comp |=([a=@u b=@u] (add a b))) dit dit dit))
6
~zod/try=> (scan "12" ;~((comp |=([a=@u b=@u] (add a b))) dit dit dit))
! {1 3}
! exit
------------------------------------------------------------------------
### `++glue`
Skip delimiter
++ glue :: add rule
~/ %glue
|* bus=_rule
~/ %fun
|* [vex=edge sab=_rule]
(plug vex ;~(pfix bus sab))
::
Parsing composer: connects an edge `vex` with a following rule `sab` by
parsing the rule `bus` (the delimiting symbol) and throwing out the
result.
`bus` is a [rule]().
`sab` is a [rule]().
`vex` is an [edge]().
~zod/try=> (scan "200|mal|bon" ;~((glue bar) dem sym sym))
[q=200 7.102.829 7.237.474]
~zod/try=> `[@u @tas @tas]`(scan "200|mal|bon" ;~((glue bar) dem sym sym))
[200 %mal %bon]
~zod/try=> (scan "200|;|bon" ;~((glue bar) dem sem sym))
[q=200 ~~~3b. 7.237.474]
~zod/try=> (scan "200.;.bon" ;~((glue dot) dem sem sym))
[q=200 ~~~3b. 7.237.474]
------------------------------------------------------------------------
### `++less`
Parse unless
++ less :: no first and second
|* [vex=edge sab=_rule]
?~ q.vex
=+ roq=(sab)
[p=(last p.vex p.roq) q=q.roq]
vex(q ~)
::
Parsing composer: if an edge `vex` reflects a success, fail. Otherwise,
connect `vex` with the following rule.
`sab` is a [rule]().
`vex` is an [edge]().
~zod/try=> (scan "sas-/lo" (star ;~(less lus bar prn)))
"sas-/lo"
~zod/try=> (scan "sas-/l+o" (star ;~(less lus bar prn)))
! {1 8}
! exit
~zod/try=> (scan "sas|-/lo" (star ;~(less lus bar prn)))
! {1 5}
! exit
------------------------------------------------------------------------
### `++pfix`
Discard first rule
++ pfix :: discard first rule
~/ %pfix
(comp |*([a=* b=*] b))
::
Parsing composer: connects an [edge]() `vex` with two subsequent rules,
ignoring the result of the first and producing the result of the second.
`vex` is an [edge]().
~zod/try=> `@t`(scan "%him" ;~(pfix cen sym))
'him'
~zod/try=> (scan "+++10" ;~(pfix (star lus) dem))
q=10
------------------------------------------------------------------------
### `++plug`
Parse to tuple
++ plug :: first then second
~/ %plug
|* [vex=edge sab=_rule]
?~ q.vex
vex
=+ yit=(sab q.u.q.vex)
=+ yur=(last p.vex p.yit)
?~ q.yit
[p=yur q=q.yit]
[p=yur q=[~ u=[p=[p.u.q.vex p.u.q.yit] q=q.u.q.yit]]]
::
Parsing composer: connects `vex` with a following rule `sab`, producing
a cell of both the results. See also: the monad applicator [;\~]() for a
more detailed explanation.
`sab` is a [rule]().
`vex` is an [edge]().
~zod/try=> (scan "1..20" ;~(plug dem dot dot dem))
[q=1 ~~~. ~~~. q=20]
~zod/try=> (scan "moke/~2014.1.1" ;~(plug sym fas nuck:so))
[1.701.539.693 ~~~2f. [% p=[p=~.da q=170.141.184.500.766.106.671.844.917.172.921.958.400]]]
~zod/try=> ;;(,[@tas @t ~ %da @da] (scan "moke/~2014.1.1" ;~(plug sym fas nuck:so)))
[%moke '/' ~ %da ~2014.1.1]
------------------------------------------------------------------------
### `++pose`
Parse options
++ pose :: first or second
~/ %pose
|* [vex=edge sab=_rule]
?~ q.vex
=+ roq=(sab)
[p=(last p.vex p.roq) q=q.roq]
vex
Parsing composer: if `vex` reflects a failure, connect it with the
following rule `sab`. See also: the monad applicator [;\~]()
`sab` is a [rule]().
`vex` is an [edge]().
~zod/try=> `@t`(scan "+" ;~(pose lus tar cen))
'+'
~zod/try=> `@t`(scan "*" ;~(pose lus tar cen))
'*'
~zod/try=> `@t`(scan "%" ;~(pose lus tar cen))
'%'
~zod/try=> `@t`(scan "-" ;~(pose lus tar cen))
! {1 1}
! exit
------------------------------------------------------------------------
### `++simu`
First and second
++ simu :: first and second
|* [vex=edge sab=_rule]
?~ q.vex
vex
=+ roq=(sab)
roq
::
Parsing composer: if an edge `vex` reflects a failure, fail. Otherwise,
connect `vex` with the following rule.
`sab` is a [rule]().
`vex` is an [edge]().
~zod/try=> (scan "~zod" scat:vast)
[%dtzy p=%p q=0]
~zod/try=> (scan "%zod" scat:vast)
[%dtzz p=%tas q=6.582.138]
~zod/try=> (scan "%zod" ;~(simu cen scat:vast))
[%dtzz p=%tas q=6.582.138]
~zod/try=> (scan "~zod" ;~(simu cen scat:vast))
! {1 1}
! exit
------------------------------------------------------------------------
### `++sfix`
Discard second rule
++ sfix :: discard second rule
~/ %sfix
(comp |*([a=* b=*] a))
Parsing composer: connects `vex` with two subsequent rules returning the
result of the first and discarding the result of the second.
`a` is the result of parsing the first [rule]().
`b` is the result of of parsing the second [rule]().
~zod/try=> `@t`(scan "him%" ;~(sfix sym cen))
'him'
~zod/try=> (scan "10+++" ;~(sfix dem (star lus)))
q=10
------------------------------------------------------------------------

View File

@ -1,195 +0,0 @@
section 2eE, parsing (composers)
================================
### `++bass`
++ bass
|* [wuc=@ tyd=_rule]
%+ cook
|= waq=(list ,@)
%+ roll
waq
=|([p=@ q=@] |.((add p (mul wuc q))))
tyd
::
Parser modifier:
[LSB](http://en.wikipedia.org/wiki/Least_significant_bit) ordered list
as atom of a base.
`wuc` is an [atom]().
`tyd` is a [rule]().
~zod/try=> (scan "123" (bass 10 (star dit)))
q=123
~zod/try=> (scan "123" (bass 8 (star dit)))
q=83
~zod/try=> `@ub`(scan "123" (bass 8 (star dit)))
0b101.0011
------------------------------------------------------------------------
### `++boss`
++ boss
|* [wuc=@ tyd=_rule]
%+ cook
|= waq=(list ,@)
%+ reel
waq
=|([p=@ q=@] |.((add p (mul wuc q))))
tyd
::
Parser modifier:
[LSB](http://en.wikipedia.org/wiki/Least_significant_bit) ordered list
as atom of a base.
`wuc` is an [atom]().
`tyd` is a [rule]().
~zod/try=> (scan "123" (boss 10 (star dit)))
q=321
~zod/try=> `@t`(scan "bam" (boss 256 (star alp)))
'bam'
~zod/try=> `@ux`(scan "bam" (boss 256 (star alp)))
0x6d.6162
------------------------------------------------------------------------
### `++ifix`
++ ifix
|* [fel=[p=_rule q=_rule] hof=_rule]
;~(pfix p.fel ;~(sfix hof q.fel))
::
Parser modifier: surround with pair of rules, output of which is
discarded.
`fel` is a pair of [rule]()s.
`hof` is a [rule]().
~zod/try=> (scan "-40-" (ifix [hep hep] dem))
q=40
~zod/try=> (scan "4my4" (ifix [dit dit] (star alf)))
"my"
------------------------------------------------------------------------
### `++more`
++ more
|* [bus=_rule fel=_rule]
;~(pose (most bus fel) (easy ~))
::
Parser modifier: using a delimiter rule, parse a list of matches.
`bus` is a [rule]().
`fel` is a [rule]().
~zod/try=> (scan "" (more ace dem))
~
~zod/try=> (scan "40 20" (more ace dem))
[q=40 ~[q=20]]
~zod/try=> (scan "40 20 60 1 5" (more ace dem))
[q=40 ~[q=20 q=60 q=1 q=5]]
------------------------------------------------------------------------
### `++most`
++ most
|* [bus=_rule fel=_rule]
;~(plug fel (star ;~(pfix bus fel)))
::
Parser modifier: using a delimiter rule, parse a list of at least one
match.
`bus` is a [rule]().
`fel` is a [rule]().
~zod/try=> (scan "40 20" (most ace dem))
[q=40 ~[q=20]]
~zod/try=> (scan "40 20 60 1 5" (most ace dem))
[q=40 ~[q=20 q=60 q=1 q=5]]
~zod/try=> (scan "" (most ace dem))
! {1 1}
! exit
------------------------------------------------------------------------
### `++plus`
++ plus |*(fel=_rule ;~(plug fel (star fel)))
Parser modifier: parse list of at least one match
`fel` is a [rule]().
~zod/try=> (scan ">>>>" (cook lent (plus gar)))
4
~zod/try=> (scan "- - " (plus ;~(pose ace hep)))
[~~- " - "]
~zod/try=> `tape`(scan "- - " (plus ;~(pose ace hep)))
"- - "
~zod/try=> `(pole ,@t)`(scan "- - " (plus ;~(pose ace hep)))
['-' [' ' [' ' ['-' [' ' ~]]]]]
------------------------------------------------------------------------
### `++slug`
++ slug
|* raq=_|*([a=* b=*] [a b])
|* [bus=_rule fel=_rule]
;~((comp raq) fel (stir rud raq ;~(pfix bus fel)))
::
Parser modifier: By composing with a gate, parse a delimited list of
matches.
`bus` is a [rule]().
`fel` is a [rule]().
~zod/try=> (scan "20+5+110" ((slug add) lus dem))
135
~zod/try=> `@t`(scan "a b c" ((slug |=(a=[@ @t] (cat 3 a))) ace alp))
'abc'
------------------------------------------------------------------------
### `++star`
++ star :: 0 or more times
|* fel=_rule
(stir `(list ,_(wonk *fel))`~ |*([a=* b=*] [a b]) fel)
Parser modifier: parse list of matches.
`fel` is a [rule]().
~zod/try=> (scan "aaaaa" (just 'a'))
! {1 2}
! 'syntax-error'
! exit
~zod/try=> (scan "aaaaa" (star (just 'a')))
"aaaaa"
~zod/try=> (scan "abcdef" (star (just 'a')))
! {1 2}
! 'syntax-error'
! exit
~zod/try=> (scan "abcabc" (star (jest 'abc')))
<|abc abc|>
~zod/try=> (scan "john smith" (star (shim 0 200)))
"john smith"
------------------------------------------------------------------------

View File

@ -1,648 +0,0 @@
section 2eF, parsing (ascii)
============================
### `++ace`
Parse space
++ ace (just ' ')
Parses ASCII character 32, space.
~zod/try=> (scan " " ace)
~~.
~zod/try=> `cord`(scan " " ace)
' '
~zod/try=> (ace [[1 1] " "])
[p=[p=1 q=2] q=[~ [p=~~. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (ace [[1 1] " abc "])
[p=[p=1 q=2] q=[~ [p=~~. q=[p=[p=1 q=2] q="abc "]]]]
------------------------------------------------------------------------
### `++bar`
Parse vertical bar
++ bar (just '|')
Parses ASCII character 124, the vertical bar.
~zod/try=> (scan "|" bar)
~~~7c.
~zod/try=> `cord`(scan "|" bar)
'|'
~zod/try=> (bar [[1 1] "|"])
[p=[p=1 q=2] q=[~ [p=~~~7c. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (bar [[1 1] "|="])
[p=[p=1 q=2] q=[~ [p=~~~7c. q=[p=[p=1 q=2] q="="]]]]
------------------------------------------------------------------------
### `++bas`
Parse backslash
++ bas (just '\\')
Parses ASCII character 92, the backslash. Note the extra `\` in the slam
of `bas` with [`++just`](/doc/hoon/library/2ec#++just) is to escape the escape character, `\`.
~zod/try=> (scan "\\" bas)
~~~5c.
~zod/try=> `cord`(scan "\\" bas)
'\'
~zod/try=> (bas [[1 1] "\"])
~ <syntax error at [1 18]>
~zod/try=> (bas [[1 1] "\\"])
[p=[p=1 q=2] q=[~ [p=~~~5c. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (bas [[1 1] "\""])
[p=[p=1 q=1] q=~]
------------------------------------------------------------------------
### `++buc`
Parse dollar sign
++ buc (just '$')
Parses ASCII character 36, the dollar sign.
~zod/try=> (scan "$" buc)
~~~24.
~zod/try=> `cord`(scan "$" buc)
'$'
~zod/try=> (buc [[1 1] "$"])
[p=[p=1 q=2] q=[~ [p=~~~24. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (buc [[1 1] "$%"])
[p=[p=1 q=2] q=[~ [p=~~~24. q=[p=[p=1 q=2] q="%"]]]]
------------------------------------------------------------------------
### `++cab`
Parse underscore
++ cab (just '_')
Parses ASCII character 95, the underscore.
~zod/try=> (scan "_" cab)
~~~5f.
~zod/try=> `cord`(scan "_" cab)
'_'
~zod/try=> (cab [[1 1] "_"])
[p=[p=1 q=2] q=[~ [p=~~~5f. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (cab [[1 1] "|_"])
[p=[p=1 q=1] q=~]
------------------------------------------------------------------------
### `++cen`
Parses percent sign
++ cen (just '%')
Parses ASCII character 37, the percent sign.
~zod/try=> (scan "%" cen)
~~~25.
~zod/try=> `cord`(scan "%" cen)
'%'
~zod/try=> (cen [[1 1] "%"])
[p=[p=1 q=2] q=[~ [p=~~~25. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (cen [[1 1] "%^"])
[p=[p=1 q=2] q=[~ [p=~~~25. q=[p=[p=1 q=2] q="^"]]]]
------------------------------------------------------------------------
### `++col`
Parse colon
++ col (just ':')
Parses ASCII character 58, the colon
~zod/try=> (scan ":" col)
~~~3a.
~zod/try=> `cord`(scan ":" col)
':'
~zod/try=> (col [[1 1] ":"])
[p=[p=1 q=2] q=[~ [p=~~~3a. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (col [[1 1] ":-"])
[p=[p=1 q=2] q=[~ [p=~~~3a. q=[p=[p=1 q=2] q="-"]]]]
------------------------------------------------------------------------
### `++com`
Parse comma
++ com (just ',')
Parses ASCII character 44, the comma.
~zod/try=> (scan "," com)
~~~2c.
~zod/try=> `cord`(scan "," com)
','
~zod/try=> (com [[1 1] ","])
[p=[p=1 q=2] q=[~ [p=~~~2c. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (com [[1 1] "not com"])
[p=[p=1 q=1] q=~]
------------------------------------------------------------------------
### `++doq`
Parse double quote
++ doq (just '"')
Parses ASCII character 34, the double quote.
~tadbyl-hilbel/try=> (scan "\"" doq)
~~~22.
~tadbyl-hilbel/try=> `cord`(scan "\"" doq)
'"'
~tadbyl-hilbel/try=> (doq [[1 1] "\""])
[p=[p=1 q=2] q=[~ [p=~~~22. q=[p=[p=1 q=2] q=""]]]]
~tadbyl-hilbel/try=> (doq [[1 1] "not successfully parsed"])
[p=[p=1 q=1] q=~]
~tadbyl-hilbel/try=> (scan "see?" doq)
! {1 1}
! 'syntax-error'
! exit
------------------------------------------------------------------------
### `++dot`
Parse period
++ dot (just '.')
Parses ASCII character 46, the period.
~zod/try=> (scan "." dot)
~~~.
~zod/try=> `cord`(scan "." dot)
'.'
~zod/try=> (dot [[1 1] "."])
[p=[p=1 q=2] q=[~ [p=~~~. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (dot [[1 1] ".^"])
[p=[p=1 q=2] q=[~ [p=~~~. q=[p=[p=1 q=2] q="^"]]]]
------------------------------------------------------------------------
### `++fas`
Parse forward slash
++ fas (just '/')
Parses ASCII character 47, the forward slash.
~zod/try=> (scan "/" fas)
~~~2f.
~zod/try=> `cord`(scan "/" fas)
'/'
~zod/try=> (fas [[1 1] "/"])
[p=[p=1 q=2] q=[~ [p=~~~2f. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (fas [[1 1] "|/"])
[p=[p=1 q=1] q=~]
------------------------------------------------------------------------
### `++gal`
Parse less-than sign
++ gal (just '<')
Parses ASCII character 60, the less-than sign.
~zod/try=> (scan "<" gal)
~~~3c.
~zod/try=> `cord`(scan "<" gal)
'<'
~zod/try=> (gal [[1 1] "<"])
[p=[p=1 q=2] q=[~ [p=~~~3c. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (gal [[1 1] "<+"])
[p=[p=1 q=2] q=[~ [p=~~~3c. q=[p=[p=1 q=2] q="+"]]]]
~zod/try=> (gal [[1 1] "+<"])
[p=[p=1 q=1] q=~]
------------------------------------------------------------------------
### `++gar`
Parse greater-than sign
++ gar (just '>')
Parses ASCII character 62, the greater-than sign.
~zod/try=> (scan ">" gar)
~~~3e.
~zod/try=> `cord`(scan ">" gar)
'>'
~zod/try=> (gar [[1 1] ">"])
[p=[p=1 q=2] q=[~ [p=~~~3e. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (gar [[1 1] "=>"])
[p=[p=1 q=1] q=~]
------------------------------------------------------------------------
### `++hax`
Parse number sign
++ hax (just '#')
Parses ASCII character 35, the number sign.
~zod/try=> (scan "#" hax)
~~~23.
~zod/try=> `cord`(scan "#" hax)
'#'
~zod/try=> (hax [[1 1] "#"])
[p=[p=1 q=2] q=[~ [p=~~~23. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (hax [[1 1] "#!"])
[p=[p=1 q=2] q=[~ [p=~~~23. q=[p=[p=1 q=2] q="!"]]]]
------------------------------------------------------------------------
### `++kel`
Parse left curley bracket
++ kel (just '{')
Parses ASCII character 123, the left curly bracket. Note that `{`
(`kel`) and `}` (`ker`) open and close a Hoon expression for Hoon string
interpolation. To parse either of them, they must be escaped.
~zod/try=> (scan "\{" kel)
~~~7b.
~zod/try=> `cord`(scan "\{" kel)
'{'
~zod/try=> (kel [[1 1] "\{"])
[p=[p=1 q=2] q=[~ [p=~~~7b. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (kel [[1 1] " \{"])
[p=[p=1 q=1] q=~]
------------------------------------------------------------------------
### `++ker`
Parse right curley bracket
++ ker (just '}')
Parses ASCII character 125, the right curly bracket. Note that `{`
(`kel`) and `}` (`ker`) open and close a Hoon expression for Hoon string
interpolation. To parse either of them, they must be escaped.
~zod/try=> (scan "}" ker)
~~~7d.
~zod/try=> `cord`(scan "}" ker)
'}'
~zod/try=> (ker [[1 1] "}"])
[p=[p=1 q=2] q=[~ [p=~~~7d. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (ker [[1 1] "\{}"])
[p=[p=1 q=1] q=~]
------------------------------------------------------------------------
### `++ket`
Parse caret
++ ket (just '^')
Parses ASCII character 94, the caret.
~zod/try=> (scan "^" ket)
~~~5e.
~zod/try=> `cord`(scan "^" ket)
'^'
~zod/try=> (ket [[1 1] "^"])
[p=[p=1 q=2] q=[~ [p=~~~5e. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (ket [[1 1] ".^"])
[p=[p=1 q=1] q=~]
------------------------------------------------------------------------
### `++lus`
Parse plus sign
++ lus (just '+')
Parses ASCII character 43, the plus sign.
~zod/try=> (scan "+" lus)
~~~2b.
~zod/try=> `cord`(scan "+" lus)
'+'
~zod/try=> (lus [[1 1] "+"])
[p=[p=1 q=2] q=[~ [p=~~~2b. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (lus [[1 1] ".+"])
[p=[p=1 q=1] q=~]
------------------------------------------------------------------------
### `++hep`
Parse hyphen
++ hep (just '-')
Parses ASCII character 45, the hyphen.
~zod/try=> (scan "-" hep)
~~-
~zod/try=> `cord`(scan "-" hep)
'-'
~zod/try=> (hep [[1 1] "-"])
[p=[p=1 q=2] q=[~ [p=~~- q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (hep [[1 1] ":-"])
[p=[p=1 q=1] q=~]
------------------------------------------------------------------------
### `++pel`
Parse left parenthesis
++ pel (just '(')
Parses ASCII character 40, the left parenthesis.
~zod/try=> (scan "(" pel)
~~~28.
~zod/try=> `cord`(scan "(" pel)
'('
~zod/try=> (pel [[1 1] "("])
[p=[p=1 q=2] q=[~ [p=~~~28. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (pel [[1 1] ";("])
[p=[p=1 q=1] q=~]
------------------------------------------------------------------------
### `++pam`
Parse ampersand
++ pam (just '&')
Parses ASCII character 38, the ampersand.
~zod/try=> (scan "&" pam)
~~~26.
~zod/try=> `cord`(scan "&" pam)
'&'
~zod/try=> (pam [[1 1] "&"])
[p=[p=1 q=2] q=[~ [p=~~~26. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (pam [[1 1] "?&"])
[p=[p=1 q=1] q=~]
------------------------------------------------------------------------
### `++per`
Parse right parenthesis
++ per (just ')')
Parses ASCII character 41, the right parenthesis.
~zod/try=> (scan ")" per)
~~~29.
~zod/try=> `cord`(scan ")" per)
')'
~zod/try=> (per [[1 1] ")"])
[p=[p=1 q=2] q=[~ [p=~~~29. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (per [[1 1] " )"])
[p=[p=1 q=1] q=~]
------------------------------------------------------------------------
### `++pat`
Parse "at" sign
++ pat (just '@')
Parses ASCII character 64, the "at" sign.
~zod/try=> (scan "@" pat)
~~~4.
~zod/try=> `cord`(scan "@" pat)
'@'
~zod/try=> (pat [[1 1] "@"])
[p=[p=1 q=2] q=[~ [p=~~~4. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (pat [[1 1] "?@"])
[p=[p=1 q=1] q=~]
------------------------------------------------------------------------
### `++sel`
Parse left square bracket
Left square bracket
++ sel (just '[')
Parses ASCII character 91, the left square bracket.
~zod/try=> (scan "[" sel)
~~~5b.
~zod/try=> `cord`(scan "[" sel)
'['
~zod/try=> (sel [[1 1] "["])
[p=[p=1 q=2] q=[~ [p=~~~5b. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (sel [[1 1] "-["])
[p=[p=1 q=1] q=~]
------------------------------------------------------------------------
### `++sem`
Parse semicolon
++ sem (just ';')
Parses ASCII character 59, the semicolon.
### `Examples`
~zod/try=> (scan ";" sem)
~~~3b.
~zod/try=> `cord`(scan ";" sem)
';'
~zod/try=> (sem [[1 1] ";"])
[p=[p=1 q=2] q=[~ [p=~~~3b. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (sem [[1 1] " ;"])
[p=[p=1 q=1] q=~]
------------------------------------------------------------------------
### `++ser`
Parse right square bracket
++ ser (just ']')
Parses ASCII character 93, the right square bracket.
~zod/try=> (scan "]" ser)
~~~5d.
~zod/try=> `cord`(scan "]" ser)
']'
~zod/try=> (ser [[1 1] "]"])
[p=[p=1 q=2] q=[~ [p=~~~5d. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (ser [[1 1] "[ ]"])
[p=[p=1 q=1] q=~]
------------------------------------------------------------------------
### `++sig`
Parse tilde
++ sig (just '~')
Parses ASCII character 126, the tilde.
~zod/try=> (scan "~" sig)
~~~~
~zod/try=> `cord`(scan "~" sig)
'~'
~zod/try=> (sig [[1 1] "~"])
[p=[p=1 q=2] q=[~ [p=~~~~ q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (sig [[1 1] "?~"])
[p=[p=1 q=1] q=~]
------------------------------------------------------------------------
### `++soq`
Parse single quote
++ soq (just '\'')
Parses ASCII character 39, soq. Note the extra '' is to escape the first
`soq` because soq delimits a cord.
~zod/try=> (scan "'" soq)
~~~27.
~zod/try=> `cord`(scan "'" soq)
'''
~zod/try=> (soq [[1 1] "'"])
[p=[p=1 q=2] q=[~ [p=~~~27. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (soq [[1 1] ">'"])
[p=[p=1 q=1] q=~]
------------------------------------------------------------------------
### `++tar`
Parse asterisk
++ tar (just '*')
Parses ASCII character 42, the asterisk.
~zod/try=> (scan "*" tar)
~~~2a.
~zod/try=> `cord`(scan "*" tar)
'*'
~zod/try=> (tar [[1 1] "*"])
[p=[p=1 q=2] q=[~ [p=~~~2a. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (tar [[1 1] ".*"])
[p=[p=1 q=1] q=~]
------------------------------------------------------------------------
### `++tec`
Parse backtick
++ tec (just '`') :: backTiCk
Parses ASCII character 96, the backtick (also known as the "grave
accent".
~zod/try=> (scan "`" tec)
~~~6.
~zod/try=> `cord`(scan "`" tec)
'`'
~zod/try=> (tec [[1 1] "`"])
[p=[p=1 q=2] q=[~ [p=~~~6. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (tec [[1 1] " `"])
[p=[p=1 q=1] q=~]
------------------------------------------------------------------------
### `++tis`
Parse equals sign
++ tis (just '=')
Parses ASCII character 61, the equals sign.
~zod/try=> (scan "=" tis)
~~~3d.
~zod/try=> `cord`(scan "=" tis)
'='
~zod/try=> (tis [[1 1] "="])
[p=[p=1 q=2] q=[~ [p=~~~3d. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (tis [[1 1] "|="])
[p=[p=1 q=1] q=~]
------------------------------------------------------------------------
### `++wut`
Parses question mark
++ wut (just '?')
Parses ASCII character 63, wut.
~zod/try=> (scan "?" wut)
~~~3f.
~zod/try=> `cord`(scan "?" wut)
'?'
~zod/try=> (wut [[1 1] "?"])
[p=[p=1 q=2] q=[~ [p=~~~3f. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (wut [[1 1] ".?"])
[p=[p=1 q=1] q=~]
------------------------------------------------------------------------
### `++zap`
Exclamation point
++ zap (just '!')
Parses ASCII character 33, the exclamation point zap.
~zod/try=> (scan "!" zap)
~~~21.
~zod/try=> `cord`(scan "!" zap)
'!'
~zod/try=> (zap [[1 1] "!"])
[p=[p=1 q=2] q=[~ [p=~~~21. q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (zap [[1 1] "?!"])
[p=[p=1 q=1] q=~]
------------------------------------------------------------------------

View File

@ -1,160 +0,0 @@
section 2eG, parsing (whitespace)
=================================
### `++dog`
`.` optional gap
++ dog ;~(plug dot gay) ::
Dot followed by an optional gap, used in numbers.
/~zod/try=> 1.234.
703
1.234.703
~zod/try=> (scan "a. " ;~(pfix alf dog))
[~~~. ~]
------------------------------------------------------------------------
### `++doh`
`@p` separator
++ doh ;~(plug ;~(plug hep hep) gay) ::
Phonetic base phrase separator
/~zod/try=> ~nopfel-botduc-nilnev-dolfyn--haspub-natlun-lodmur-holtyd
~nopfel-botduc-nilnev-dolfyn--haspub-natlun-lodmur-holtyd
/~zod/try=> ~nopfel-botduc-nilnev-dolfyn--
haspub-natlun-lodmur-holtyd
~nopfel-botduc-nilnev-dolfyn--haspub-natlun-lodmur-holtyd
~zod/try=> (scan "--" doh)
[[~~- ~~-] ~]
~zod/try=> (scan "-- " doh)
[[~~- ~~-] ~]
------------------------------------------------------------------------
### `++dun`
`--` to `~`
++ dun (cold ~ ;~(plug hep hep)) :: -- (phep) to ~
Parse phep, `--`, to null, `~`.
~zod/try=> (scan "--" dun)
~
~zod/try=> (dun [[1 1] "--"])
[p=[p=1 q=3] q=[~ u=[p=~ q=[p=[p=1 q=3] q=""]]]]
------------------------------------------------------------------------
### `++duz`
`==` to `~`
++ duz (cold ~ ;~(plug tis tis)) :: == (stet) to ~
Parse stet, `==`, to null `~`.
~zod/try=> (scan "==" duz)
~
~zod/try=> (duz [[1 1] "== |=..."])
[p=[p=1 q=3] q=[~ u=[p=~ q=[p=[p=1 q=3] q=" |=..."]]]]
------------------------------------------------------------------------
### `++gah`
Newline or ' '
++ gah (mask [`@`10 ' ' ~]) :: newline or ace
Whitespace component, either newline or space.
/~zod/try=> ^- * :: show spaces
"""
-
-
-
"""
[32 32 32 45 10 32 45 10 32 32 45 0]
/~zod/try=> ^- *
"""
"""
[32 32 32 10 32 10 32 32 0]
/~zod/try=> ^- (list ,@)
%- scan :_ (star gah)
"""
"""
~[32 32 32 10 32 10 32 32]
------------------------------------------------------------------------
### `++gap`
Plural whitespace
++ gap (cold ~ ;~(plug gaq (star ;~(pose vul gah)))) :: plural whitespace
Separates tall runes
------------------------------------------------------------------------
### `++gaq`
End of line
++ gaq ;~ pose :: end of line
(just `@`10)
;~(plug gah ;~(pose gah vul))
vul
==
Two spaces, a newline, or comment.
------------------------------------------------------------------------
### `++gaw`
Classic whitespace
++ gaw (cold ~ (star ;~(pose vul gah))) :: classic white
Terran whitespace
------------------------------------------------------------------------
### `++gay`
Optional gap.
++ gay ;~(pose gap (easy ~)) ::
Optional gap.
------------------------------------------------------------------------
### `++vul`
++ vul %- cold :- ~ :: comments
;~ plug col col
(star prn)
(just `@`10)
==
Parse comments and produce a null. Note that a comment must be ended
with a newline character.
~zod/try=> (scan "::this is a comment \0a" vul)
~
~zod/try=> (scan "::this is a comment " vul)
! {1 21}
! exit
------------------------------------------------------------------------

View File

@ -1,531 +0,0 @@
section 2eH, parsing (idioms)
=============================
### `++alf`
Alphabetic characters
++ alf ;~(pose low hig) :: alphabetic
Parse alphabetic characters, both upper and lowercase.
~zod/try=> (scan "a" alf)
~~a
~zod/try=> (scan "A" alf)
~~~41.
~zod/try=> (scan "AaBbCc" (star alf))
"AaBbCc"
------------------------------------------------------------------------
### `++aln`
Alphanumeric characters
++ aln ;~(pose low hig nud) :: alphanumeric
Parse alphanumeric characters - both alphabetic characters and numbers.
~zod/try=> (scan "0" aln)
~~0
~zod/try=> (scan "alf42" (star aln))
"alf42"
~zod/try=> (scan "0123456789abcdef" (star aln))
"0123456789abcdef"
------------------------------------------------------------------------
### `++alp`
Alphanumeric and `-`
++ alp ;~(pose low hig nud hep) :: alphanumeric and -
Parse alphanumeric strings and hep, "-".
~zod/try=> (scan "7" alp)
~~7
~zod/try=> (scan "s" alp)
~~s
~zod/try=> (scan "123abc-" (star alp))
"123abc-"
------------------------------------------------------------------------
### `++bet`
Axis syntax `-`, `+`
++ bet ;~(pose (cold 2 hep) (cold 3 lus)) :: axis syntax - +
Parse the hep and lus axis syntax.
~zod/try=> (scan "-" bet)
2
~zod/try=> (scan "+" bet)
3
------------------------------------------------------------------------
### `++bin`
Binary to atom
++ bin (bass 2 (most gon but)) :: binary to atom
Parse a tape of binary (0s and 1s) and produce its atomic
representation.
~zod/try=> (scan "0000" bin)
0
~zod/try=> (scan "0001" bin)
1
~zod/try=> (scan "0010" bin)
2
~zod/try=> (scan "100000001111" bin)
2.063
------------------------------------------------------------------------
### `++but`
Binary digit
++ but (cook |=(a=@ (sub a '0')) (shim '0' '1')) :: binary digit
Parse a single binary digit.
~zod/try=> (scan "0" but)
0
~zod/try=> (scan "1" but)
1
~zod/try=> (scan "01" but)
! {1 2}
! 'syntax-error'
! exit
~zod/try=> (scan "01" (star but))
~[0 1]
------------------------------------------------------------------------
### `++cit`
Octal digit
++ cit (cook |=(a=@ (sub a '0')) (shim '0' '7')) :: octal digit
Parse a single octal digit.
~zod/try=> (scan "1" cit)
1
~zod/try=> (scan "7" cit)
7
~zod/try=> (scan "8" cit)
! {1 1}
! 'syntax-error'
! exit
~zod/try=> (scan "60" (star cit))
~[6 0]
------------------------------------------------------------------------
### `++dem`
Decimal to atom
++ dem (bass 10 (most gon dit)) :: decimal to atom
Parse a decimal number to an atom.
~zod/try=> (scan "7" dem)
7
~zod/try=> (scan "42" dem)
42
~zod/try=> (scan "150000000" dem)
150.000.000
~zod/try=> (scan "12456" dem)
12.456
------------------------------------------------------------------------
### `++dit`
Decimal digit
++ dit (cook |=(a=@ (sub a '0')) (shim '0' '9')) :: decimal digit
Parse a single decimal digit.
~zod/try=> (scan "7" dit)
7
~zod/try=> (scan "42" (star dit))
~[4 2]
~zod/try=> (scan "26000" (star dit))
~[2 6 0 0 0]
------------------------------------------------------------------------
### `++gul`
Axis syntax `<` or `>`
++ gul ;~(pose (cold 2 gal) (cold 3 gar)) :: axis syntax < >
Parse the axis gal and gar axis syntax.
~zod/try=> (scan "<" gul)
2
~zod/try=> (scan ">" gul)
3
------------------------------------------------------------------------
### `++gon`
Long numbers
++ gon ;~(pose ;~(plug bas gay fas) (easy ~)) :: long numbers \ /
Parse long numbers - Numbers which wrap around the shell with the line
break characters bas and fas.
~zod/try=> (scan "\\/" gon)
[~~~5c. ~ ~~~2f.]
~zod/try=> (gon [[1 1] "\\/"])
[p=[p=1 q=3] q=[~ u=[p=[~~~5c. ~ ~~~2f.] q=[p=[p=1 q=3] q=""]]]]
------------------------------------------------------------------------
### `++hex`
Hex to atom
++ hex (bass 16 (most gon hit)) :: hex to atom
Parse any hexadecimal number to an atom.
~zod/try=> (scan "a" hex)
10
~zod/try=> (scan "A" hex)
10
~zod/try=> (scan "2A" hex)
42
~zod/try=> (scan "1ee7" hex)
7.911
~zod/try=> (scan "1EE7" hex)
7.911
~zod/try=> (scan "1EE7F7" hex)
2.025.463
~zod/try=> `@ux`(scan "1EE7F7" hex)
0x1e.e7f7
------------------------------------------------------------------------
### `++hig`
Uppercase
++ hig (shim 'A' 'Z') :: uppercase
Parse a single uppercase letter.
~zod/try=> (scan "G" hig)
~~~47.
~zod/try=> `cord`(scan "G" hig)
'G'
~zod/try=> (scan "ABCDEFGHIJKLMNOPQRSTUVWXYZ" (star hig))
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
~zod/try=> (hig [[1 1] "G"])
[p=[p=1 q=2] q=[~ [p=~~~47. q=[p=[p=1 q=2] q=""]]]]
------------------------------------------------------------------------
### `++hit`
Hex digits
++ hit ;~ pose :: hex digits
dit
(cook |=(a=char (sub a 87)) (shim 'a' 'f'))
(cook |=(a=char (sub a 55)) (shim 'A' 'F'))
==
Parse a single hexadecimal digit.
~zod/try=> (scan "a" hit)
10
~zod/try=> (scan "A" hit)
10
~zod/try=> (hit [[1 1] "a"])
[p=[p=1 q=2] q=[~ [p=10 q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (scan "2A" (star hit))
~[2 10]
------------------------------------------------------------------------
### `++low`
Lowercase
++ low (shim 'a' 'z') :: lowercase
Parse a single lowercase letter.
~zod/try=> (scan "g" low)
~~g
~zod/try=> `cord`(scan "g" low)
'g'
~zod/try=> (scan "abcdefghijklmnopqrstuvwxyz" (star low))
"abcdefghijklmnopqrstuvwxyz"
~zod/try=> (low [[1 1] "g"])
[p=[p=1 q=2] q=[~ [p=~~g q=[p=[p=1 q=2] q=""]]]]
------------------------------------------------------------------------
### `++mes`
Hexbyte
++ mes %+ cook :: hexbyte
|=([a=@ b=@] (add (mul 16 a) b))
;~(plug hit hit)
Parse a hexbyte.
~zod/try=> (scan "2A" mes)
42
~zod/try=> (mes [[1 1] "2A"])
[p=[p=1 q=3] q=[~ u=[p=42 q=[p=[p=1 q=3] q=""]]]]
~zod/try=> (scan "42" mes)
66
------------------------------------------------------------------------
### `++nix`
Letters, `-`, and `_`
++ nix (boss 256 (star ;~(pose aln cab))) ::
Letters, `-`, and `_`
~zod/try=> (scan "as_me" nix)
q=435.626.668.897
~zod/try=> `@t`(scan "as_me" nix)
'as_me'
------------------------------------------------------------------------
### `++nud`
Numeric
++ nud (shim '0' '9') :: numeric
Parse a numeric character - A number.
~zod/try=> (scan "0" nud)
~~0
~zod/try=> (scan "7" nud)
~~7
~zod/try=> (nud [[1 1] "1"])
[p=[p=1 q=2] q=[~ [p=~~1 q=[p=[p=1 q=2] q=""]]]]
~zod/try=> (scan "0123456789" (star nud))
"0123456789"
------------------------------------------------------------------------
### `++prn`
Printable character
++ prn ;~(less (just `@`127) (shim 32 256))
Parse any printable character
~zod/try=> (scan "h" prn)
~~h
~zod/try=> (scan "!" prn)
~~~21.
~zod/try=> (scan "\01" prn)
! {1 1}
! exit
------------------------------------------------------------------------
### `++qat`
Chars in blockcord
++ qat ;~ pose :: chars in blockcord
prn
;~(less ;~(plug (just `@`10) soqs) (just `@`10))
==
Parse character in cord block.
~zod/try=> (scan "h" qat)
~~h
~zod/try=> (scan "!" qat)
~~~21.
~zod/try=> (scan "\0a" qat)
~~~a.
~zod/try=> (scan "\00" qat)
! {1 1}
! exit
------------------------------------------------------------------------
### `++qit`
Chars in cord
++ qit ;~ pose :: chars in a cord
;~(less bas soq prn)
;~(pfix bas ;~(pose bas soq mes)) :: escape chars
==
Parse an individual character to its cord atom representation.
~zod/try=> (scan "%" qit)
37
~zod/try=> `@t`(scan "%" qit)
'%'
~zod/try=> (scan "0" qit)
48
~zod/try=> (scan "E" qit)
69
~zod/try=> (scan "a" qit)
97
~zod/try=> (scan "\\0a" qit)
10
~zod/try=> `@ux`(scan "\\0a" qit)
0xa
~zod/try=> (scan "cord" (star qit))
~[99 111 114 100]
------------------------------------------------------------------------
### `++qut`
Cord
++ qut ;~ pose :: cord
;~ less soqs
(ifix [soq soq] (boss 256 (more gon qit)))
==
%- inde %+ ifix
:- ;~ plug soqs
;~(pose ;~(plug (plus ace) vul) (just '\0a'))
==
;~(plug (just '\0a') soqs)
(boss 256 (star qat))
==
::
Parse single-soq cord with `\{gap}/` anywhere in the middle, or
triple-soq cord which must be in an indented block.
~zod/try=> (scan "'cord'" qut)
q=1.685.221.219
~zod/try=> 'cord'
'cord'
~zod/try=> `@ud`'cord'
1.685.221.219
/~zod/try=> '''
Heredoc isn't prohibited from containing quotes
'''
'Heredoc isn't prohibited from containing quotes'
------------------------------------------------------------------------
### `++soqs`
Delimiting `'''`
++ soqs ;~(plug soq soq soq) :: delimiting '''
Triple single quote
~zod/try=> (scan "'''" soqs)
[~~~27. ~~~27. ~~~27.]
~zod/try=> (rash '"""' soqs)
! {1 1}
! exit
------------------------------------------------------------------------
### `++sym`
Term
++ sym
%+ cook
|=(a=tape (rap 3 ^-((list ,@) a)))
;~(plug low (star ;~(pose nud low hep)))
::
A term: a letter(lowercase), followed by letters, numbers, or `-`.
~zod/try=> (scan "sam-2" sym)
215.510.507.891
~zod/try=> `@t`(scan "sam-2" sym)
'sam-2'
~zod/try=> (scan "sym" sym)
7.174.515
------------------------------------------------------------------------
### `++ven`
`+>-` axis syntax
++ ven ;~ (comp |=([a=@ b=@] (peg a b))) :: +>- axis syntax
bet
=+ hom=`?`|
|= tub=nail
^- (like axis)
=+ vex=?:(hom (bet tub) (gul tub))
?~ q.vex
[p.tub [~ 1 tub]]
=+ wag=$(p.tub p.vex, hom !hom, tub q.u.q.vex)
?> ?=(^ q.wag)
[p.wag [~ (peg p.u.q.vex p.u.q.wag) q.u.q.wag]]
==
Axis syntax parser
~zod/arvo=/hoon/hoon> (scan "->+" ven)
11
~zod/arvo=/hoon/hoon> `@ub`(scan "->+" ven)
0b1011
~zod/arvo=/hoon/hoon> (peg (scan "->" ven) (scan "+" ven))
11
~zod/arvo=/hoon/hoon> ->+:[[1 2 [3 4]] 5]
[3 4]
------------------------------------------------------------------------
### `++vit`
Base64 digit
++ vit :: base64 digit
;~ pose
(cook |=(a=@ (sub a 65)) (shim 'A' 'Z'))
(cook |=(a=@ (sub a 71)) (shim 'a' 'z'))
(cook |=(a=@ (add a 4)) (shim '0' '9'))
(cold 62 (just '-'))
(cold 63 (just '+'))
==
Terran base64
~zod/arvo=/hoon/hoon> (scan "C" vit)
2
~zod/arvo=/hoon/hoon> (scan "c" vit)
28
~zod/arvo=/hoon/hoon> (scan "2" vit)
54
~zod/arvo=/hoon/hoon> (scan "-" vit)
62

View File

@ -1,107 +0,0 @@
section 2eI, parsing (external)
===============================
### `++rash`
Parse or crash
++ rash |*([naf=@ sab=_rule] (scan (trip naf) sab)) ::
Parse a cord with a given rule and crash if the cord isn't entirely
parsed.
`naf` is an [atom]().
`sab` is a [rule]().
~zod/try=> (rash 'I was the world in which I walked, and what I saw' (star (shim 0 200)))
"I was the world in which I walked, and what I saw"
~zod/try=> (rash 'abc' (just 'a'))
! {1 2}
! 'syntax-error'
! exit
~zod/try=> (rash 'abc' (jest 'abc'))
'abc'
`~zod/try=> (rash 'abc' (jest 'ab'))
! {1 3}
! 'syntax-error'
! exit
------------------------------------------------------------------------
### `++rush`
Parse or null
++ rush |*([naf=@ sab=_rule] (rust (trip naf) sab))
Parse a given with a given rule and produce null if the cord isn't
entirely parsed.
`naf` is an [atom]().
`sab` is a [rule]().
~zod/try=> (rush 'I was the world in which I walked, and what I saw' (star (shim 0 200)))
[~ "I was the world in which I walked, and what I saw"]
~zod/try=> (rush 'abc' (just 'a'))
~
~zod/try=> (rush 'abc' (jest 'abc'))
[~ 'abc']
~zod/try=> (rush 'abc' (jest 'ac'))
~
~zod/try=> (rush 'abc' (jest 'ab'))
~
------------------------------------------------------------------------
### `++rust`
Parse tape or null
++ rust |* [los=tape sab=_rule]
=+ vex=((full sab) [[1 1] los])
?~(q.vex ~ [~ u=p.u.q.vex])
Parse a tape with a given rule and produce null if the tape isn't
entirely parsed.
`los` is a [tape]().
`sab` is a [rule]().
~zod/try=> (rust "I was the world in which I walked, and what I saw" (star (shim 0 200)))
[~ "I was the world in which I walked, and what I saw"]
~zod/try=> (rust "Or heard or felt came not but from myself;" (star (shim 0 200)))
[~ "Or heard or felt came not but from myself;"]
~zod/try=> (rust "And there I found myself more truly and more strange." (jest 'And there I'))
~
------------------------------------------------------------------------
### `++scan`
Parse tape or crash
++ scan |* [los=tape sab=_rule]
=+ vex=((full sab) [[1 1] los])
?~ q.vex
~_ (show [%m '{%d %d}'] p.p.vex q.p.vex ~)
~|('syntax-error' !!)
p.u.q.vex
Parse a tape with a given rule and crash if the tape isn't entirely
parsed.
`los` is a [tape]().
`sab` is a [rule]().
~zod/try=> (scan "I was the world in which I walked, and what I saw" (star (shim 0 200)))
"I was the world in which I walked, and what I saw"
~zod/try=> (scan "Or heard or felt came not but from myself;" (star (shim 0 200)))
"Or heard or felt came not but from myself;"
~zod/try=> (scan "And there I found myself more truly and more strange." (jest 'And there I'))
! {1 12}
! 'syntax-error'
! exit

View File

@ -1,561 +0,0 @@
section 2eJ, formatting (basic text)
====================================
### `++cass`
To lowercase
++ cass :: lowercase
|= vib=tape
%+ rap 3
(turn vib |=(a=@ ?.(&((gte a 'A') (lte a 'Z')) a (add 32 a))))
::
Produce the case insensitive (all lowercase) cord of a tape.
`vib` is a [tape]().
~zod/try=> (cass "john doe")
7.309.170.810.699.673.450
~zod/try=> `cord`(cass "john doe")
'john doe'
~zod/try=> (cass "abc, 123, !@#")
2.792.832.775.110.938.439.066.079.945.313
~zod/try=> `cord`(cass "abc, 123, !@#")
'abc, 123, !@#'
------------------------------------------------------------------------
### `++cuss`
To uppercase
++ cuss :: uppercase
|= vib=tape
^- @t
%+ rap 3
(turn vib |=(a=@ ?.(&((gte a 'a') (lte a 'z')) a (sub a 32))))
::
Turn all occurances of lowercase letters in any tape into uppercase
letters, as a cord.
`vib` is a [tape]().
~zod/try=> (cuss "john doe")
'JOHN DOE'
~zod/try=> (cuss "abc ABC 123 !@#")
'ABC ABC 123 !@#'
~zod/try=> `@ud`(cuss "abc")
4.407.873
~zod/try=> (cuss "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsQqRrVvWwXxYyZz")
'AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSQQRRVVWWXXYYZZ'
------------------------------------------------------------------------
### `++crip`
Tape to cord
++ crip |=(a=tape `@t`(rap 3 a)) :: tape to cord
Produce cord from a tape.
`a` is a [tape]().
~zod/try=> (crip "john doe")
'john doe'
~zod/try=> (crip "abc 123 !@#")
'abc 123 !@#'
~zod/try=> `@ud`(crip "abc")
6.513.249
------------------------------------------------------------------------
### `++mesc`
Escape special chars
++ mesc :: ctrl code escape
|= vib=tape
^- tape
?~ vib
~
?: =('\\' i.vib)
['\\' '\\' $(vib t.vib)]
?: ?|((gth i.vib 126) (lth i.vib 32) =(39 i.vib))
['\\' (welp ~(rux at i.vib) '/' $(vib t.vib))]
[i.vib $(vib t.vib)]
::
Escape special characters, used in [`++show`](/doc/hoon/library/2ez#++show)
`vib` is a [tape]().
/~zod/try=> (mesc "ham lus")
"ham lus"
/~zod/try=> (mesc "bas\\hur")
"bas\\\\hur"
/~zod/try=> (mesc "as'saß")
"as\0x27/sa\0xc3/\0x9f/"
------------------------------------------------------------------------
### `++runt`
Prepend `n` times
++ runt :: prepend repeatedly
|= [[a=@ b=@] c=tape]
^- tape
?: =(0 a)
c
[b $(a (dec a))]
::
Add `a` repetitions of character `b` to the head of `c`
`a` and `b` are [atom]()s.
`c` is a [tape]().
/~zod/try=> (runt [2 '/'] "ham")
"//ham"
/~zod/try=> (runt [10 'a'] "")
"aaaaaaaaaa"
------------------------------------------------------------------------
### `++sand`
Soft-cast by odor
++ sand :: atom sanity
|= a=@ta
|= b=@ ^- (unit ,@)
?.(((sane a) b) ~ [~ b])
::
Soft-cast validity by odor.
`a` is a [`@ta`]().
`b` is an [atom]().
/~zod/try=> `(unit ,@ta)`((sand %ta) 'sym-som')
[~ ~.sym-som]
/~zod/try=> `(unit ,@ta)`((sand %ta) 'err!')
~
------------------------------------------------------------------------
### `++sane`
Check odor validity
++ sane :: atom sanity
|= a=@ta
|= b=@ ^- ?
?. =(%t (end 3 1 a))
~|(%sane-stub !!)
=+ [inx=0 len=(met 3 b)]
?: =(%tas a)
|- ^- ?
?: =(inx len) &
=+ cur=(cut 3 [inx 1] b)
?& ?| &((gte cur 'a') (lte cur 'z'))
&(=('-' cur) !=(0 inx) !=(len inx))
&(&((gte cur '0') (lte cur '9')) !=(0 inx))
==
$(inx +(inx))
==
?: =(%ta a)
|- ^- ?
?: =(inx len) &
=+ cur=(cut 3 [inx 1] b)
?& ?| &((gte cur 'a') (lte cur 'z'))
&((gte cur '0') (lte cur '9'))
|(=('-' cur) =('~' cur) =('_' cur) =('.' cur))
==
$(inx +(inx))
==
|- ^- ?
?: =(0 b) &
=+ cur=(end 3 1 b)
?: &((lth cur 32) !=(10 cur)) |
=+ len=(teff cur)
?& |(=(1 len) =+(i=1 |-(|(=(i len) &((gte (cut 3 [i 1] b) 128) $(i +(i)))))))
$(b (rsh 3 len b))
==
::
Check validity by odor. Produces a gate.
`a` is a [`@ta`]().
`b` is an [atom]().
/~zod/try=> ((sane %tas) %mol)
%.y
/~zod/try=> ((sane %tas) 'lam')
%.y
/~zod/try=> ((sane %tas) 'more ace')
%.n
------------------------------------------------------------------------
### `++trim`
Tape split
++ trim :: tape split
|= [a=@ b=tape]
^- [p=tape q=tape]
?~ b
[~ ~]
?: =(0 a)
[~ b]
=+ c=$(a (dec a), b t.b)
[[i.b p.c] q.c]
::
Split first `a` characters off tape.
`a` is an [atom]().
`b` is a [tape]().
/~zod/try=> (trim 5 "lasok termun")
[p="lasok" q=" termun"]
/~zod/try=> (trim 5 "zam")
[p="zam" q=""]
------------------------------------------------------------------------
### `++trip`
Cord to tape
++ trip :: cord to tape
~/ %trip
|= a=@ ^- tape
?: =(0 (met 3 a))
~
[^-(@ta (end 3 1 a)) $(a (rsh 3 1 a))]
::
Produce tape from cord.
`a` is an [atom]().
/~zod/try=> (trip 'john doe')
"john doe"
/~zod/try=> (trip 'abc 123 !@#')
"abc 123 !@#"
/~zod/try=> (trip 'abc')
"abc"
------------------------------------------------------------------------
### `++teff`
UTF8 Length
++ teff :: length utf8
|= a=@t ^- @
=+ b=(end 3 1 a)
?: =(0 b)
?>(=(0 a) 0)
?> |((gte b 32) =(10 b))
?:((lte b 127) 1 ?:((lte b 223) 2 ?:((lte b 239) 3 4)))
::
Number of utf8 bytes.
`a` is a [`@t`]().
/~zod/try=> (teff 'a')
1
/~zod/try=> (teff 'ß')
2
------------------------------------------------------------------------
### `++turf`
UTF8 to UTF32 cord
++ turf :: utf8 to utf32
|= a=@t
^- @c
%+ rap 5
|- ^- (list ,@c)
=+ b=(teff a)
?: =(0 b) ~
:- %+ can 0
%+ turn
^- (list ,[p=@ q=@])
?+ b !!
1 [[0 7] ~]
2 [[8 6] [0 5] ~]
3 [[16 6] [8 6] [0 4] ~]
4 [[24 6] [16 6] [8 6] [0 3] ~]
==
|=([p=@ q=@] [q (cut 0 [p q] a)])
$(a (rsh 3 b a))
::
Convert utf8 ([cord]()) to utf32 codepoints.
`a` is a [`@t`]().
/~zod/try=> (turf 'my ßam')
~-my.~df.am
/~zod/try=> 'я тут'
'я тут'
/~zod/try=> (turf 'я тут')
~-~44f..~442.~443.~442.
/~zod/try=> `@ux`'я тут'
0x82.d183.d182.d120.8fd1
/~zod/try=> `@ux`(turf 'я тут')
0x442.0000.0443.0000.0442.0000.0020.0000.044f
------------------------------------------------------------------------
### `++tuba`
UTF8 to UTF32 tape
++ tuba :: utf8 to utf32 tape
|= a=tape
^- (list ,@c)
(rip 5 (turf (rap 3 a))) :: XX horrible
::
Convert tape to list of codepoints.
`a` is a [tape]()
/~zod/try=> (tuba "я тут")
~[~-~44f. ~-. ~-~442. ~-~443. ~-~442.]
/~zod/try=> (tuba "chars")
~[~-c ~-h ~-a ~-r ~-s]
------------------------------------------------------------------------
### `++tufa`
UTF32 to UTF8 tape
++ tufa :: utf32 to utf8 tape
|= a=(list ,@c)
^- tape
?~ a ""
(weld (rip 3 (tuft i.a)) $(a t.a))
::
Wrap list of utf32 codepoints to utf8 [tape]().
`a` is a [list]() of [`@c`]().
/~zod/try=> (tufa ~[~-~44f. ~-. ~-~442. ~-~443. ~-~442.])
"я тут"
/~zod/try=> (tufa ((list ,@c) ~[%a %b 0xb1 %c]))
"ab±c"
------------------------------------------------------------------------
### `++tuft`
UTF32 to UTF8 text
++ tuft :: utf32 to utf8 text
|= a=@c
^- @t
%+ rap 3
|- ^- (list ,@)
?: =(0 a)
~
=+ b=(end 5 1 a)
=+ c=$(a (rsh 5 1 a))
?: (lth b 0x7f)
[b c]
?: (lth b 0x7ff)
:* (mix 0b1100.0000 (cut 0 [6 5] b))
(mix 0b1000.0000 (end 0 6 b))
c
==
?: (lth b 0xffff)
:* (mix 0b1110.0000 (cut 0 [12 4] b))
(mix 0b1000.0000 (cut 0 [6 6] b))
(mix 0b1000.0000 (end 0 6 b))
c
==
:* (mix 0b1111.0000 (cut 0 [18 3] b))
(mix 0b1000.0000 (cut 0 [12 6] b))
(mix 0b1000.0000 (cut 0 [6 6] b))
(mix 0b1000.0000 (end 0 6 b))
c
==
::
Convert utf32 glyph to
[LSB](http://en.wikipedia.org/wiki/Least_significant_bit) utf8 cord.
`a` is a [`@c`]().
/~zod/try=> (tuft `@c`%a)
'a'
/~zod/try=> (tuft `@c`0xb6)
'¶'
------------------------------------------------------------------------
### `++wack`
Coin format encode
++ wack :: coin format
|= a=@ta
^- @ta
=+ b=(rip 3 a)
%+ rap 3
|- ^- tape
?~ b
~
?: =('~' i.b) ['~' '~' $(b t.b)]
?: =('_' i.b) ['~' '-' $(b t.b)]
[i.b $(b t.b)]
::
Escape span `~` as `~~` and `_` as `~-`. Used for printing.
`a` is a [`@ta`]().
/~zod/try=> (wack '~20_sam~')
~.~~20~-sam~~
/~zod/try=> `@t`(wack '~20_sam~')
'~~20~-sam~~'
~zod/try=> ~(rend co %many ~[`ud/5 `ta/'~20_sam'])
"._5_~~.~~20~-sam__"
~zod/try=> ._5_~~.~~20~-sam__
[5 ~.~20_sam]
------------------------------------------------------------------------
### `++wick`
Coin format decode
++ wick :: coin format
|= a=@
^- @ta
=+ b=(rip 3 a)
%+ rap 3
|- ^- tape
?~ b
~
?: =('~' i.b)
?~ t.b !!
[?:(=('~' i.t.b) '~' ?>(=('-' i.t.b) '_')) $(b t.t.b)]
[i.b $(b t.b)]
::
Unescape span `~~` as `~` and `~-` as `_`.
`a` is a an [atom]().
/~zod/try=> `@t`(wick '~-ams~~lop')
'_ams~lop'
/~zod/try=> `@t`(wick (wack '~20_sam~'))
'~20_sam~'
------------------------------------------------------------------------
### `++woad`
Unescape cord
++ woad :: cord format
|= a=@ta
^- @t
%+ rap 3
|- ^- (list ,@)
?: =(0 a)
~
=+ b=(end 3 1 a)
=+ c=(rsh 3 1 a)
?: =('.' b)
[' ' $(a c)]
?. =('~' b)
[b $(a c)]
=> .(b (end 3 1 c), c (rsh 3 1 c))
?+ b =- (weld (rip 3 (tuft p.d)) $(a q.d))
^= d
=+ d=0
|- ^- [p=@ q=@]
?: =('.' b)
[d c]
?< =(0 c)
%= $
b (end 3 1 c)
c (rsh 3 1 c)
d %+ add (mul 16 d)
%+ sub b
?: &((gte b '0') (lte b '9')) 48
?>(&((gte b 'a') (lte b 'z')) 87)
==
%'.' ['.' $(a c)]
%'~' ['~' $(a c)]
==
::
Unescape cord codepoints.
`a` is a [`@ta`]().
/~zod/try=> (woad ~.~b6.20.as)
'¶20 as'
------------------------------------------------------------------------
### `++wood`
Escape cord
++ wood :: cord format
|= a=@t
^- @ta
%+ rap 3
|- ^- (list ,@)
?: =(0 a)
~
=+ b=(teff a)
=+ c=(turf (end 3 b a))
=+ d=$(a (rsh 3 b a))
?: ?| &((gte c 'a') (lte c 'z'))
&((gte c '0') (lte c '9'))
=('-' c)
==
[c d]
?+ c
:- '~'
=+ e=(met 2 c)
|- ^- tape
?: =(0 c)
['.' d]
=. e (dec e)
=+ f=(rsh 2 e c)
[(add ?:((lte f 9) 48 87) f) $(c (end 2 e c))]
::
%' ' ['.' d]
%'.' ['~' '.' d]
%'~' ['~' '~' d]
==
Escape cord codepoints.
`a` is a [`@ta`]().
/~zod/try=> (wood 'my ßam')
~.my.~df.am

View File

@ -1,162 +0,0 @@
section 2eK, formatting (layout)
================================
### `++re`
Pretty-printing engine
++ re
|_ tac=tank
Pretty-printing engine.
`tac` is a [`++tank`](/doc/hoon/library/1#++tank).
/~zod/try=> ~(. re leaf/"ham")
<2.ghl [[%leaf ""] <414.gly 100.xkc 1.ypj %164>]>
### `++ram`
Flatten to tape
++ ram
^- tape
?- -.tac
%leaf p.tac
%palm ram(tac [%rose [p.p.tac (weld q.p.tac r.p.tac) s.p.tac] q.tac])
%rose
%+ weld
q.p.tac
|- ^- tape
?~ q.tac
r.p.tac
=+ voz=$(q.tac t.q.tac)
(weld ram(tac i.q.tac) ?~(t.q.tac voz (weld p.p.tac voz)))
==
::
Flatten tank out into a tape.
/~zod/try=> ~(ram re leaf/"foo")
"foo"
/~zod/try=> ~(ram re rose/["." "(" ")"]^~[leaf/"bar" leaf/"baz" leaf/"bam"])
"(bar.baz.bam)"
### `++win`
Render at indent
++ win
|= [tab=@ edg=@]
=+ lug=`wall`~
|^ |- ^- wall
?- -.tac
%leaf (rig p.tac)
%palm
?: fit
(rig ram)
?~ q.tac
(rig q.p.tac)
?~ t.q.tac
(rig(tab (add 2 tab), lug $(tac i.q.tac)) q.p.tac)
=> .(q.tac `(list tank)`q.tac)
=+ lyn=(mul 2 (lent q.tac))
=+ ^= qyr
|- ^- wall
?~ q.tac
lug
%= ^$
tac i.q.tac
tab (add tab (sub lyn 2))
lug $(q.tac t.q.tac, lyn (sub lyn 2))
==
(wig(lug qyr) q.p.tac)
::
%rose
?: fit
(rig ram)
=+ ^= gyl
|- ^- wall
?~ q.tac
?:(=(%$ r.p.tac) lug (rig r.p.tac))
^$(tac i.q.tac, lug $(q.tac t.q.tac), tab din)
?: =(%$ q.p.tac)
gyl
(wig(lug gyl) q.p.tac)
==
::
Render at indent level `tab` and width `edg`.
`tab` and `edg` are [atom]()s.
/~zod/try=> (~(win re leaf/"samoltekon-lapdok") 0 20)
<<"samoltekon-lapdok">>
/~zod/try=> (~(win re leaf/"samoltekon-lapdok") 0 10)
<<"\/samolt\/" " ekon-l" " apdok" "\/ \/">>
/~zod/try=> (~(win re rose/["--" "[" "]"]^~[leaf/"1423" leaf/"2316"]) 0 20)
<<"[1423--2316]">>
/~zod/try=> (~(win re rose/["--" "[" "]"]^~[leaf/"1423" leaf/"2316"]) 0 10)
<<"[ 1423" " 2316" "]">>
### `++din`
++ din (mod (add 2 tab) (mul 2 (div edg 3)))
XX document
### `++fit`
Fit on one line test
++ fit (lte (lent ram) (sub edg tab))
Determine whether `tac` fits on one line. Internal to `++win`
### `++rig`
Wrap in `\/`
++ rig
|= hom=tape
^- wall
?: (lte (lent hom) (sub edg tab))
[(runt [tab ' '] hom) lug]
=> .(tab (add tab 2), edg (sub edg 2))
=+ mut=(trim (sub edg tab) hom)
:- (runt [(sub tab 2) ' '] ['\\' '/' (weld p.mut `_hom`['\\' '/' ~])])
=> .(hom q.mut)
|-
?~ hom
:- %+ runt
[(sub tab 2) ' ']
['\\' '/' (runt [(sub edg tab) ' '] ['\\' '/' ~])]
lug
=> .(mut (trim (sub edg tab) hom))
[(runt [tab ' '] p.mut) $(hom q.mut)]
::
Wrap tape in `\/` if it doesn't fit at current indentation. Internal to
`++win`
### `++wig`
`++win` render tape
++ wig
|= hom=tape
^- wall
?~ lug
(rig hom)
=+ lin=(lent hom)
=+ wug=:(add 1 tab lin)
?. =+ mir=i.lug
|- ?~ mir
|
?|(=(0 wug) ?&(=(' ' i.mir) $(mir t.mir, wug (dec wug))))
(rig hom) :: ^ XX regular form?
[(runt [tab ' '] (weld hom `tape`[' ' (slag wug i.lug)])) t.lug]
--
--
Render tape. Internal to `++win`.

File diff suppressed because it is too large Load Diff

View File

@ -1,758 +0,0 @@
section 2eM, regular-expressions
================================
### `++pars`
++ pars
|= [a=tape] :: parse tape to rege
^- (unit rege)
=+ foo=((full apex:rags) [[1 1] a])
?~ q.foo
~
[~ p.u.q.foo]
::
Parse regular expression
~zod/try=> (pars "samo")
[ ~
[ %pair
p=[%lite p=~~s]
q=[%pair p=[%lite p=~~a] q=[%pair p=[%lite p=~~m] q=[%lite p=~~o]]]
]
]
~zod/try=> (pars "so[,.0-9]")
[ ~
[ %pair
p=[%lite p=~~s]
q=[%pair p=[%lite p=~~o] q=[%brac p=288.036.862.105.223.168]]
]
]
~zod/try=> `@ub`288.036.862.105.223.168
0b11.1111.1111.0101.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000
~zod/try=> `@ub`(lsh 0 `@`'9' 1)
0b10.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000
~zod/try=> `@ub`(roll (turn ",.0123456789" |=(a=@ (lsh 0 a 1))) con)
0b11.1111.1111.0101.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000
~zod/try=> (pars "sop.*")
[ ~
[ %pair
p=[%lite p=~~s]
q=[%pair p=[%lite p=~~o] q=[%pair p=[%lite p=~~p] q=[%mant p=%dote]]]
]
]
~zod/try=> (pars "(hel)?")
[ ~
[ %eith
p
[ %capt
p=[%pair p=[%lite p=~~h] q=[%pair p=[%lite p=~~e] q=[%lite p=~~l]]]
q=0
]
q=%empt
]
]
~zod/try=> (pars "(hel)??")
[ ~
[ %eith
p=%empt
q
[ %capt
p=[%pair p=[%lite p=~~h] q=[%pair p=[%lite p=~~e] q=[%lite p=~~l]]]
q=0
]
]
]
~zod/try=> (pars "a\{1,20}")
[~ [%betw p=[%lite p=~~a] q=1 r=20]]
### `++rags`
++ rags :: rege parsers
=> |%
Regex parser arms
### `++nor`
++ nor ;~(less (mask "^$()|*?+.[\\") (shim 1 127)) :: non-control char
XX document
### `++les`
++ les ;~(less bas asp) :: not backslash
XX document
### `++lep`
++ lep ;~(less (mask "^[]\\") asp) :: charset non-control
XX document
### `++asp`
++ asp (shim 32 126) :: printable ascii
XX document
### `++alb`
++ alb ;~(less ser asp) :: charset literal char
XX document
### `++mis`
++ mis ;~(less aln asp) :: non alphanumeric
--
|%
XX document
### `++apex`
++ apex :: top level
%+ knee *rege |. ~+
;~ pose
;~((bend |=(a=[rege rege] (some [%eith a]))) mall ;~(pfix bar apex))
(stag %eith ;~(plug (easy %empt) ;~(pfix bar apex)))
(easy %empt)
==
::
XX document
### `++mall`
++ mall
%+ knee *rege |. ~+
;~((bend |=(a=[rege rege] (some [%pair a]))) bets mall)
::
XX document
### `++bets`
++ bets
%+ knee *rege |. ~+
|= tub=nail
=+ vex=(chun tub)
?~ q.vex
vex
=+ a=p.u.q.vex
%- ;~ pose
(cold [%eith %empt a] (jest '??'))
(cold [%manl a] (jest '*?'))
(cold [%plll a] (jest '+?'))
(cold [%eith a %empt] wut)
(cold [%mant a] tar)
(cold [%plls a] lus)
(stag %betl ;~(plug (easy a) ;~(sfix rang wut)))
(stag %betw ;~(plug (easy a) rang))
(stag %binl ;~(plug (easy a) (ifix [kel (jest ',}?')] dim:ag)))
(stag %bant ;~(plug (easy a) (ifix [kel (jest '}?')] dim:ag)))
(stag %bant ;~(plug (easy a) (ifix [kel ker] dim:ag)))
(stag %bint ;~(plug (easy a) (ifix [kel (jest ',}')] dim:ag)))
(easy a)
==
q.u.q.vex
::
XX document
### `++ranc`
++ ranc
|= [a=@ b=@]
^- @
?:((gth a b) 0 (con (bex a) $(a +(a))))
::
XX document
### `++flap`
++ flap |=(a=@ (mix a (dec (bex 256))))
::
XX document
### `++rang`
++ rang
%+ sear |=([a=@ b=@] ?:((lte a b) (some [a b]) ~))
(ifix [kel ker] ;~(plug dim:ag ;~(pfix com dim:ag)))
::
XX document
### `++chun`
++ chun
%+ knee *rege |. ~+
;~ pose
(cold %ende buc)
(cold %sart ket)
(cold %dote dot)
%+ cook |=(a=(list char) (reel a |=([p=char q=rege] [%pair [%lite p] q])))
;~(pfix (jest '\\Q') cape)
|= tub=nail
=+ foo=;~(plug kel dim:ag ;~(pose ker (jest ',}') ;~(plug com dim:ag ker)))
=+ bar=(foo tub)
?~(q.bar (chad tub) (fail tub))
(cook |=([a=rege] [%capt a 0]) (ifix [pel per] apex))
%+ cook |=([a=rege] [%capt a 0])
(ifix [;~(plug (jest '(?P<') (plus aln) gar) per] apex)
(ifix [(jest '(?:') per] apex)
(stag %brac ;~(pfix sel seac))
==
::
XX document
### `++seac`
++ seac
|= tub=nail
?~ q.tub
(fail tub)
?: =(i.q.tub '^')
(;~(pfix ket (cook flap sead)) tub)
(sead tub)
::
XX document
### `++sead`
++ sead
%+ knee *@ |. ~+
;~ pose
|= tub=nail
?~ q.tub
(fail tub)
?. =(i.q.tub ']')
(fail tub)
?~ t.q.tub
(fail tub)
?: =(i.t.q.tub '-')
?~ t.t.q.tub
(fail tub)
?: =(i.t.t.q.tub ']')
(;~(pfix ser (cook |=(a=@ (con (bex ']') a)) sade)) tub)
(fail tub)
(;~(pfix ser (cook |=(a=@ (con (bex ']') a)) sade)) tub)
|= tub=nail
?~ q.tub
(fail tub)
?. =(i.q.tub '-')
(fail tub)
?~ t.q.tub
(fail tub)
?: =(i.t.q.tub '-')
?~ t.t.q.tub
(fail tub)
?: =(i.t.t.q.tub ']')
(;~(pfix hep (cook |=(a=@ (con (bex '-') a)) sade)) tub)
(fail tub)
(;~(pfix hep (cook |=(a=@ (con (bex '-') a)) sade)) tub)
(cook |=(a=[@ @] (con a)) ;~(plug seap sade))
==
::
XX document
### `++sade`
++ sade
%+ knee *@ |. ~+
;~ pose
(cold (bex '-') (jest '-]'))
(cold 0 ser)
(cook |=([p=@ q=@] `@`(con p q)) ;~(plug seap sade))
==
::
XX document
### `++seap`
++ seap
%+ knee *@ |. ~+
;~ pose
unid
%+ ifix (jest '[:')^(jest ':]')
;~(pose ;~(pfix ket (cook flap chas)) chas)
%+ sear |=([a=@ b=@] ?:((gth a b) ~ (some (ranc a b))))
;~(plug asp ;~(pfix hep alb))
|= tub=nail
?~ q.tub
(fail tub)
?~ t.q.tub
((cook bex les) tub)
?: =(i.t.q.tub '-')
?~ t.t.q.tub
((cook bex les) tub)
?: =(i.t.t.q.tub ']')
((cook bex les) tub)
(fail tub)
((cook bex les) tub)
;~(pfix bas escd)
==
::
XX document
### `++cape`
++ cape
%+ knee *tape |. ~+
;~ pose
(cold ~ (jest '\\E'))
;~(plug next cape)
(cook |=(a=char (tape [a ~])) next)
(full (easy ~))
==
XX document
### `++chas`
++ chas :: ascii character set
=- (sear ~(get by -) sym)
%- mo ^- (list ,[@tas @I])
:~ alnum/alnum alpha/alpha ascii/ascii blank/blank cntrl/cntrl
digit/digit graph/graph lower/lower print/print punct/punct
space/space upper/upper word/wordc xdigit/xdigit
==
:: Character sets
++ alnum :(con lower upper digit)
XX document
###++alpha
++ alpha :(con lower upper)
XX document
###++ascii
++ ascii (ranc 0 127)
++ blank (con (bex 32) (bex 9))
XX document
### `++cntrl`
++ cntrl :(con (ranc 0 31) (bex 127))
XX document
### `++digit`
++ digit (ranc '0' '9')
XX document
### `++graph`
++ graph (ranc 33 126)
XX document
### `++lower`
++ lower (ranc 'a' 'z')
XX document
### `++print`
++ print (ranc 32 126)
XX document
### `++punct`
++ punct ;: con
(ranc '!' '/')
(ranc ':' '@')
(ranc '[' '`')
(ranc '{' '~')
==
XX document
### `++space`
++ space :(con (ranc 9 13) (bex ' '))
XX document
### `++upper`
++ upper (ranc 'A' 'Z')
XX document
### `++white`
++ white :(con (bex ' ') (ranc 9 10) (ranc 12 13))
XX document
### `++wordc`
++ wordc :(con digit lower upper (bex '_'))
XX document
### `++xdigit`
++ xdigit :(con (ranc 'a' 'f') (ranc 'A' 'F') digit)
::
XX document
### `++chad`
++ chad
%+ knee *rege |. ~+
;~(pose (stag %lite nor) (stag %brac unid) ;~(pfix bas escp))
::
XX document
### `++escd`
++ escd
%+ knee *@ |. ~+
;~ pose
(cold (bex 7) (just 'a'))
(cold (bex 9) (just 't'))
(cold (bex 10) (just 'n'))
(cold (bex 11) (just 'v'))
(cold (bex 12) (just 'f'))
(cold (bex 13) (just 'r'))
(cold (bex 0) (just '0'))
(sear |=(a=@ ?:((lth a 256) (some (bex a)) ~)) (bass 8 (stun [2 3] cit)))
(cook bex ;~(pfix (just 'x') (bass 16 (stun [2 2] hit))))
(cook bex (ifix [(jest 'x{') ker] (bass 16 (stun [2 2] hit))))
(cook bex mis)
==
::
XX document
### `++escp`
++ escp
%+ knee *rege |. ~+
;~ pose
(cold %empt (just 'Q'))
(cold [%lite `@tD`0] (just '0'))
(cold [%lite `@tD`7] (just 'a'))
(cold [%lite `@tD`9] (just 't'))
(cold [%lite `@tD`10] (just 'n'))
(cold [%lite `@tD`11] (just 'v'))
(cold [%lite `@tD`12] (just 'f'))
(cold [%lite `@tD`13] (just 'r'))
(sear |=(a=@ ?:((lth a 256) (some [%lite a]) ~)) (bass 8 (stun [2 3] cit)))
(stag %lite ;~(pfix (just 'x') (bass 16 (stun [2 2] hit))))
(stag %lite (ifix [(jest 'x{') ker] (bass 16 (stun [2 2] hit))))
(cold %dote (just 'C'))
(cold %sart (just 'A'))
(cold %ende (just 'z'))
(cold %boun (just 'b'))
(cold %bout (just 'B'))
(stag %brac (cold wordc (just 'w')))
(stag %brac (cold (flap wordc) (just 'W')))
(stag %lite mis)
==
::
XX document
### `++unid`
++ unid
%+ knee *@ |. ~+
;~ pose
(cold digit (jest '\\d'))
(cold (flap digit) (jest '\\D'))
(cold white (jest '\\s'))
(cold (flap white) (jest '\\S'))
(cold wordc (jest '\\w'))
(cold (flap wordc) (jest '\\W'))
==
--
::
XX document
### `++ra`
++ ra :: regex engine
|_ a=rege
XX document
### `++proc`
++ proc :: capture numbering
|= b=@
=- -(+ +>.$(a a))
^- [p=@ a=rege]
?- a
[%capt *] =+ foo=$(a p.a, b +(b))
[p.foo [%capt a.foo b]]
[%eith *] =+ foo=$(a p.a)
=+ bar=$(a q.a, b p.foo)
[p.bar [%eith a.foo a.bar]]
[%pair *] =+ foo=$(a p.a)
=+ bar=$(a q.a, b p.foo)
[p.bar [%pair a.foo a.bar]]
[%manl *] =+ foo=$(a p.a)
[p.foo [%manl a.foo]]
[%plll *] =+ foo=$(a p.a)
[p.foo [%plll a.foo]]
[%binl *] =+ foo=$(a p.a)
[p.foo [%binl a.foo q.a]]
[%betl *] =+ foo=$(a p.a)
[p.foo [%betl a.foo q.a r.a]]
[%mant *] =+ foo=$(a p.a)
[p.foo [%mant a.foo]]
[%plls *] =+ foo=$(a p.a)
[p.foo [%plls a.foo]]
[%bant *] =+ foo=$(a p.a)
[p.foo [%bant a.foo q.a]]
[%bint *] =+ foo=$(a p.a)
[p.foo [%bint a.foo q.a]]
[%betw *] =+ foo=$(a p.a)
[p.foo [%betw a.foo q.a r.a]]
* [b a]
==
::
XX document
### `++cont`
++ cont
|= [a=(map ,@u tape) b=(map ,@u tape)]
(~(gas by _(map ,@u tape)) (weld (~(tap by a)) (~(tap by b))))
::
XX document
### `++abor`
++ abor
|= [a=char b=(unit ,[tape (map ,@u tape)])]
^- (unit ,[tape (map ,@u tape)])
?~ b
b
[~ [[a -.u.b] +.u.b]]
::
XX document
### `++matc`
++ matc
|= [b=tape c=tape]
^- (unit (map ,@u tape))
=+ foo=`(unit ,[tape (map ,@u tape)])`(deep b %empt c)
(bind foo |*(a=^ (~(put by +.a) 0 -.a)))
::
XX document
### `++chet`
++ chet
|= [b=(unit ,[tape (map ,@u tape)]) c=tape d=tape]
^- (unit ,[tape (map ,@u tape)])
?~ b
b
?~ -.u.b
b
=+ bar=(deep (slag (lent -.u.b) c) %empt d)
?~ bar
bar
b
XX document
### `++blak`
++ blak (some ["" _(map ,@u tape)])
XX document
### `++word`
++ word |=(a=char =((dis wordc:rags (bex a)) 0))
XX document
### `++deep`
++ deep
|= [b=tape c=rege d=tape]
^- (unit ,[tape (map ,@u tape)])
?- a
%dote ?~(b ~ (some [[i.b ~] _(map ,@u tape)]))
%ende ?~(b blak ~)
%sart ?:(=(b d) blak ~)
%empt blak
%boun =+ ^= luc
?: =(b d)
&
=+ foo=(slag (dec (sub (lent d) (lent b))) d)
(word -.foo)
=+ cuc=?~(b & (word -.b))
?:(!=(luc cuc) blak ~)
%bout =+ ^= luc
?: =(b d)
&
=+ foo=(slag (dec (sub (lent d) (lent b))) d)
(word -.foo)
=+ cuc=?~(b & (word -.b))
?:(=(luc cuc) blak ~)
[%capt *] =+ foo=$(a p.a)
?~ foo
foo
=+ ft=u.foo
=+ bar=$(a c, b (slag (lent -.ft) b), c %empt)
?~ bar
bar
[~ [-.ft (~(put by +.ft) q.a -.ft)]]
[%lite *] ?~(b ~ ?:(=(i.b p.a) (some [[i.b ~] _(map ,@u tape)]) ~))
[%brac *] ?~ b
~
?. =((dis (bex `@`i.b) p.a) 0)
(some [[i.b ~] _(map ,@u tape)])
~
[%eith *] =+ foo=(chet(a c) $(a p.a) b d)
=+ bar=(chet(a c) $(a q.a) b d)
?~ foo
bar
?~ bar
foo
=+ ft=u.foo
=+ bt=u.bar
?: (gte (lent -.ft) (lent -.bt))
foo
bar
[%pair *] =+ foo=$(a p.a, c [%pair q.a c])
?~ foo
foo
=+ ft=u.foo
=+ bar=$(a q.a, b (slag (lent -.ft) b))
?~ bar
bar
=+ bt=u.bar
[~ [(weld -.ft -.bt) (cont +.ft +.bt)]]
[%manl *] =+ foo=$(a p.a)
?~ foo
blak
?~ -.u.foo
blak
$(a [%eith %empt [%pair p.a [%eith %empt a]]])
[%mant *] =+ foo=$(a p.a)
?~ foo
blak
=+ ft=u.foo
?~ -.ft
blak
$(a [%eith [%pair p.a [%eith a %empt]] %empt])
[%plls *] $(a [%pair p.a [%mant p.a]])
[%plll *] $(a [%pair p.a [%manl p.a]])
[%binl *] =+ min=?:(=(q.a 0) 0 (dec q.a))
?: =(q.a 0)
$(a [%manl p.a])
$(a [%pair p.a [%binl p.a min]])
[%bant *] ?: =(0 q.a)
blak
$(a [%pair p.a [%bant p.a (dec q.a)]])
[%bint *] =+ min=?:(=(q.a 0) 0 (dec q.a))
?: =(q.a 0)
$(a [%mant p.a])
$(a [%pair p.a [%bint p.a min]])
[%betw *] ?: =(0 r.a)
blak
?: =(q.a 0)
$(a [%eith [%pair p.a [%betw p.a 0 (dec r.a)]] %empt])
$(a [%pair p.a [%betw p.a (dec q.a) (dec r.a)]])
[%betl *] ?: =(0 r.a)
blak
?: =(q.a 0)
$(a [%eith %empt [%pair p.a [%betl p.a 0 (dec r.a)]]])
$(a [%pair p.a [%betl p.a (dec q.a) (dec r.a)]])
==
--
::
XX document
### `++rexp`
++ rexp :: Regex match
~/ %rexp
|= [a=tape b=tape]
^- (unit (unit (map ,@u tape)))
=+ ^= bar
|= [a=@ b=(map ,@u tape)]
?: =(a 0)
b
=+ c=(~(get by b) a)
?~ c
$(a (dec a), b (~(put by b) a ""))
$(a (dec a))
=+ par=(pars a)
?~ par ~
=+ poc=(~(proc ra u.par) 1)
=+ c=b
|-
=+ foo=(matc:poc c b)
?~ foo
?~ c
[~ ~]
$(c t.c)
[~ [~ (bar (dec p.poc) u.foo)]]
::
XX document
### `++repg`
++ repg :: Global regex replace
~/ %repg
|= [a=tape b=tape c=tape]
^- (unit tape)
=+ par=(pars a)
?~ par ~
=+ poc=(~(proc ra u.par) 1)
=+ d=b
:- ~
|-
^- tape
=+ foo=(matc:poc d b)
?~ foo
?~ d
~
[i.d $(d t.d)]
=+ ft=(need (~(get by u.foo) 0))
?~ d
c
(weld c $(d `tape`(slag (lent ft) `tape`d)))
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

View File

@ -1,378 +0,0 @@
section 2eN, pseudo-cryptography
================================
### `++un`
Reversible scrambling core
++ un :: =(x (wred (wren x)))
|%
A core that contains arms that perform reversible scrambling operations.
Used in the `@p` phonetic base.
------------------------------------------------------------------------
### `++wren`
Conceal structure
++ wren :: conceal structure
|= pyn=@ ^- @
=+ len=(met 3 pyn)
?: =(0 len)
0
=> .(len (dec len))
=+ mig=(zaft (xafo len (cut 3 [len 1] pyn)))
%+ can 3
%- flop ^- (list ,[@ @])
:- [1 mig]
|- ^- (list ,[@ @])
?: =(0 len)
~
=> .(len (dec len))
=+ mog=(zyft :(mix mig (end 3 1 len) (cut 3 [len 1] pyn)))
[[1 mog] $(mig mog)]
::
Scrambles a bytestring `pyn` by adding the current position to each
byte, looking it up in an s-box, and then performing the XOR operation
on the result, pushing it forward. Produces an atom.
`pyn` is an [atom]().
~zod/try=> `@ux`(wren:un 'testing')
0x30.bf6a.b9fe.7d8f
~zod/try=> `@ux`'testing'
0x67.6e69.7473.6574
~zod/try=> `@da`(wred:un (wren:un ~2001.2.5))
~2001.2.5
------------------------------------------------------------------------
### `++wred`
Restore structure
++ wred :: restore structure
|= cry=@ ^- @
=+ len=(met 3 cry)
?: =(0 len)
0
=> .(len (dec len))
=+ mig=(cut 3 [len 1] cry)
%+ can 3
%- flop ^- (list ,[@ @])
:- [1 (xaro len (zart mig))]
|- ^- (list ,[@ @])
?: =(0 len)
~
=> .(len (dec len))
=+ mog=(cut 3 [len 1] cry)
[[1 :(mix mig (end 3 1 len) (zyrt mog))] $(mig mog)]
::
Unscrambles a bytestring `cry` by subtracting the current position from
each byte, looking it up in an s-box, and performing the XOR operation
on the result, pushing it forward. Produces an atom.
`cry` is an [atom]().
~zod/try=> (wred:un 0x30.bf6a.b9fe.7d8f)
29.113.321.805.538.676
~zod/try=> `@t`(wred:un 0x30.bf6a.b9fe.7d8f)
'testing'
~zod/try=> (wred:un (wren:un 200.038.426))
200.038.426
------------------------------------------------------------------------
### `++xafo`
Add modulo 255
++ xafo |=([a=@ b=@] +((mod (add (dec b) a) 255)))
Produces the sum of two atoms modulo 255, encoded as a nonzero byte.
~zod/try=> (xafo:un 5 6)
11
~zod/try=> (xafo:un 256 20)
21
------------------------------------------------------------------------
### `++xaro`
Subtract modulo 255
++ xaro |=([a=@ b=@] +((mod (add (dec b) (sub 255 (mod a 255))) 255)))
Produces the difference between two atoms modulo 255, encoded as a
nonzero byte.
~zod/try=> (xaro:un 17 57)
40
~zod/try=> (xaro:un 265 12)
2
------------------------------------------------------------------------
### `++zaft`
Look up in 255 sub box
++ zaft :: forward 255-sbox
|= a=@D
=+ ^= b
0xcc.75bc.86c8.2fb1.9a42.f0b3.79a0.92ca.21f6.1e41.cde5.fcc0.
7e85.51ae.1005.c72d.1246.07e8.7c64.a914.8d69.d9f4.59c2.8038.
1f4a.dca2.6fdf.66f9.f561.a12e.5a16.f7b0.a39f.364e.cb70.7318.
1de1.ad31.63d1.abd4.db68.6a33.134d.a760.edee.5434.493a.e323.
930d.8f3d.3562.bb81.0b24.43cf.bea5.a6eb.52b4.0229.06b2.6704.
78c9.45ec.d75e.58af.c577.b7b9.c40e.017d.90c3.87f8.96fa.1153.
0372.7f30.1c32.ac83.ff17.c6e4.d36d.6b55.e2ce.8c71.8a5b.b6f3.
9d4b.eab5.8b3c.e7f2.a8fe.9574.5de0.bf20.3f15.9784.9939.5f9c.
e609.564f.d8a4.b825.9819.94aa.2c08.8e4c.9b22.477a.2840.3ed6.
3750.6ef1.44dd.89ef.6576.d00a.fbda.9ed2.3b6c.7b0c.bde9.2ade.
5c88.c182.481a.1b0f.2bfd.d591.2726.57ba
(cut 3 [(dec a) 1] b)
::
The inverse of [`++zart`](). Looks up a nonzero byte`a\` in a substiution
box with 255 values, producing a unique nonzero byte.
`a` is an [atom]() of one byte in length.
~zod/try=> (zaft:un 0x12)
42
~zod/try=> (zaft:un 0xff)
204
~zod/try=> (zaft:un 0x0)
! decrement-underflow
! exit
------------------------------------------------------------------------
### `++zart`
Reverse look up in 255 sub box
++ zart :: reverse 255-sbox
|= a=@D
=+ ^= b
0x68.4f07.ea1c.73c9.75c2.efc8.d559.5125.f621.a7a8.8591.5613.
dd52.40eb.65a2.60b7.4bcb.1123.ceb0.1bd6.3c84.2906.b164.19b3.
1e95.5fec.ffbc.f187.fbe2.6680.7c77.d30e.e94a.9414.fd9a.017d.
3a7e.5a55.8ff5.8bf9.c181.e5b6.6ab2.35da.50aa.9293.3bc0.cdc6.
f3bf.1a58.4130.f844.3846.744e.36a0.f205.789e.32d8.5e54.5c22.
0f76.fce7.4569.0d99.d26e.e879.dc16.2df4.887f.1ffe.4dba.6f5d.
bbcc.2663.1762.aed7.af8a.ca20.dbb4.9bc7.a942.834c.105b.c4d4.
8202.3e61.a671.90e6.273d.bdab.3157.cfa4.0c2e.df86.2496.f7ed.
2b48.2a9d.5318.a343.d128.be9c.a5ad.6bb5.6dfa.c5e1.3408.128d.
2c04.0339.97a1.2ff0.49d0.eeb8.6c0a.0b37.b967.c347.d9ac.e072.
e409.7b9f.1598.1d3f.33de.8ce3.8970.8e7a
(cut 3 [(dec a) 1] b)
::
The inverse of [`++zaft`](). Looks up the index of a nonzero byte `a` in
the substitution box with 255 values, producing a unique nonzero byte.
`a` is an [atom]() of one byte in length.
~zod/try=> `@ux`(zart:un 204)
0xff
~zod/try=> `@ux`(zart:un 42)
0x12
------------------------------------------------------------------------
### `++zyft`
Lookup byte in 256 sub box
++ zyft :: forward 256-sbox
|= a=@D
=+ ^= b
0xbb49.b71f.b881.b402.17e4.6b86.69b5.1647.115f.dddb.7ca5.
8371.4bd5.19a9.b092.605d.0d9b.e030.a0cc.78ba.5706.4d2d.
986a.768c.f8e8.c4c7.2f1c.effe.3cae.01c0.253e.65d3.3872.
ce0e.7a74.8ac6.daac.7e5c.6479.44ec.4143.3d20.4af0.ee6c.
c828.deca.0377.249f.ffcd.7b4f.eb7d.66f2.8951.042e.595a.
8e13.f9c3.a79a.f788.6199.9391.7fab.6200.4ce5.0758.e2f1.
7594.c945.d218.4248.afa1.e61a.54fb.1482.bea4.96a2.3473.
63c2.e7cb.155b.120a.4ed7.bfd8.b31b.4008.f329.fca3.5380.
9556.0cb2.8722.2bea.e96e.3ac5.d1bc.10e3.2c52.a62a.b1d6.
35aa.d05e.f6a8.0f3b.31ed.559d.09ad.f585.6d21.fd1d.8d67.
370b.26f4.70c1.b923.4684.6fbd.cf8b.5036.0539.9cdc.d93f.
9068.1edf.8f33.b632.d427.97fa.9ee1
(cut 3 [a 1] b)
::
The inverse of [`++zyrt`](). Looks up a byte `a` in a substituion box
with 256 values, producing a byte.
`a` is an [atom]() of one byte in length.
~zod/try=> (zyft:un 0x12)
57
~zod/try=> (zyft:un 0x0)
225
~zod/try=> (zyft:un 0xff)
187
------------------------------------------------------------------------
### `++zyrt`
Reverse lookup byte in 256 sub box
++ zyrt :: reverse 256-sbox
|= a=@D
=+ ^= b
0x9fc8.2753.6e02.8fcf.8b35.2b20.5598.7caa.c9a9.30b0.9b48.
47ce.6371.80f6.407d.00dd.0aa5.ed10.ecb7.0f5a.5c3a.e605.
c077.4337.17bd.9eda.62a4.79a7.ccb8.44cd.8e64.1ec4.5b6b.
1842.ffd8.1dfb.fd07.f2f9.594c.3be3.73c6.2cb6.8438.e434.
8d3d.ea6a.5268.72db.a001.2e11.de8c.88d3.0369.4f7a.87e2.
860d.0991.25d0.16b9.978a.4bf4.2a1a.e96c.fa50.85b5.9aeb.
9dbb.b2d9.a2d1.7bba.66be.e81f.1946.29a8.f5d2.f30c.2499.
c1b3.6583.89e1.ee36.e0b4.6092.937e.d74e.2f6f.513e.9615.
9c5d.d581.e7ab.fe74.f01b.78b1.ae75.af57.0ec2.adc7.3245.
12bf.2314.3967.0806.31dc.cb94.d43f.493c.54a6.0421.c3a1.
1c4a.28ac.fc0b.26ca.5870.e576.f7f1.616d.905f.ef41.33bc.
df4d.225e.2d56.7fd6.1395.a3f8.c582
(cut 3 [a 1] b)
The inverse of [`++zyft`](/doc/hoon/library/2en#++zyft). Looks up a byte `a` in a substituion box
with 256 values, producing a byte.
`a` is an [atom]() of one byte in length.
~zod/try=> `@ux`(zyrt:un 57)
0x12
~zod/try=> `@ux`(zyrt:un 225)
0x0
~zod/try=> `@ux`(zyrt:un 187)
0xff
### `++ob`
Reversible scrambling core, v2
++ ob
|%
A core for performing reversible scrambling operations for the `@p` phonetic base.
------------------------------------------------------------------------
### `++feen`
Conceal structure, v2
++ feen :: conceal structure v2
|= pyn=@ ^- @
?: &((gte pyn 0x1.0000) (lte pyn 0xffff.ffff))
(add 0x1.0000 (fice (sub pyn 0x1.0000)))
?: &((gte pyn 0x1.0000.0000) (lte pyn 0xffff.ffff.ffff.ffff))
=+ lo=(dis pyn 0xffff.ffff)
=+ hi=(dis pyn 0xffff.ffff.0000.0000)
%+ con hi
(add 0x1.0000 (fice (sub lo 0x1.0000)))
pyn
Randomly permutes atoms that fit into 17 to 32 bits into one another. If the atom fits into 33 to 64 bits, does the same permutation on the low 32 bits only. Otherwise, passes the atom through unchanged.
------------------------------------------------------------------------
### `++fend`
++ fend :: restore structure v2
|= cry=@ ^- @
?: &((gte cry 0x1.0000) (lte cry 0xffff.ffff))
(add 0x1.0000 (teil (sub cry 0x1.0000)))
?: &((gte cry 0x1.0000.0000) (lte cry 0xffff.ffff.ffff.ffff))
=+ lo=(dis cry 0xffff.ffff)
=+ hi=(dis cry 0xffff.ffff.0000.0000)
%+ con hi
(add 0x1.0000 (teil (sub lo 0x1.0000)))
cry
Randomly permutes atoms that fit into 17 to 32 bits into one another, and randomly permutes the low 32 bits of atoms that fit into 33 to 64 bits; otherwise, passes the atom through unchanged. The permutation is the inverse of the one applied by [`++feen`]().
------------------------------------------------------------------------
### `++fice`
++ fice :: adapted from
|= nor=@ :: black and rogaway
^- @ :: "ciphers with
=+ ^= sel :: arbitrary finite
%+ rynd 2 :: domains", 2002
%+ rynd 1
%+ rynd 0
[(mod nor 65.535) (div nor 65.535)]
(add (mul 65.535 -.sel) +.sel)
Applies a 3-round Feistel-like cipher to randomly permute atoms in the range `0` to `2^32 - 2^16`. The construction given in Black and Rogaway is ideal for a domain with a size of that form, and as with a conventionel Feistel cipher, three rounds suffice to make the permutation pseudorandom.
------------------------------------------------------------------------
### `++teil`
++ teil :: reverse ++fice
|= vip=@
^- @
=+ ^= sel
%+ rund 0
%+ rund 1
%+ rund 2
[(mod vip 65.535) (div vip 65.535)]
(add (mul 65.535 -.sel) +.sel)
Applies the reverse of the Feistel-like cipher applied by [`++fice`](). Unlike a conventional Feistel cipher that is its own inverse if keys are used in reverse order, this Feistel-like cipher uses two moduli that must be swapped when applying the reverse transformation.
------------------------------------------------------------------------
### `++rynd`
++ rynd :: feistel round
|= [n=@ l=@ r=@]
^- [@ @]
:- r
?~ (mod n 2)
(~(sum fo 65.535) l (en:aesc (snag n raku) r))
(~(sum fo 65.536) l (en:aesc (snag n raku) r))
A single round of the Feistel-like cipher [`++fice`](). AES ([`++aesc`]()) is used as the round function.
------------------------------------------------------------------------
### `++rund`
++ rund :: reverse round
|= [n=@ l=@ r=@]
^- [@ @]
:- r
?~ (mod n 2)
(~(dif fo 65.535) l (en:aesc (snag n raku) r))
(~(dif fo 65.536) l (en:aesc (snag n raku) r))
A single round of the Feistel-like reverse cipher [`++teil`]().
------------------------------------------------------------------------
### `++raku`
++ raku
^- (list ,@ux)
:~ 0x15f6.25e3.083a.eb3e.7a55.d4db.fb99.32a3.
43af.2750.219e.8a24.e5f8.fac3.6c36.f968
0xf2ff.24fe.54d0.1abd.4b2a.d8aa.4402.8e88.
e82f.19ec.948d.b1bb.ed2e.f791.83a3.8133
0xa3d8.6a7b.400e.9e91.187d.91a7.6942.f34a.
6f5f.ab8e.88b9.c089.b2dc.95a6.aed5.e3a4
==
Arbitrary keys for use with [`++aesc`]().

View File

@ -1,453 +0,0 @@
section 2eO, virtualization
===========================
### `++mack`
Nock subject to unit
++ mack
|= [sub=* fol=*]
^- (unit)
=+ ton=(mink [sub fol] |=(* ~))
?.(?=([0 *] ton) ~ [~ p.ton])
::
Accepts a nock subject-formula cell and wraps it into a [`++unit`]().
`fol` is pure nock, meaning that nock `11` operations result in a block,
producing a `~`.
`sub` is a subject [noun]().
`fol` is a formula [noun](), which is generally a `++nock`.
~zod/try=> (mack [[1 2 3] [0 1]])
[~ [1 2 3]]
~zod/try=> (mack [41 4 0 1])
[~ 42]
~zod/try=> (mack [4 0 4])
~
~zod/try=> (mack [[[0 2] [1 3]] 4 4 4 4 0 5])
[~ 6]
~zod/try=> ;;((unit ,@tas) (mack [[1 %yes %no] 6 [0 2] [0 6] 0 7]))
[~ %no]
------------------------------------------------------------------------
### `++mink`
Mock interpreter
++ mink
~/ %mink
|= [[sub=* fol=*] sky=$+(* (unit))]
=+ tax=*(list ,[@ta *])
|- ^- tone
?@ fol
[%2 tax]
?: ?=(^ -.fol)
=+ hed=$(fol -.fol)
?: ?=(%2 -.hed)
hed
=+ tal=$(fol +.fol)
?- -.tal
%0 ?-(-.hed %0 [%0 p.hed p.tal], %1 hed)
%1 ?-(-.hed %0 tal, %1 [%1 (weld p.hed p.tal)])
%2 tal
==
?+ fol
[%2 tax]
::
[0 b=@]
?: =(0 b.fol) [%2 tax]
?: =(1 b.fol) [%0 sub]
?: ?=(@ sub) [%2 tax]
=+ [now=(cap b.fol) lat=(mas b.fol)]
$(b.fol lat, sub ?:(=(2 now) -.sub +.sub))
::
[1 b=*]
[%0 b.fol]
::
[2 b=[^ *]]
=+ ben=$(fol b.fol)
?. ?=(%0 -.ben) ben
?>(?=(^ p.ben) $(sub -.p.ben, fol +.p.ben))
::?>(?=(^ p.ben) $([sub fol] p.ben)
::
[3 b=*]
=+ ben=$(fol b.fol)
?. ?=(%0 -.ben) ben
[%0 .?(p.ben)]
::
[4 b=*]
=+ ben=$(fol b.fol)
?. ?=(%0 -.ben) ben
?. ?=(@ p.ben) [%2 tax]
[%0 .+(p.ben)]
::
[5 b=*]
=+ ben=$(fol b.fol)
?. ?=(%0 -.ben) ben
?. ?=(^ p.ben) [%2 tax]
[%0 =(-.p.ben +.p.ben)]
::
[6 b=* c=* d=*]
$(fol =>(fol [2 [0 1] 2 [1 c d] [1 0] 2 [1 2 3] [1 0] 4 4 b]))
::
[7 b=* c=*] $(fol =>(fol [2 b 1 c]))
[8 b=* c=*] $(fol =>(fol [7 [[0 1] b] c]))
[9 b=* c=*] $(fol =>(fol [7 c 0 b]))
[10 @ c=*] $(fol c.fol)
[10 [b=* c=*] d=*]
=+ ben=$(fol c.fol)
?. ?=(%0 -.ben) ben
?: ?=(?(%hunk %lose %mean %spot) b.fol)
$(fol d.fol, tax [[b.fol p.ben] tax])
$(fol d.fol)
::
[11 b=*]
=+ ben=$(fol b.fol)
?. ?=(%0 -.ben) ben
=+ val=(sky p.ben)
?~(val [%1 p.ben ~] [%0 u.val])
::
==
::
Bottom-level [mock]() (virtual nock) interpreter. Produces a
[`++tone`](), a nock computation result. If nock 11 is invoked, `sky`
computes on the subject and produces a [`++unit`]() result. An empty
result becomes a `%1` `++tone`, indicating a block.
`sub` is the subject as a [noun]().
`fol` is the formula as a [noun]().
`sky` is an [`%iron`]() gate invoked with [nock operator 11]().
~zod/try=> (mink [20 [4 0 1]] ,~)
[%0 p=21]
~zod/try=> (mink [[90 5 3] [0 3]] ,~)
[%0 p=[5 3]]
~zod/try=> (mink 20^[4 0 1] ,~)
[%0 p=21]
~zod/try=> (mink [90 5 3]^[0 3] ,~)
[%0 p=[5 3]]
~zod/try=> (mink [0]^[11 1 20] ,~)
[%1 p=~[20]]
~zod/try=> (mink [0]^[11 1 20] |=(a=* `[40 a]))
[%0 p=[40 20]]
~zod/try=> (mink [5]^[0 2] ,~)
[%2 p=~]
~zod/try=> (mink [5]^[10 yelp/[0 1] 0 0] ,~)
[%2 p=~[[~.yelp 5]]]
------------------------------------------------------------------------
### `++mock`
Compute formula on subject with hint
++ mock
|= [[sub=* fol=*] sky=$+(* (unit))]
(mook (mink [sub fol] sky))
::
Produces a [`++toon`](), which is either a sucessful, blocked, or
crashed result. If nock 11 is invoked, `sky` computes on the subject and
produces a [`++unit`]() result. An empty result becomes a `%1` `++tune`,
indicating a block.
`sub` is the subject as a [noun]().
`fol` is the formula as a [noun]().
`sky` is an [%iron]() gate invoked with [nock operator 11]().
~zod/try=> (mock [5 4 0 1] ,~)
[%0 p=6]
~zod/try=> (mock [~ 11 1 0] |=(* `999))
[%0 p=999]
~zod/try=> (mock [~ 0 1.337] ,~)
[%2 p=~]
~zod/try=> (mock [~ 11 1 1.337] ,~)
[%1 p=~[1.337]]
~zod/try=> (mock [[[4 4 4 4 0 3] 10] 11 9 2 0 1] |=(* `[+<]))
[%0 p=14]
~zod/try=> (mock [[[4 4 4 4 0 3] 10] 11 9 2 0 1] |=(* `[<+<>]))
[%0 p=[49 52 0]]
~zod/try=> ;;(tape +:(mock [[[4 4 4 4 0 3] 10] 11 9 2 0 1] |=(* `[<+<>])))
"14"
------------------------------------------------------------------------
### `++mook`
Intelligently render crash annotation
++ mook
|= ton=tone
^- toon
?. ?=([2 *] ton) ton
:- %2
=+ yel=(lent p.ton)
=. p.ton
?. (gth yel 256) p.ton
%+ weld
(scag 128 p.ton)
^- (list ,[@ta *])
:_ (slag (sub yel 128) p.ton)
:- %lose
%+ rap 3
;: weld
"[skipped "
~(rend co %$ %ud (sub yel 256))
" frames]"
==
|- ^- (list tank)
?~ p.ton ~
=+ rex=$(p.ton t.p.ton)
?+ -.i.p.ton rex
%hunk [(tank +.i.p.ton) rex]
%lose [[%leaf (rip 3 (,@ +.i.p.ton))] rex]
%mean :_ rex
?@ +.i.p.ton [%leaf (rip 3 (,@ +.i.p.ton))]
=+ mac=(mack +.i.p.ton +<.i.p.ton)
?~(mac [%leaf "####"] (tank u.mac))
%spot :_ rex
=+ sot=(spot +.i.p.ton)
:- %leaf
;: weld
~(ram re (smyt p.sot))
":<["
~(rend co ~ %ud p.p.q.sot)
" "
~(rend co ~ %ud q.p.q.sot)
"].["
~(rend co ~ %ud p.q.q.sot)
" "
~(rend co ~ %ud q.q.q.sot)
"]>"
==
==
::
Converts a `%2` `++tone` nock stack trace to a list of [`++tank`]().
Each may be a tank, cord, [`++spot`](), or trapped tank. Produces a
[`++toon`]().
`ton` is a [`++tone`]().
~zod/try=> (mook [%0 5 4 5 1])
[%0 p=[5 4 5 1]]
~zod/try=> (mook [%2 ~[[%hunk %rose ["<" "," ">"] ~[[%leaf "err"]]]]])
[%2 p=~[[%rose p=[p="<" q="," r=">"] q=[i=[%leaf p="err"] t=~]]]]
~zod/try=> (mook [%2 ~[[%malformed %elem] [%lose 'do print']]])
[%2 p=~[[%leaf p="do print"]]]
~zod/try=> (mook [%2 ~[[%mean |.(>(add 5 6)<)]]])
[%2 p=~[[%leaf p="11"]]]
~zod/try=> (mook [%2 ~[[%spot /b/repl [1 1]^[1 2]] [%mean |.(!!)]]])
[%2 p=~[[%leaf p="/b/repl/:<[1 1].[1 2]>"] [%leaf p="####"]]]
------------------------------------------------------------------------
### `++mang`
Unit: Slam gate with sample
++ mang
|= [[gat=* sam=*] sky=$+(* (unit))]
^- (unit)
=+ ton=(mong [[gat sam] sky])
?.(?=([0 *] ton) ~ [~ p.ton])
::
Produces a [`++unit`]() computation result from slamming `gat` with
`sam`, using `sky` to compute or block on nock 11 when applicable.
Similar to [`++mong`]().
`gat` is a [noun]() that is generally a [`gate`]().
`sam` is a [`sample`]() noun.
`sky` is an [%iron]() gate invoked with [nock operator 11]().
~zod/try=> (mang [|=(@ 20) ~] ,~)
[~ 20]
~zod/try=> (mang [|=(@ !!) ~] ,~)
~
~zod/try=> (mang [|=(a=@ (add 20 a)) ~] ,~)
[~ 20]
~zod/try=> (mang [|=(a=[@ @] (add 20 -.a)) ~] ,~)
~
~zod/try=> (mang [|=(a=[@ @] (add 20 -.a)) [4 6]] ,~)
[~ 24]
~zod/try=> (mang [|=(a=@ .^(a)) ~] ,~)
~
~zod/try=> (mang [|=(a=@ .^(a)) ~] ,[~ %42])
[~ 42]
~zod/try=> (mang [|=(a=@ .^(a)) ~] |=(a=* [~ a 6]))
[~ [0 6]]
~zod/try=> (mang [|=(a=@ .^(a)) 8] |=(a=* [~ a 6]))
[~ [8 6]]
------------------------------------------------------------------------
### `++mong`
Slam gate with sample
++ mong
|= [[gat=* sam=*] sky=$+(* (unit))]
^- toon
?. &(?=(^ gat) ?=(^ +.gat))
[%2 ~]
(mock [[-.gat [sam +>.gat]] -.gat] sky)
::
Produces a [`++toon`]() computation result from slamming `gat` with
`sam`, using `sky` to compute or block on nock 11 when applicable.
`gat` is a [noun]() that is generally a [`gate`]().
`sam` is a [`sample`]() noun.
`sky` is an [%iron]() gate invoked with [nock operator 11]().
~zod/try=> (mong [|=(@ 20) ~] ,~)
[%0 p=20]
~zod/try=> (mong [|=(@ !!) ~] ,~)
[%2 p=~]
~zod/try=> (mong [|=(a=@ (add 20 a)) ~] ,~)
[%0 p=20]
~zod/try=> (mong [|=(a=[@ @] (add 20 -.a)) ~] ,~)
[%2 p=~]
~zod/try=> (mong [|=(a=[@ @] (add 20 -.a)) [4 6]] ,~)
[%0 p=24]
~zod/try=> (mong [|=(a=@ .^(a)) ~] ,~)
[%1 p=~[0]]
~zod/try=> (mong [|=(a=@ .^(a)) ~] ,[~ %42])
[%0 p=42]
~zod/try=> (mong [|=(a=@ .^(a)) ~] |=(a=* [~ a 6]))
[%0 p=[0 6]]
~zod/try=> (mong [|=(a=@ .^(a)) 8] |=(a=* [~ a 6]))
[%0 p=[8 6]]
------------------------------------------------------------------------
### `++mung`
Virtualize slamming gate
++ mung
|= [[gat=* sam=*] sky=$+(* (unit))]
^- tone
?. &(?=(^ gat) ?=(^ +.gat))
[%2 ~]
(mink [[-.gat [sam +>.gat]] -.gat] sky)
::
Produces a [`++tone`]() computation result from slamming `gat` with
`sam`, using `sky` to compute or block on nock 11 when applicable.
`gat` is a [noun]() that is generally a [`gate`]().
`sam` is a [`sample`]() noun.
`sky` is an [%iron]() gate invoked with [nock operator 11]().
~zod/try=> (mung [|=(@ 20) ~] ,~)
[%0 p=20]
~zod/try=> (mung [|=(@ !!) ~] ,~)
[%2 p=~]
~zod/try=> (mung [|=(a=@ (add 20 a)) ~] ,~)
[%0 p=20]
~zod/try=> (mung [|=(a=[@ @] (add 20 -.a)) ~] ,~)
[%2 p=~]
~zod/try=> (mung [|=(a=[@ @] (add 20 -.a)) [4 6]] ,~)
[%0 p=24]
~zod/try=> (mung [|=(a=@ .^(a)) ~] ,~)
[%1 p=~[0]]
~zod/try=> (mung [|=(a=@ .^(a)) ~] ,[~ %42])
[%0 p=42]
~zod/try=> (mung [|=(a=@ .^(a)) ~] |=(a=* [~ a 6]))
[%0 p=[0 6]]
~zod/try=> (mung [|=(a=@ .^(a)) 8] |=(a=* [~ a 6]))
[%0 p=[8 6]]
------------------------------------------------------------------------
### `++mule`
Typed virtual
++ mule :: typed virtual
~/ %mule
|* taq=_|.(_*)
=+ mud=(mute taq)
?- -.mud
& [%& p=$:taq]
| [%| p=p.mud]
==
::
Kicks a `++trap`, producing its results or any errors that occur along
the way. Used to lazily compute stack traces.
`taq` is a [`++trap`](), generally producing a list of [`++tank`]()s.
~zod/try=> (mule |.(leaf/"hello"))
[%.y p=[%leaf "hello"]]
~zod/try=> (mule |.(!!))
[%.n p=~]
~zod/try=> (mule |.(.^(a//=pals/1)))
[ %.n
p
~[
[ %rose
p=[p="/" q="/" r="/"]
q
[ i=[%leaf p="a"]
t=[i=[%leaf p="~zod"] t=[i=[%leaf p="pals"] t=[i=[%leaf p="1"] t=~]]]
]
]
]
]
------------------------------------------------------------------------
### `++mute`
Untyped virtual
++ mute :: untyped virtual
|= taq=_^?(|.(_*))
^- (each ,* (list tank))
=+ ton=(mock [taq 9 2 0 1] |=(* ~))
?- -.ton
%0 [%& p.ton]
%1 [%| (turn p.ton |=(a=* (smyt (path a))))]
%2 [%| p.ton]
==
Kicks a `++trap`, producing its result as a noun or the tanks of any
error that occurs. Similar to [`++mule`](), but preserves no type
information.
`taq` is a [`++trap`](/doc/hoon/library/1#++trap).
~zod/try=> (mute |.(leaf/"hello"))
[%.y p=[1.717.658.988 104 101 108 108 111 0]]
~zod/try=> (mute |.(!!))
[%.n p=~]
~zod/try=> (mute |.(.^(a//=pals/1)))
[ %.n
p
~[
[ %rose
p=[p="/" q="/" r="/"]
q=[i=[%leaf p="a"] t=[i=[%leaf p="~zod"] t=[i=[%leaf p="pals"] t=[i=[%leaf p="1"] t=~]]]]
]
]
]
------------------------------------------------------------------------

View File

@ -1,586 +0,0 @@
section 2eP, diff
=================
A- more or less low priority and/or currently in the wrong section
anyway.
------------------------------------------------------------------------
------------------------------------------------------------------------
### `++berk`
Invert diff patches
++ berk :: invert diff patch
|* bur=(urge)
|- ^+ bur
?~ bur ~
:_ $(bur t.bur)
?- -.i.bur
& i.bur
| [%| q.i.bur p.i.bur]
==
::
Inverts a list of changes `bur`. Skips stay constant and replaces are
swapped. Produces a `bur`.
`bur` is a [`++urge`]().
~zod/try=> (berk `(urge)`~[`10 %|^[~[2] ~[3 4]] `5])
~[[%.y p=10] [%.n p=~[3 4] q=~[2]] [%.y p=5]]
~zod/try=> (lurk "somes" `(urge char)`~[`1 [%| "o" "a"] `3])
"sames"
~zod/try=> (berk `(urge char)`~[`1 [%| "o" "a"] `3])
~[[%.y p=1] [%.n p="a" q="o"] [%.y p=3]]
~zod/try=> (lurk "sames" (berk `(urge char)`~[`1 [%| "o" "a"] `3]))
"somes"
------------------------------------------------------------------------
### `++diff`
Generate patch
++ diff :: generate patch
|= pum=umph
|= [old=* new=*] ^- udon
:- pum
?+ pum ~|(%unsupported !!)
%a [%d (nude old new)]
%b =+ [hel=(cue ((hard ,@) old)) hev=(cue ((hard ,@) new))]
[%d (nude hel hev)]
%c =+ [hel=(lore ((hard ,@) old)) hev=(lore ((hard ,@) new))]
[%c (lusk hel hev (loss hel hev))]
==
::
Produces a patch between two nouns, by change type
`pum` is an [`++umph`]().
~zod/try=> ((diff %a) 20 21)
[p=%a q=[%d p=[%1 p=21] q=[%1 p=20]]]
~zod/try=> ((diff %a) [1 2 3] [1 2 4])
[ p=%a
q
[ %d
p=[p=[%0 p=2] q=[p=[%0 p=6] q=[%1 p=4]]]
q=[p=[%0 p=2] q=[p=[%0 p=6] q=[%1 p=3]]]
]
]
~zod/try=> ~04hh
[1 2]
~zod/try=> ~0ph
[1 1]
~zod/try=> ((diff %b) 0v4hh 0vph)
[p=%b q=[%d p=[p=[%0 p=2] q=[%0 p=2]] q=[p=[%0 p=3] q=[%1 p=2]]]]
~zod/try=> ((diff %c) (role 'sam' 'les' 'les' 'kor' ~) (role 'sam' 'mor' 'kor' ~))
[p=%c q=[%c p=~[[%.y p=1] [%.n p=~[7.562.604 7.562.604] q=~[7.499.629]] [%.y p=1]]]]
~[[%.y p=0] [%.y p=0] [%.y p=1] [%.n p=<|les les|> q=<|mor|>] [%.y p=1]]
~zod/try=> (,[%c %c (urge cord)] ((diff %c) (role 'sam' 'les' 'les' 'kor' ~) (role 'sam' 'mor' 'kor' ~)))
[%c %c ~[[%.y p=1] [%.n p=<|les les|> q=<|mor|>] [%.y p=1]]]
------------------------------------------------------------------------
### `++loss`
Longest subsequence
++ loss :: longest subsequence
~/ %loss
|* [hel=(list) hev=(list)]
|- ^+ hev
=+ ^= sev
=+ [inx=0 sev=*(map ,@t (list ,@ud))]
|- ^+ sev
?~ hev sev
=+ guy=(~(get by sev) i.hev)
$(hev t.hev, inx +(inx), sev (~(put by sev) i.hev [inx ?~(guy ~ u.guy)]))
=| gox=[p=@ud q=(map ,@ud ,[p=@ud q=_hev])]
=< abet
=< main
|%
++ abet =.(q.rag ?:(=([& 0] p.rag) q.rag [p.rag q.rag]) (flop q.rag))
++ hink :: extend fits top
|= [inx=@ud goy=@ud] ^- ?
|(=(p.gox inx) (lth goy p:(need (~(get by q.gox) inx))))
::
++ lonk :: extend fits bottom
|= [inx=@ud goy=@ud] ^- ?
|(=(0 inx) (gth goy p:(need (~(get by q.gox) (dec inx)))))
::
++ lune :: extend
|= [inx=@ud goy=@ud]
^+ +>
%_ +>.$
gox
:- ?:(=(inx p.gox) +(p.gox) p.gox)
%+ ~(put by q.gox) inx
[goy (snag goy hev) ?:(=(0 inx) ~ q:(need (~(get by q.gox) (dec inx))))]
==
::
++ merg :: merge all matches
|= gay=(list ,@ud)
^+ +>
=+ ^= zes
=+ [inx=0 zes=*(list ,[p=@ud q=@ud])]
|- ^+ zes
?: |(?=(~ gay) (gth inx p.gox)) zes
?. (lonk inx i.gay) $(gay t.gay)
?. (hink inx i.gay) $(inx +(inx))
$(inx +(inx), gay t.gay, zes [[inx i.gay] zes])
|- ^+ +>.^$
?~(zes +>.^$ $(zes t.zes, +>.^$ (lune i.zes)))
::
++ main
|- ^+ +
?~ hel
?~ hev
?>(?=(~ lcs) +)
$(hev t.hev, rag (done %| ~ [i.hev ~]))
?~ hev
$(hel t.hel, rag (done %| [i.hel ~] ~))
?~ lcs
+(rag (done %| (flop hel) (flop hev)))
?: =(i.hel i.lcs)
?: =(i.hev i.lcs)
$(lcs t.lcs, hel t.hel, hev t.hev, rag (done %& 1))
$(hev t.hev, rag (done %| ~ [i.hev ~]))
?: =(i.hev i.lcs)
$(hel t.hel, rag (done %| [i.hel ~] ~))
$(hel t.hel, hev t.hev, rag (done %| [i.hel ~] [i.hev ~]))
--
Finds a subsequence of repeated elements within two [`++list`]()s, using
several internal helper arms. Produces a [`++tape`]().
`hel` is a [`++list`]() of characters.
`hev` is a [++list\`]() of characters.
~zod/try=> (loss "sam" "sem")
"sm"
~zod/try=> (loss "samo" "semo")
"smo"
~zod/try=> (loss "sakmo" "semo")
"smo"
~zod/try=> (loss "ferdinham" "ferdilapos
~ <syntax error at [1 30]>
~zod/try=> (loss "ferdinham" "ferdilapos")
"ferdia"
------------------------------------------------------------------------
### `++locz`
Find common
++ locz :: trivial algorithm
|= [hel=tape hev=tape]
^- tape
=+ [leh=(lent hel) veh=(lent hev)]
=- (flop q.yun)
^= yun
|- ^- [p=@ud q=tape]
~+
?: |(=(0 leh) =(0 veh)) [0 ~]
=+ [dis=(snag (dec leh) hel) dat=(snag (dec veh) hev)]
?: =(dis dat)
=+ say=$(leh (dec leh), veh (dec veh))
[+(p.say) [dis q.say]]
=+ [lef=$(leh (dec leh)) rig=$(veh (dec veh))]
?:((gth p.lef p.rig) lef rig)
::
Finds a subsequence of repeated elements within two [`++list`](/doc/hoon/library/1#++list)s,
producing a [\`++tape]().
~zod/try=> (locz "samukot" "semelkot")
"smkot"
~zod/try=> (locz "samukot" "samelkot")
"samkot"
------------------------------------------------------------------------
### `++lore`
Split on `\n`
++ lore :: atom to line list
~/ %lore
|= lub=@
=| tez=(list ,@t)
|- ^+ tez
?: =(0 lub) (flop tez)
=+ ^= meg
=+ meg=0
|- ^- @ud
=+ gam=(cut 3 [meg 1] lub)
?:(|(=(10 gam) =(0 gam)) meg $(meg +(meg)))
=+ res=(rsh 3 +(meg) lub)
?: &(=(0 (cut 3 [meg 1] lub)) !=(0 res))
!!
$(lub res, tez [(end 3 meg lub) tez])
::
Split on newlines, ascii `10`
~zod/try=> (lore 'soke\0alas\0amep')
<|soke las mep|>
~zod/try=> (lore '|= a=@\0a=+ b=(add a 5)\0a(mix b a)')
<||= a=@ =+ b=(add a 5) (mix b a)|>
~zod/try=> `wain`[(fil 3 80 ' ') (lore '|= a=@\0a=+ b=(add a 5)\0a(mix b a)')]
<|
|= a=@
=+ b=(add a 5)
(mix b a)
|>
------------------------------------------------------------------------
### `++role`
Join with `\n`
++ role :: line list to atom
|= tez=(list ,@t)
(rap 3 (turn tez |=(a=@t (cat 3 a 10))))
::
Join line list with newlines.
~zod/try=> (role 'sep' 'tek' 'lap' ~)
3.230.709.852.558.292.782.985.274.739
~zod/try=> `@t`(role 'sep' 'tek' 'lap' ~)
'''
sep
tek
lap
'''
------------------------------------------------------------------------
### `++lump`
Change with `++udon`
++ lump :: apply patch
|= [don=udon src=*]
^- *
?+ p.don ~|(%unsupported !!)
%a
?+ -.q.don ~|(%unsupported !!)
%a q.q.don
%c (lurk ((hard (list)) src) p.q.don)
%d (lure src p.q.don)
==
::
%c
=+ dst=(lore ((hard ,@) src))
%- role
?+ -.q.don ~|(%unsupported !!)
%a ((hard (list ,@t)) q.q.don)
%c (lurk dst p.q.don)
==
==
::
Use udon to change noun
~zod/try=> (lump [%a %a 20 25] 20)
25
~zod/try=> (lump [%a %d [[%0 1] [%0 1]] [%0 2]] 20)
[20 20]
~zod/try=> (lump [%c %a ~['sa' 'le'] ~['sa' 'lo']] 'sa\0ale')
11.473.670.267.251
~zod/try=> (,@t (lump [%c %a ~['sa' 'le'] ~['sa' 'lo']] 'sa\0ale'))
'''
sa
lo
'''
~zod/try=> (,@t (lump [%c %c `1 [%| ~['le'] ~['lo' 'ma']] ~] 'sa\0ale'))
'''
sa
ma
lo
'''
------------------------------------------------------------------------
### `++lure`
Patch `a`
++ lure :: apply tree diff
|= [a=* b=upas]
^- *
?^ -.b
[$(b -.b) $(b +.b)]
?+ -.b ~|(%unsupported !!)
%0 .*(a [0 p.b])
%1 .*(a [1 p.b])
==
Patch a by references to axis and literal.
~zod/try=> (lure ~[1 2] [[%0 2] [%1 3] [%0 7]])
[1 3 0]
~zod/try=> (lure ~[1 2 4] [[%0 2] [%1 3] [%0 7]])
[1 3 4 0]
------------------------------------------------------------------------
### `++limp`
Reverse patch
++ limp :: invert patch
|= don=udon ^- udon
:- p.don
?+ -.q.don ~|(%unsupported !!)
%a [%a q.q.don p.q.don]
%c [%c (berk p.q.don)]
%d [%d q.q.don p.q.don]
==
::
Reverse a patch (preprocessor unchanged)
~zod/try=> (limp [%a %a 20 40])
[p=%a q=[%a p=40 q=20]]
~zod/try=> (limp [%c %c ~[`20 [%| ~[52 53] ~[51]] `6]])
[p=%c q=[%c p=~[[%.y p=20] [%.n p=~[51] q=~[52 53]] [%.y p=6]]]]
~zod/try=> (limp [%a %d [[%0 1] [%0 1]] [%0 2]])
[p=%a q=[%d p=[%0 p=2] q=[p=[%0 p=1] q=[%0 p=1]]]]
------------------------------------------------------------------------
### `++hump`
Prep for diff
++ hump :: general prepatch
|= [pum=umph src=*] ^- *
?+ pum ~|(%unsupported !!)
%a src
%b (cue ((hard ,@) src))
%c (lore ((hard ,@) src))
==
::
Prep atom for diff: leave alone, cue, or split by newlines.
~zod/try=> (hump %a ~)
0
~zod/try=> (hump %a 40)
40
~zod/try=> (hump %c 40)
[40 0]
~zod/try=> (hump %c 'as')
[29.537 0]
~zod/try=> (hump %c 'as\0alok')
[29.537 7.040.876 0]
~zod/try=> (hump %b 0vph)
[1 1]
------------------------------------------------------------------------
### `++husk`
Atomize post diff
++ husk :: unprepatch
|= [pum=umph dst=*] ^- *
?+ pum ~|(%unsupported !!)
%a dst
%b (jam dst)
%c (role ((hard (list ,@)) dst))
==
::
Re-atomize after diff: leave alone, jam, or join with newlines.
~zod/try=> (husk %a 0)
0
~zod/try=> (husk %a 40)
40
~zod/try=> (husk %c [40 0])
2.600
~zod/try=> (rip 3 (,@ (husk %c [40 0])))
~[40 10]
~zod/try=> (husk %c [%as 0])
684.897
~zod/try=> (husk %c [%as 0])
684.897
~zod/try=> (,@t (husk %c [%as 0]))
'''
as
'''
~zod/try=> (husk %c [%as %lok 0])
2.932.876.065.272.673
~zod/try=> (,@t (husk %c [%as %lok 0]))
'''
as
lok
'''
~zod/try=> (husk %b [1 1])
817
~zod/try=> (,@uv (husk %b [1 1]))
0vph
~zod/try=> ~0ph
[1 1]
------------------------------------------------------------------------
### `++lurk`
Apply list patch
++ lurk :: apply list patch
|* [hel=(list) rug=(urge)]
^+ hel
=+ war=`_hel`~
|- ^+ hel
?~ rug (flop war)
?- -.i.rug
&
%= $
rug t.rug
hel (slag p.i.rug hel)
war (weld (flop (scag p.i.rug hel)) war)
==
::
|
%= $
rug t.rug
hel =+ gur=(flop p.i.rug)
|- ^+ hel
?~ gur hel
?>(&(?=(^ hel) =(i.gur i.hel)) $(hel t.hel, gur t.gur))
war (weld q.i.rug war)
==
==
::
Amend list using an urge: list of `[%& {number skipped}]` and
`[%| old new]`
~zod/try=> (lurk "hema" `(urge char)`~[`1 [%| "e" "ru"] `2])
"hurma"
~zod/try=> (lurk "koltep" `(urge char)`~[`3 [%| "et" ""] `1])
"kolp"
------------------------------------------------------------------------
### `++lusk`
`lcs` to list patch
++ lusk :: lcs to list patch
|* [hel=(list) hev=(list) lcs=(list)]
=+ ^= rag
^- $% [& p=@ud]
[| p=_lcs q=_lcs]
==
[%& 0]
=> .(rag [p=rag q=*(list ,_rag)])
=< abet =< main
|%
++ abet =.(q.rag ?:(=([& 0] p.rag) q.rag [p.rag q.rag]) (flop q.rag))
++ done
|= new=_p.rag
^+ rag
?- -.p.rag
| ?- -.new
| [[%| (weld p.new p.p.rag) (weld q.new q.p.rag)] q.rag]
& [new [p.rag q.rag]]
==
& ?- -.new
| [new ?:(=(0 p.p.rag) q.rag [p.rag q.rag])]
& [[%& (add p.p.rag p.new)] q.rag]
==
==
::
++ main
|- ^+ +
?~ hel
?~ hev
?>(?=(~ lcs) +)
$(hev t.hev, rag (done %| ~ [i.hev ~]))
?~ hev
$(hel t.hel, rag (done %| [i.hel ~] ~))
?~ lcs
+(rag (done %| (flop hel) (flop hev)))
?: =(i.hel i.lcs)
?: =(i.hev i.lcs)
$(lcs t.lcs, hel t.hel, hev t.hev, rag (done %& 1))
$(hev t.hev, rag (done %| ~ [i.hev ~]))
?: =(i.hev i.lcs)
$(hel t.hel, rag (done %| [i.hel ~] ~))
$(hel t.hel, hev t.hev, rag (done %| [i.hel ~] [i.hev ~]))
--
Using a common sequence, generate urge from two lists
~zod/try=> (lusk "hamok" "hasok" "haok")
~[[%.y p=2] [%.n p="m" q="s"] [%.y p=2]]
~zod/try=> (lusk "hamok" "hasok" "hak")
~[[%.y p=2] [%.n p="om" q="os"] [%.y p=1]]
~zod/try=> (lusk "telroga" "tesomga" "teoga")
~[[%.y p=2] [%.n p="rl" q="s"] [%.y p=1] [%.n p="" q="m"] [%.y p=2]]
~zod/try=> (lurk "telroga" `(urge char)`~[[%.y p=2] [%.n p="rl" q="s"] [%.y p=1] [%.n p="" q="m"] [%.y p=2]])
"tesomga"
------------------------------------------------------------------------
### `++nude`
Tree change
++ nude :: tree change
|= [a=* b=*]
^- [p=upas q=upas]
=< [p=(tred a b) q=(tred b a)]
|%
++ axes :: locs of nouns
|= [a=@ b=*] ^- (map ,* axis)
=+ c=*(map ,* axis)
|- ^- (map ,* axis)
=> .(c (~(put by c) b a))
?@ b
c
%- ~(uni by c)
%- ~(uni by $(a (mul 2 a), b -.b))
$(a +((mul 2 a)), b +.b)
::
++ tred :: diff a->b
|= [a=* b=*] ^- upas
=| c=(unit ,*)
=+ d=(axes 1 a)
|- ^- upas
=> .(c (~(get by d) b))
?~ c
?@ b
[%1 b]
=+ e=^-(upas [$(b -.b) $(b +.b)])
?- e
[[%1 *] [%1 *]] [%1 [p.p.e p.q.e]]
* e
==
[%0 u.c]
--
Generate tree diff from two nouns.
~zod/try=> (nude 40 20)
[p=[%1 p=20] q=[%1 p=40]]
~zod/try=> (nude [5 5] 5)
[p=[%0 p=3] q=[p=[%0 p=1] q=[%0 p=1]]]
~zod/try=> (nude "sam" "sal")
[ p=[p=[%1 p=115] q=[p=[%1 p=97] q=[p=[%1 p=108] q=[%0 p=15]]]]
q=[p=[%1 p=115] q=[p=[%1 p=97] q=[p=[%1 p=109] q=[%0 p=15]]]]
]
------------------------------------------------------------------------

View File

@ -1,439 +0,0 @@
section 2eW, lite number theory
===============================
### `++egcd`
GCD
++ egcd :: schneier's egcd
|= [a=@ b=@]
=+ si
=+ [c=(sun a) d=(sun b)]
=+ [u=[c=(sun 1) d=--0] v=[c=--0 d=(sun 1)]]
|- ^- [d=@ u=@ v=@]
?: =(--0 c)
[(abs d) d.u d.v]
:: ?> ?& =(c (sum (pro (sun a) c.u) (pro (sun b) c.v)))
:: =(d (sum (pro (sun a) d.u) (pro (sun b) d.v)))
:: ==
=+ q=(fra d c)
%= $
c (dif d (pro q c))
d c
u [(dif d.u (pro q c.u)) c.u]
v [(dif d.v (pro q c.v)) c.v]
==
::
Greatest common denominator
~zod/try=> (egcd 20 15)
[d=5 u=2 v=1]
~zod/try=> (egcd 24 16)
[d=8 u=2 v=1]
~zod/try=> (egcd 7 5)
[d=1 u=3 v=6]
~zod/try=> (egcd (shaf ~ %ham) (shaf ~ %sam))
[ d=1
u=59.983.396.314.566.203.239.184.568.129.921.874.787
v=38.716.650.351.034.402.960.165.718.823.532.275.722
]
------------------------------------------------------------------------
### `++pram`
Probable prime
++ pram :: rabin-miller
|= a=@ ^- ?
?: ?| =(0 (end 0 1 a))
=(1 a)
=+ b=1
|- ^- ?
?: =(512 b)
|
?|(=+(c=+((mul 2 b)) &(!=(a c) =(a (mul c (div a c))))) $(b +(b)))
==
|
=+ ^= b
=+ [s=(dec a) t=0]
|- ^- [s=@ t=@]
?: =(0 (end 0 1 s))
$(s (rsh 0 1 s), t +(t))
[s t]
?> =((mul s.b (bex t.b)) (dec a))
=+ c=0
|- ^- ?
?: =(c 64)
&
=+ d=(~(raw og (add c a)) (met 0 a))
=+ e=(~(exp fo a) s.b d)
?& ?| =(1 e)
=+ f=0
|- ^- ?
?: =(e (dec a))
&
?: =(f (dec t.b))
|
$(e (~(pro fo a) e e), f +(f))
==
$(c +(c))
==
::
Probable prime test
~zod/try=> (pram 31)
%.y
~zod/try=> =+(a=2 |-(?:(=(a 31) ~ [i=(mod 31 a) t=$(a +(a))])))
~[1 1 3 1 1 3 7 4 1 9 7 5 3 1 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1]
~zod/try=> =+(a=2 |-(?:(=(a 31) ~ [i=(mod 30 a) t=$(a +(a))])))
~[0 0 2 0 0 2 6 3 0 8 6 4 2 0 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0]
~zod/try=> (pram 256)
%.n
~zod/try=> (pram (dec (bex 127)))
%.y
------------------------------------------------------------------------
### `++ramp`
`r-m` prime
++ ramp :: make r-m prime
|= [a=@ b=(list ,@) c=@] ^- @ux :: [bits snags seed]
=> .(c (shas %ramp c))
=+ d=_@
|-
?: =((mul 100 a) d)
~|(%ar-ramp !!)
=+ e=(~(raw og c) a)
?: &((levy b |=(f=@ !=(1 (mod e f)))) (pram e))
e
$(c +(c), d (shax d))
::
Random `a` bit prime, which isn't 1 modulo a list of other numbers,
using salt `c`.
~zod/try=> (ramp 20 ~ %hamelok)
0xf.1f0d
~zod/try=> (ramp 20 ~ %hameloe)
0x2.d341
~zod/try=> (ramp 5 ~ %kole)
0x1f
~zod/try=> (ramp 7 ~ %kole)
0x4f
~zod/try=> (ramp 7 ~[0x4e] %kole)
0x43
~zod/try=> `@uw`(ramp 128 ~ %late)
0w3y.irKIL.l-pp1.2CkG4.3lsTF
------------------------------------------------------------------------
### `++fo`
Prime engine
++ fo :: modulo prime
|_ a=@
XX DO NOT RERUN GET.LS, THERE EXIST ARM COLLISIONS
Core for performing arithmetic modulo a prime number
~zod/try=> ~(. fo 79)
<7.get [@ud <373.jdd 100.kzl 1.ypj %164>]>
------------------------------------------------------------------------
### `++dif`
Difference
++ dif
|= [b=@ c=@]
(sit (sub (add a b) (sit c)))
::
Subtract
~zod/try=> (~(dif fo 79) 10 5)
5
~zod/try=> (~(dif fo 79) 5 10)
74
------------------------------------------------------------------------
### `++exp`
Exponent
++ exp
|= [b=@ c=@]
?: =(0 b)
1
=+ d=$(b (rsh 0 1 b))
=+ e=(pro d d)
?:(=(0 (end 0 1 b)) e (pro c e))
::
Exponent
~zod/try=> (~(exp fo 79) 3 5)
46
------------------------------------------------------------------------
### `++fra`
Divide
++ fra
|= [b=@ c=@]
(pro b (inv c))
::
Divide
~zod/try=> (~(fra fo 79) 20 4)
5
~zod/try=> (~(fra fo 79) 7 11)
15
------------------------------------------------------------------------
### `++inv`
Inverse
++ inv
|= b=@
=+ c=(dul:si u:(egcd b a) a)
c
::
Multiplicative inverse
~zod/try=> (~(inv fo 79) 12)
33
~zod/try=> (~(pro fo 79) 12 33)
1
~zod/try=> (~(inv fo 79) 0)
0
------------------------------------------------------------------------
### `++pro`
Product
++ pro
|= [b=@ c=@]
(sit (mul b c))
::
Product
~zod/try=> (~(pro fo 79) 5 10)
50
~zod/try=> (~(pro fo 79) 5 20)
21
------------------------------------------------------------------------
### `++sit`
Bounds
++ sit
|= b=@
(mod b a)
::
Bounds check
~zod/try=> (~(sit fo 79) 9)
9
~zod/try=> (~(sit fo 79) 99)
20
------------------------------------------------------------------------
### `++sum`
Sum
++ sum
|= [b=@ c=@]
(sit (add b c))
--
Add
~zod/try=> (~(sum fo 79) 9 9)
18
~zod/try=> (~(sum fo 79) 70 9)
0
------------------------------------------------------------------------
### `++ga`
++ ga :: GF (bex p.a)
|= a=[p=@ q=@ r=@] :: dim poly gen
=+ si=(bex p.a)
=+ ma=(dec si)
=> |%
RSA internals
XX document
------------------------------------------------------------------------
### `++dif`
++ dif :: add and sub
|= [b=@ c=@]
~| [%dif-ga a]
?> &((lth b si) (lth c si))
(mix b c)
::
XX document
------------------------------------------------------------------------
### `++dub`
++ dub :: mul by x
|= b=@
~| [%dub-ga a]
?> (lth b si)
?: =(1 (cut 0 [(dec p.a) 1] b))
(dif (sit q.a) (sit (lsh 0 1 b)))
(lsh 0 1 b)
::
XX document
------------------------------------------------------------------------
### `++pro`
++ pro :: slow multiply
|= [b=@ c=@]
?: =(0 b)
0
?: =(1 (dis 1 b))
(dif c $(b (rsh 0 1 b), c (dub c)))
$(b (rsh 0 1 b), c (dub c))
::
XX document
------------------------------------------------------------------------
### `++toe`
++ toe :: exp/log tables
=+ ^= nu
|= [b=@ c=@]
^- (map ,@ ,@)
=+ d=*(map ,@ ,@)
|-
?: =(0 c)
d
%= $
c (dec c)
d (~(put by d) c b)
==
=+ [p=(nu 0 (bex p.a)) q=(nu ma ma)]
=+ [b=1 c=0]
|- ^- [p=(map ,@ ,@) q=(map ,@ ,@)]
?: =(ma c)
[(~(put by p) c b) q]
%= $
b (pro r.a b)
c +(c)
p (~(put by p) c b)
q (~(put by q) b c)
==
::
XX document
------------------------------------------------------------------------
### `++sit`
++ sit :: reduce
|= b=@
(mod b (bex p.a))
--
XX document
------------------------------------------------------------------------
### `++fra`
++ fra :: divide
|= [b=@ c=@]
(pro b (inv c))
::
XX document
------------------------------------------------------------------------
### `++inv`
++ inv :: invert
|= b=@
~| [%inv-ga a]
=+ c=(~(get by q) b)
?~ c !!
=+ d=(~(get by p) (sub ma u.c))
(need d)
::
XX document
------------------------------------------------------------------------
### `++pow`
++ pow :: exponent
|= [b=@ c=@]
=+ [d=1 e=c f=0]
|-
?: =(p.a f)
d
?: =(1 (cut 0 [f 1] b))
$(d (pro d e), e (pro e e), f +(f))
$(e (pro e e), f +(f))
::
XX document
------------------------------------------------------------------------
### `++pro`
++ pro :: multiply
|= [b=@ c=@]
~| [%pro-ga a]
=+ d=(~(get by q) b)
?~ d 0
=+ e=(~(get by q) c)
?~ e 0
=+ f=(~(get by p) (mod (add u.d u.e) ma))
(need f)
--
XX document
------------------------------------------------------------------------

View File

@ -1,717 +0,0 @@
section 2eX, jetted crypto
==========================
------------------------------------------------------------------------
### `++aesc`
++ aesc :: AES-256
~% %aesc + ~
|%
XX document
### `++en`
++ en :: ECB enc
~/ %en
|= [a=@I b=@H] ^- @uxH
=+ ahem
(be & (ex a) b)
XX document
### `++de`
++ de :: ECB dec
~/ %de
|= [a=@I b=@H] ^- @uxH
=+ ahem
(be | (ix (ex a)) b)
--
XX document
### `++ahem`
++ ahem :: AES helpers
:: XX should be in aesc, isn't for performance reasons
=>
=+ =+ [gr=(ga 8 0x11b 3) few==>(fe .(a 5))]
=+ [pro=pro.gr dif=dif.gr pow=pow.gr ror=ror.few]
[pro=pro dif=dif pow=pow ror=ror nnk=8 nnb=4 nnr=14]
=> |%
XX document
### `++cipa`
++ cipa :: AES params
$_ ^? |%
XX document
### `++co`
++ co [0xe 0xb 0xd 0x9]
XX document
### `++ix`
++ ix :: key expand, inv
|= a=@ ^- @
=+ [i=1 j=_@ b=_@ c=co:pin]
|-
?: =(nnr i)
a
=> .(b (cut 7 [i 1] a))
=> .(b (rep 5 (mcol (pode 5 4 b) c)))
=> .(j (sub nnr i))
%= $
i +(i)
a
%+ can 7
:~ [i (cut 7 [0 i] a)]
[1 b]
[j (cut 7 [+(i) j] a)]
==
==
--
::
XX document
### `++ro`
++ ro [0 3 2 1]
XX document
### `++su`
++ su 0x7d0c.2155.6314.69e1.26d6.77ba.7e04.2b17.
6199.5383.3cbb.ebc8.b0f5.2aae.4d3b.e0a0.
ef9c.c993.9f7a.e52d.0d4a.b519.a97f.5160.
5fec.8027.5910.12b1.31c7.0788.33a8.dd1f.
f45a.cd78.fec0.db9a.2079.d2c6.4b3e.56fc.
1bbe.18aa.0e62.b76f.89c5.291d.711a.f147.
6edf.751c.e837.f9e2.8535.ade7.2274.ac96.
73e6.b4f0.cecf.f297.eadc.674f.4111.913a.
6b8a.1301.03bd.afc1.020f.3fca.8f1e.2cd0.
0645.b3b8.0558.e4f7.0ad3.bc8c.00ab.d890.
849d.8da7.5746.155e.dab9.edfd.5048.706c.
92b6.655d.cc5c.a4d4.1698.6886.64f6.f872.
25d1.8b6d.49a2.5b76.b224.d928.66a1.2e08.
4ec3.fa42.0b95.4cee.3d23.c2a6.3294.7b54.
cbe9.dec4.4443.8e34.87ff.2f9b.8239.e37c.
fbd7.f381.9ea3.40bf.38a5.3630.d56a.0952
--
::
XX document
### `++pen`
++ pen :: encrypt
^- cipa
|%
XX document
### `++co`
++ co [0xe 0xb 0xd 0x9]
XX document
### `++ix`
++ ix :: key expand, inv
|= a=@ ^- @
=+ [i=1 j=_@ b=_@ c=co:pin]
|-
?: =(nnr i)
a
=> .(b (cut 7 [i 1] a))
=> .(b (rep 5 (mcol (pode 5 4 b) c)))
=> .(j (sub nnr i))
%= $
i +(i)
a
%+ can 7
:~ [i (cut 7 [0 i] a)]
[1 b]
[j (cut 7 [+(i) j] a)]
==
==
--
::
XX document
### `++ro`
++ ro [0 3 2 1]
XX document
### `++su`
++ su 0x7d0c.2155.6314.69e1.26d6.77ba.7e04.2b17.
6199.5383.3cbb.ebc8.b0f5.2aae.4d3b.e0a0.
ef9c.c993.9f7a.e52d.0d4a.b519.a97f.5160.
5fec.8027.5910.12b1.31c7.0788.33a8.dd1f.
f45a.cd78.fec0.db9a.2079.d2c6.4b3e.56fc.
1bbe.18aa.0e62.b76f.89c5.291d.711a.f147.
6edf.751c.e837.f9e2.8535.ade7.2274.ac96.
73e6.b4f0.cecf.f297.eadc.674f.4111.913a.
6b8a.1301.03bd.afc1.020f.3fca.8f1e.2cd0.
0645.b3b8.0558.e4f7.0ad3.bc8c.00ab.d890.
849d.8da7.5746.155e.dab9.edfd.5048.706c.
92b6.655d.cc5c.a4d4.1698.6886.64f6.f872.
25d1.8b6d.49a2.5b76.b224.d928.66a1.2e08.
4ec3.fa42.0b95.4cee.3d23.c2a6.3294.7b54.
cbe9.dec4.4443.8e34.87ff.2f9b.8239.e37c.
fbd7.f381.9ea3.40bf.38a5.3630.d56a.0952
--
::
XX document
### `++pin`
++ pin :: decrypt
^- cipa
|%
XX document
### `++co`
++ co [0xe 0xb 0xd 0x9]
XX document
### `++ix`
++ ix :: key expand, inv
|= a=@ ^- @
=+ [i=1 j=_@ b=_@ c=co:pin]
|-
?: =(nnr i)
a
=> .(b (cut 7 [i 1] a))
=> .(b (rep 5 (mcol (pode 5 4 b) c)))
=> .(j (sub nnr i))
%= $
i +(i)
a
%+ can 7
:~ [i (cut 7 [0 i] a)]
[1 b]
[j (cut 7 [+(i) j] a)]
==
==
--
::
XX document
### `++ro`
++ ro [0 3 2 1]
XX document
### `++su`
++ su 0x7d0c.2155.6314.69e1.26d6.77ba.7e04.2b17.
6199.5383.3cbb.ebc8.b0f5.2aae.4d3b.e0a0.
ef9c.c993.9f7a.e52d.0d4a.b519.a97f.5160.
5fec.8027.5910.12b1.31c7.0788.33a8.dd1f.
f45a.cd78.fec0.db9a.2079.d2c6.4b3e.56fc.
1bbe.18aa.0e62.b76f.89c5.291d.711a.f147.
6edf.751c.e837.f9e2.8535.ade7.2274.ac96.
73e6.b4f0.cecf.f297.eadc.674f.4111.913a.
6b8a.1301.03bd.afc1.020f.3fca.8f1e.2cd0.
0645.b3b8.0558.e4f7.0ad3.bc8c.00ab.d890.
849d.8da7.5746.155e.dab9.edfd.5048.706c.
92b6.655d.cc5c.a4d4.1698.6886.64f6.f872.
25d1.8b6d.49a2.5b76.b224.d928.66a1.2e08.
4ec3.fa42.0b95.4cee.3d23.c2a6.3294.7b54.
cbe9.dec4.4443.8e34.87ff.2f9b.8239.e37c.
fbd7.f381.9ea3.40bf.38a5.3630.d56a.0952
--
::
XX document
### `++mcol`
++ mcol
|= [a=(list ,@) b=[p=@ q=@ r=@ s=@]] ^- (list ,@)
=+ c=[p=_@ q=_@ r=_@ s=_@]
|- ^- (list ,@)
?~ a ~
=> .(p.c (cut 3 [0 1] i.a))
=> .(q.c (cut 3 [1 1] i.a))
=> .(r.c (cut 3 [2 1] i.a))
=> .(s.c (cut 3 [3 1] i.a))
:_ $(a t.a)
%+ rep 3
%+ turn
%- limo
:~ [[p.c p.b] [q.c q.b] [r.c r.b] [s.c s.b]]
[[p.c s.b] [q.c p.b] [r.c q.b] [s.c r.b]]
[[p.c r.b] [q.c s.b] [r.c p.b] [s.c q.b]]
[[p.c q.b] [q.c r.b] [r.c s.b] [s.c p.b]]
==
|= [a=[@ @] b=[@ @] c=[@ @] d=[@ @]]
:(dif (pro a) (pro b) (pro c) (pro d))
::
XX document
### `++pode`
++ pode :: explode to block
|= [a=bloq b=@ c=@] ^- (list ,@)
=+ d=(rip a c)
=+ m=(met a c)
|-
?: =(m b)
d
$(m +(m), d (weld d (limo [0 ~])))
XX document
### `++sube`
++ sube :: s-box word
|= [a=@ b=@] ^- @
(rep 3 (turn (pode 3 4 a) |=(c=@ (cut 3 [c 1] b))))
--
|%
XX document
### `++be`
++ be :: block cipher
|= [a=? b=@ c=@H] ^- @uxH
~| %be-aesc
=> %= .
+
=> +
|%
XX document
### `++ankh`
++ ankh
|= [a=cipa b=@ c=@]
(pode 5 nnb (cut 5 [(mul (ix.a b) nnb) nnb] c))
XX document
### `++sark`
++ sark
|= [c=(list ,@) d=(list ,@)] ^- (list ,@)
?~ c ~
?~ d !!
[(mix i.c i.d) $(c t.c, d t.d)]
XX document
### `++srow`
++ srow
|= [a=cipa b=(list ,@)] ^- (list ,@)
=+ [c=0 d=~ e=ro.a]
|-
?: =(c nnb)
d
:_ $(c +(c))
%+ rep 3
%+ turn
(limo [0 p.e] [1 q.e] [2 r.e] [3 s.e] ~)
|= [f=@ g=@]
(cut 3 [f 1] (snag (mod (add g c) nnb) b))
XX document
### `++subs`
++ subs
|= [a=cipa b=(list ,@)] ^- (list ,@)
?~ b ~
[(sube i.b su.a) $(b t.b)]
--
==
=+ [d=?:(a pen pin) e=(pode 5 nnb c) f=1]
=> .(e (sark e (ankh d 0 b)))
|-
?. =(nnr f)
=> .(e (subs d e))
=> .(e (srow d e))
=> .(e (mcol e co.d))
=> .(e (sark e (ankh d f b)))
$(f +(f))
=> .(e (subs d e))
=> .(e (srow d e))
=> .(e (sark e (ankh d nnr b)))
(rep 5 e)
XX document
### `++ex`
++ ex :: key expand
|= a=@I ^- @
=+ [b=a c=0 d=su:pen i=nnk]
|-
?: =(i (mul nnb +(nnr)))
b
=> .(c (cut 5 [(dec i) 1] b))
=> ?: =(0 (mod i nnk))
=> .(c (ror 3 1 c))
=> .(c (sube c d))
.(c (mix c (pow (dec (div i nnk)) 2)))
?: &((gth nnk 6) =(4 (mod i nnk)))
.(c (sube c d))
.
=> .(c (mix c (cut 5 [(sub i nnk) 1] b)))
=> .(b (can 5 [i b] [1 c] ~))
$(i +(i))
XX document
### `++ix`
++ ix :: key expand, inv
|= a=@ ^- @
=+ [i=1 j=_@ b=_@ c=co:pin]
|-
?: =(nnr i)
a
=> .(b (cut 7 [i 1] a))
=> .(b (rep 5 (mcol (pode 5 4 b) c)))
=> .(j (sub nnr i))
%= $
i +(i)
a
%+ can 7
:~ [i (cut 7 [0 i] a)]
[1 b]
[j (cut 7 [+(i) j] a)]
==
==
--
::
XX document
### `++curt`
++ curt :: curve25519
|= [a=@ b=@]
=> %= .
+
=> +
=+ =+ [p=486.662 q=(sub (bex 255) 19)]
=+ fq=~(. fo q)
[p=p q=q fq=fq]
|%
XX document
### `++cla`
++ cla
|= raw=@
=+ low=(dis 248 (cut 3 [0 1] raw))
=+ hih=(con 64 (dis 127 (cut 3 [31 1] raw)))
=+ mid=(cut 3 [1 30] raw)
(can 3 [[1 low] [30 mid] [1 hih] ~])
XX document
### `++sqr`
++ sqr |=(a=@ (mul a a))
XX document
### `++inv`
++ inv |=(a=@ (~(exp fo q) (sub q 2) a))
XX document
### `++cad`
++ cad
|= [n=[x=@ z=@] m=[x=@ z=@] d=[x=@ z=@]]
=+ ^= xx
;: mul 4 z.d
%- sqr %- abs:si
%+ dif:si
(sun:si (mul x.m x.n))
(sun:si (mul z.m z.n))
==
=+ ^= zz
;: mul 4 x.d
%- sqr %- abs:si
%+ dif:si
(sun:si (mul x.m z.n))
(sun:si (mul z.m x.n))
==
[(sit.fq xx) (sit.fq zz)]
XX document
### `++cub`
++ cub
|= [x=@ z=@]
=+ ^= xx
%+ mul
%- sqr %- abs:si
(dif:si (sun:si x) (sun:si z))
(sqr (add x z))
=+ ^= zz
;: mul 4 x z
:(add (sqr x) :(mul p x z) (sqr z))
==
[(sit.fq xx) (sit.fq zz)]
--
==
=+ one=[b 1]
=+ i=253
=+ r=one
=+ s=(cub one)
|-
?: =(i 0)
=+ x=(cub r)
(sit.fq (mul -.x (inv +.x)))
=+ m=(rsh 0 i a)
?: =(0 (mod m 2))
$(i (dec i), s (cad r s one), r (cub r))
$(i (dec i), r (cad r s one), s (cub s))
::
XX document
### `++ed`
++ ed :: ed25519
=>
=+ =+ [b=256 q=(sub (bex 255) 19)]
=+ fq=~(. fo q)
=+ ^= l
%+ add
(bex 252)
27.742.317.777.372.353.535.851.937.790.883.648.493
=+ d=(dif.fq 0 (fra.fq 121.665 121.666))
=+ ii=(exp.fq (div (dec q) 4) 2)
[b=b q=q fq=fq l=l d=d ii=ii]
~% %coed +> ~
|%
### `++norm`
++ norm |=(x=@ ?:(=(0 (mod x 2)) x (sub q x)))
::
XX document
### `++xrec`
++ xrec :: recover x-coord
|= y=@ ^- @
=+ ^= xx
%+ mul (dif.fq (mul y y) 1)
(inv.fq +(:(mul d y y)))
=+ x=(exp.fq (div (add 3 q) 8) xx)
?: !=(0 (dif.fq (mul x x) (sit.fq xx)))
(norm (pro.fq x ii))
(norm x)
::
XX document
### `++ward`
++ ward :: edwards multiply
|= [pp=[@ @] qq=[@ @]] ^- [@ @]
=+ dp=:(pro.fq d -.pp -.qq +.pp +.qq)
=+ ^= xt
%+ pro.fq
%+ sum.fq
(pro.fq -.pp +.qq)
(pro.fq -.qq +.pp)
(inv.fq (sum.fq 1 dp))
=+ ^= yt
%+ pro.fq
%+ sum.fq
(pro.fq +.pp +.qq)
(pro.fq -.pp -.qq)
(inv.fq (dif.fq 1 dp))
[xt yt]
::
XX document
### `++scam`
++ scam :: scalar multiply
|= [pp=[@ @] e=@] ^- [@ @]
?: =(0 e)
[0 1]
=+ qq=$(e (div e 2))
=> .(qq (ward qq qq))
?: =(1 (dis 1 e))
(ward qq pp)
qq
::
XX document
### `++etch`
++ etch :: encode point
|= pp=[@ @] ^- @
(can 0 ~[[(sub b 1) +.pp] [1 (dis 1 -.pp)]])
::
XX document
### `++curv`
++ curv :: point on curve?
|= [x=@ y=@] ^- ?
.= 0
%+ dif.fq
%+ sum.fq
(pro.fq (sub q (sit.fq x)) x)
(pro.fq y y)
(sum.fq 1 :(pro.fq d x x y y))
::
XX document
### `++deco`
++ deco :: decode point
|= s=@ ^- (unit ,[@ @])
=+ y=(cut 0 [0 (dec b)] s)
=+ si=(cut 0 [(dec b) 1] s)
=+ x=(xrec y)
=> .(x ?:(!=(si (dis 1 x)) (sub q x) x))
=+ pp=[x y]
?. (curv pp)
~
[~ pp]
::
XX document
### `++bb`
++ bb
=+ bby=(pro.fq 4 (inv.fq 5))
[(xrec bby) bby]
::
--
~% %ed + ~
|%
XX document
### `++puck`
++ puck :: public key
~/ %puck
|= sk=@I ^- @
?: (gth (met 3 sk) 32) !!
=+ h=(shal (rsh 0 3 b) sk)
=+ ^= a
%+ add
(bex (sub b 2))
(lsh 0 3 (cut 0 [3 (sub b 5)] h))
=+ aa=(scam bb a)
(etch aa)
XX document
### `++suck`
++ suck :: keypair from seed
|= se=@I ^- @uJ
=+ pu=(puck se)
(can 0 ~[[b se] [b pu]])
::
XX document
### `++sign`
++ sign :: certify
~/ %sign
|= [m=@ se=@] ^- @
=+ sk=(suck se)
=+ pk=(cut 0 [b b] sk)
=+ h=(shal (rsh 0 3 b) sk)
=+ ^= a
%+ add
(bex (sub b 2))
(lsh 0 3 (cut 0 [3 (sub b 5)] h))
=+ ^= r
=+ hm=(cut 0 [b b] h)
=+ ^= i
%+ can 0
:~ [b hm]
[(met 0 m) m]
==
(shaz i)
=+ rr=(scam bb r)
=+ ^= ss
=+ er=(etch rr)
=+ ^= ha
%+ can 0
:~ [b er]
[b pk]
[(met 0 m) m]
==
(~(sit fo l) (add r (mul (shaz ha) a)))
(can 0 ~[[b (etch rr)] [b ss]])
::
XX document
### `++veri`
++ veri :: validate
~/ %veri
|= [s=@ m=@ pk=@] ^- ?
?: (gth (div b 4) (met 3 s)) |
?: (gth (div b 8) (met 3 pk)) |
=+ cb=(rsh 0 3 b)
=+ rr=(deco (cut 0 [0 b] s))
?~ rr |
=+ aa=(deco pk)
?~ aa |
=+ ss=(cut 0 [b b] s)
=+ ha=(can 3 ~[[cb (etch u.rr)] [cb pk] [(met 3 m) m]])
=+ h=(shaz ha)
=((scam bb ss) (ward u.rr (scam u.aa h)))
::
--
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
XX document
------------------------------------------------------------------------

View File

@ -1,399 +0,0 @@
section 2eY, SHA-256
====================
### `++shad`
++ shad |=(ruz=@ (shax (shax ruz))) :: double sha-256
XX document
### `++shaf`
++ shaf :: half sha-256
|= [sal=@ ruz=@]
=+ haz=(shas sal ruz)
(mix (end 7 1 haz) (rsh 7 1 haz))
::
XX document
### `++shak`
++ shak :: XX shd be PBKDF
|= [who=@p wud=@]
(shas (mix %shak who) wud)
::
XX document
### `++sham`
++ sham :: noun hash
|= yux=* ^- @uvH ^- @
?@ yux
(shaf %mash yux)
(shaf %sham (jam yux))
::
XX document
### `++shas`
++ shas :: salted hash
|= [sal=@ ruz=@]
(shax (mix sal (shax ruz)))
::
XX document
### `++shax`
++ shax :: sha-256
~/ %shax
|= ruz=@ ^- @
~| %sha
=+ [few==>(fe .(a 5)) wac=|=([a=@ b=@] (cut 5 [a 1] b))]
=+ [sum=sum.few ror=ror.few net=net.few inv=inv.few]
=+ ral=(lsh 0 3 (met 3 ruz))
=+ ^= ful
%+ can 0
:~ [ral ruz]
[8 128]
[(mod (sub 960 (mod (add 8 ral) 512)) 512) 0]
[64 (~(net fe 6) ral)]
==
=+ lex=(met 9 ful)
=+ ^= kbx 0xc671.78f2.bef9.a3f7.a450.6ceb.90be.fffa.
8cc7.0208.84c8.7814.78a5.636f.748f.82ee.
682e.6ff3.5b9c.ca4f.4ed8.aa4a.391c.0cb3.
34b0.bcb5.2748.774c.1e37.6c08.19a4.c116.
106a.a070.f40e.3585.d699.0624.d192.e819.
c76c.51a3.c24b.8b70.a81a.664b.a2bf.e8a1.
9272.2c85.81c2.c92e.766a.0abb.650a.7354.
5338.0d13.4d2c.6dfc.2e1b.2138.27b7.0a85.
1429.2967.06ca.6351.d5a7.9147.c6e0.0bf3.
bf59.7fc7.b003.27c8.a831.c66d.983e.5152.
76f9.88da.5cb0.a9dc.4a74.84aa.2de9.2c6f.
240c.a1cc.0fc1.9dc6.efbe.4786.e49b.69c1.
c19b.f174.9bdc.06a7.80de.b1fe.72be.5d74.
550c.7dc3.2431.85be.1283.5b01.d807.aa98.
ab1c.5ed5.923f.82a4.59f1.11f1.3956.c25b.
e9b5.dba5.b5c0.fbcf.7137.4491.428a.2f98
=+ ^= hax 0x5be0.cd19.1f83.d9ab.9b05.688c.510e.527f.
a54f.f53a.3c6e.f372.bb67.ae85.6a09.e667
=+ i=0
|- ^- @
?: =(i lex)
(rep 5 (turn (rip 5 hax) net))
=+ ^= wox
=+ dux=(cut 9 [i 1] ful)
=+ wox=(rep 5 (turn (rip 5 dux) net))
=+ j=16
|- ^- @
?: =(64 j)
wox
=+ :* l=(wac (sub j 15) wox)
m=(wac (sub j 2) wox)
n=(wac (sub j 16) wox)
o=(wac (sub j 7) wox)
==
=+ x=:(mix (ror 0 7 l) (ror 0 18 l) (rsh 0 3 l))
=+ y=:(mix (ror 0 17 m) (ror 0 19 m) (rsh 0 10 m))
=+ z=:(sum n x o y)
$(wox (con (lsh 5 j z) wox), j +(j))
=+ j=0
=+ :* a=(wac 0 hax)
b=(wac 1 hax)
c=(wac 2 hax)
d=(wac 3 hax)
e=(wac 4 hax)
f=(wac 5 hax)
g=(wac 6 hax)
h=(wac 7 hax)
==
|- ^- @
?: =(64 j)
%= ^$
i +(i)
hax %+ rep 5
:~ (sum a (wac 0 hax))
(sum b (wac 1 hax))
(sum c (wac 2 hax))
(sum d (wac 3 hax))
(sum e (wac 4 hax))
(sum f (wac 5 hax))
(sum g (wac 6 hax))
(sum h (wac 7 hax))
==
==
=+ l=:(mix (ror 0 2 a) (ror 0 13 a) (ror 0 22 a)) :: s0
=+ m=:(mix (dis a b) (dis a c) (dis b c)) :: maj
=+ n=(sum l m) :: t2
=+ o=:(mix (ror 0 6 e) (ror 0 11 e) (ror 0 25 e)) :: s1
=+ p=(mix (dis e f) (dis (inv e) g)) :: ch
=+ q=:(sum h o p (wac j kbx) (wac j wox)) :: t1
$(j +(j), a (sum q n), b a, c b, d c, e (sum d q), f e, g f, h g)
::
XX document
### `++shaw`
++ shaw :: hash to nbits
|= [sal=@ len=@ ruz=@]
(~(raw og (shas sal (mix len ruz))) len)
::
XX document
### `++og`
++ og :: shax-powered rng
~/ %og
|_ a=@
XX document
### `++rad`
++ rad :: random in range
|= b=@ ^- @
=+ c=(raw (met 0 b))
?:((lth c b) c $(a +(a)))
::
XX document
### `++rads`
++ rads :: random continuation
|= b=@
=+ r=(rad b)
[r +>.$(a (shas %og-s r))]
XX document
### `++raw`
++ raw :: random bits
~/ %raw
|= b=@ ^- @
%+ can
0
=+ c=(shas %og-a (mix b a))
|- ^- (list ,[@ @])
?: =(0 b)
~
=+ d=(shas %og-b (mix b (mix a c)))
?: (lth b 256)
[[b (end 0 b d)] ~]
[[256 d] $(c d, b (sub b 256))]
XX document
### `++raws`
++ raws :: random bits continuation
|= b=@
=+ r=(raw b)
[r +>.$(a (shas %og-s r))]
--
XX document
### `++shaz`
++ shaz :: sha-512
|= ruz=@ ^- @
(shal [(met 3 ruz) ruz])
XX document
### `++shal`
++ shal :: sha-512 with length
~/ %shal
|= [len=@ ruz=@] ^- @
=> .(ruz (cut 3 [0 len] ruz))
=+ [few==>(fe .(a 6)) wac=|=([a=@ b=@] (cut 6 [a 1] b))]
=+ [sum=sum.few ror=ror.few net=net.few inv=inv.few]
=+ ral=(lsh 0 3 len)
=+ ^= ful
%+ can 0
:~ [ral ruz]
[8 128]
[(mod (sub 1.920 (mod (add 8 ral) 1.024)) 1.024) 0]
[128 (~(net fe 7) ral)]
==
=+ lex=(met 10 ful)
=+ ^= kbx 0x6c44.198c.4a47.5817.5fcb.6fab.3ad6.faec.
597f.299c.fc65.7e2a.4cc5.d4be.cb3e.42b6.
431d.67c4.9c10.0d4c.3c9e.be0a.15c9.bebc.
32ca.ab7b.40c7.2493.28db.77f5.2304.7d84.
1b71.0b35.131c.471b.113f.9804.bef9.0dae.
0a63.7dc5.a2c8.98a6.06f0.67aa.7217.6fba.
f57d.4f7f.ee6e.d178.eada.7dd6.cde0.eb1e.
d186.b8c7.21c0.c207.ca27.3ece.ea26.619c.
c671.78f2.e372.532b.bef9.a3f7.b2c6.7915.
a450.6ceb.de82.bde9.90be.fffa.2363.1e28.
8cc7.0208.1a64.39ec.84c8.7814.a1f0.ab72.
78a5.636f.4317.2f60.748f.82ee.5def.b2fc.
682e.6ff3.d6b2.b8a3.5b9c.ca4f.7763.e373.
4ed8.aa4a.e341.8acb.391c.0cb3.c5c9.5a63.
34b0.bcb5.e19b.48a8.2748.774c.df8e.eb99.
1e37.6c08.5141.ab53.19a4.c116.b8d2.d0c8.
106a.a070.32bb.d1b8.f40e.3585.5771.202a.
d699.0624.5565.a910.d192.e819.d6ef.5218.
c76c.51a3.0654.be30.c24b.8b70.d0f8.9791.
a81a.664b.bc42.3001.a2bf.e8a1.4cf1.0364.
9272.2c85.1482.353b.81c2.c92e.47ed.aee6.
766a.0abb.3c77.b2a8.650a.7354.8baf.63de.
5338.0d13.9d95.b3df.4d2c.6dfc.5ac4.2aed.
2e1b.2138.5c26.c926.27b7.0a85.46d2.2ffc.
1429.2967.0a0e.6e70.06ca.6351.e003.826f.
d5a7.9147.930a.a725.c6e0.0bf3.3da8.8fc2.
bf59.7fc7.beef.0ee4.b003.27c8.98fb.213f.
a831.c66d.2db4.3210.983e.5152.ee66.dfab.
76f9.88da.8311.53b5.5cb0.a9dc.bd41.fbd4.
4a74.84aa.6ea6.e483.2de9.2c6f.592b.0275.
240c.a1cc.77ac.9c65.0fc1.9dc6.8b8c.d5b5.
efbe.4786.384f.25e3.e49b.69c1.9ef1.4ad2.
c19b.f174.cf69.2694.9bdc.06a7.25c7.1235.
80de.b1fe.3b16.96b1.72be.5d74.f27b.896f.
550c.7dc3.d5ff.b4e2.2431.85be.4ee4.b28c.
1283.5b01.4570.6fbe.d807.aa98.a303.0242.
ab1c.5ed5.da6d.8118.923f.82a4.af19.4f9b.
59f1.11f1.b605.d019.3956.c25b.f348.b538.
e9b5.dba5.8189.dbbc.b5c0.fbcf.ec4d.3b2f.
7137.4491.23ef.65cd.428a.2f98.d728.ae22
=+ ^= hax 0x5be0.cd19.137e.2179.1f83.d9ab.fb41.bd6b.
9b05.688c.2b3e.6c1f.510e.527f.ade6.82d1.
a54f.f53a.5f1d.36f1.3c6e.f372.fe94.f82b.
bb67.ae85.84ca.a73b.6a09.e667.f3bc.c908
=+ i=0
|- ^- @
?: =(i lex)
(rep 6 (turn (rip 6 hax) net))
=+ ^= wox
=+ dux=(cut 10 [i 1] ful)
=+ wox=(rep 6 (turn (rip 6 dux) net))
=+ j=16
|- ^- @
?: =(80 j)
wox
=+ :* l=(wac (sub j 15) wox)
m=(wac (sub j 2) wox)
n=(wac (sub j 16) wox)
o=(wac (sub j 7) wox)
==
=+ x=:(mix (ror 0 1 l) (ror 0 8 l) (rsh 0 7 l))
=+ y=:(mix (ror 0 19 m) (ror 0 61 m) (rsh 0 6 m))
=+ z=:(sum n x o y)
$(wox (con (lsh 6 j z) wox), j +(j))
=+ j=0
=+ :* a=(wac 0 hax)
b=(wac 1 hax)
c=(wac 2 hax)
d=(wac 3 hax)
e=(wac 4 hax)
f=(wac 5 hax)
g=(wac 6 hax)
h=(wac 7 hax)
==
|- ^- @
?: =(80 j)
%= ^$
i +(i)
hax %+ rep 6
:~ (sum a (wac 0 hax))
(sum b (wac 1 hax))
(sum c (wac 2 hax))
(sum d (wac 3 hax))
(sum e (wac 4 hax))
(sum f (wac 5 hax))
(sum g (wac 6 hax))
(sum h (wac 7 hax))
==
==
=+ l=:(mix (ror 0 28 a) (ror 0 34 a) (ror 0 39 a)) :: S0
=+ m=:(mix (dis a b) (dis a c) (dis b c)) :: maj
=+ n=(sum l m) :: t2
=+ o=:(mix (ror 0 14 e) (ror 0 18 e) (ror 0 41 e)) :: S1
=+ p=(mix (dis e f) (dis (inv e) g)) :: ch
=+ q=:(sum h o p (wac j kbx) (wac j wox)) :: t1
$(j +(j), a (sum q n), b a, c b, d c, e (sum d q), f e, g f, h g)
::
XX document
### `++shan`
++ shan :: sha-1 (deprecated)
|= ruz=@
=+ [few==>(fe .(a 5)) wac=|=([a=@ b=@] (cut 5 [a 1] b))]
=+ [sum=sum.few ror=ror.few rol=rol.few net=net.few inv=inv.few]
=+ ral=(lsh 0 3 (met 3 ruz))
=+ ^= ful
%+ can 0
:~ [ral ruz]
[8 128]
[(mod (sub 960 (mod (add 8 ral) 512)) 512) 0]
[64 (~(net fe 6) ral)]
==
=+ lex=(met 9 ful)
=+ kbx=0xca62.c1d6.8f1b.bcdc.6ed9.eba1.5a82.7999
=+ hax=0xc3d2.e1f0.1032.5476.98ba.dcfe.efcd.ab89.6745.2301
=+ i=0
|-
?: =(i lex)
(rep 5 (flop (rip 5 hax)))
=+ ^= wox
=+ dux=(cut 9 [i 1] ful)
=+ wox=(rep 5 (turn (rip 5 dux) net))
=+ j=16
|- ^- @
?: =(80 j)
wox
=+ :* l=(wac (sub j 3) wox)
m=(wac (sub j 8) wox)
n=(wac (sub j 14) wox)
o=(wac (sub j 16) wox)
==
=+ z=(rol 0 1 :(mix l m n o))
$(wox (con (lsh 5 j z) wox), j +(j))
=+ j=0
=+ :* a=(wac 0 hax)
b=(wac 1 hax)
c=(wac 2 hax)
d=(wac 3 hax)
e=(wac 4 hax)
==
|- ^- @
?: =(80 j)
%= ^$
i +(i)
hax %+ rep 5
:~
(sum a (wac 0 hax))
(sum b (wac 1 hax))
(sum c (wac 2 hax))
(sum d (wac 3 hax))
(sum e (wac 4 hax))
==
==
=+ fx=(con (dis b c) (dis (not 5 1 b) d))
=+ fy=:(mix b c d)
=+ fz=:(con (dis b c) (dis b d) (dis c d))
=+ ^= tem
?: &((gte j 0) (lte j 19))
:(sum (rol 0 5 a) fx e (wac 0 kbx) (wac j wox))
?: &((gte j 20) (lte j 39))
:(sum (rol 0 5 a) fy e (wac 1 kbx) (wac j wox))
?: &((gte j 40) (lte j 59))
:(sum (rol 0 5 a) fz e (wac 2 kbx) (wac j wox))
:(sum (rol 0 5 a) fy e (wac 3 kbx) (wac j wox))
$(j +(j), a tem, b a, c (rol 0 30 b), d c, e d)
XX document
--

View File

@ -1,250 +0,0 @@
section 2eZ, OLD rendering
==========================
### `++show`
++ show :: XX deprecated, use type
|= vem=*
|^ ^- tank
?: ?=(@ vem)
[%leaf (mesc (trip vem))]
?- vem
[s=~ c=*]
[%leaf '\'' (weld (mesc (tape +.vem)) `tape`['\'' ~])]
::
[s=%a c=@] [%leaf (mesc (trip c.vem))]
[s=%b c=*] (shop c.vem |=(a=@ ~(rub at a)))
[s=[%c p=@] c=*]
:+ %palm
[['.' ~] ['-' ~] ~ ~]
[[%leaf (mesc (trip p.s.vem))] $(vem c.vem) ~]
::
[s=%d c=*] (shop c.vem |=(a=@ ~(rud at a)))
[s=%k c=*] (tank c.vem)
[s=%h c=*]
?: =(0 c.vem) :: XX remove after 220
[%leaf '#' ~]
:+ %rose
[['/' ~] ['/' ~] ~]
=+ yol=((list ,@ta) c.vem)
(turn yol |=(a=@ta [%leaf (trip a)]))
::
[s=%o c=*]
%= $
vem
:- [%m '%h:<[%d %d].[%d %d]>']
[-.c.vem +<-.c.vem +<+.c.vem +>-.c.vem +>+.c.vem ~]
==
::
[s=%p c=*] (shop c.vem |=(a=@ ~(rup at a)))
[s=%q c=*] (shop c.vem |=(a=@ ~(r at a)))
[s=%r c=*] $(vem [[%r ' ' '{' '}'] c.vem])
[s=%t c=*] (shop c.vem |=(a=@ ~(rt at a)))
[s=%v c=*] (shop c.vem |=(a=@ ~(ruv at a)))
[s=%x c=*] (shop c.vem |=(a=@ ~(rux at a)))
[s=[%m p=@] c=*] (shep p.s.vem c.vem)
[s=[%r p=@] c=*]
$(vem [[%r ' ' (cut 3 [0 1] p.s.vem) (cut 3 [1 1] p.s.vem)] c.vem])
::
[s=[%r p=@ q=@ r=@] c=*]
:+ %rose
:* p=(mesc (trip p.s.vem))
q=(mesc (trip q.s.vem))
r=(mesc (trip r.s.vem))
==
|- ^- (list tank)
?@ c.vem
~
[^$(vem -.c.vem) $(c.vem +.c.vem)]
::
[s=%z c=*] $(vem [[%r %$ %$ %$] c.vem])
* !!
==
XX document
### `++shep`
++ shep
|= [fom=@ gar=*]
^- tank
=+ l=(met 3 fom)
=+ i=0
:- %leaf
|- ^- tape
?: (gte i l)
~
=+ c=(cut 3 [i 1] fom)
?. =(37 c)
(weld (mesc [c ~]) $(i +(i)))
=+ d=(cut 3 [+(i) 1] fom)
?. .?(gar)
['\\' '#' $(i (add 2 i))]
(weld ~(ram re (show d -.gar)) $(i (add 2 i), gar +.gar))
::
XX document
### `++shop`
++ shop
|= [aug=* vel=$+(a=@ tape)]
^- tank
?: ?=(@ aug)
[%leaf (vel aug)]
:+ %rose
[[' ' ~] ['[' ~] [']' ~]]
=> .(aug `*`aug)
|- ^- (list tank)
?: ?=(@ aug)
[^$ ~]
[^$(aug -.aug) $(aug +.aug)]
--
XX document
### `++at`
++ at
|_ a=@
XX document
### `++r`
++ r
?: ?& (gte (met 3 a) 2)
|-
?: =(0 a)
&
=+ vis=(end 3 1 a)
?& ?|(=('-' vis) ?&((gte vis 'a') (lte vis 'z')))
$(a (rsh 3 1 a))
==
==
rtam
?: (lte (met 3 a) 2)
rud
rux
::
XX document
### `++rf`
++ rf `tape`[?-(a & '&', | '|', * !!) ~]
XX document
### `++rn`
++ rn `tape`[?>(=(0 a) '~') ~]
XX document
### `++rt`
++ rt `tape`['\'' (weld (mesc (trip a)) `tape`['\'' ~])]
XX document
### `++rta`
++ rta rt
XX document
### `++rtam`
++ rtam `tape`['%' (trip a)]
XX document
### `++rub`
++ rub `tape`['0' 'b' (rum 2 ~ |=(b=@ (add '0' b)))]
XX document
### `++rud`
++ rud (rum 10 ~ |=(b=@ (add '0' b)))
XX document
### `++rum`
++ rum
|= [b=@ c=tape d=$+(@ @)]
^- tape
?: =(0 a)
[(d 0) c]
=+ e=0
|- ^- tape
?: =(0 a)
c
=+ f=&(!=(0 e) =(0 (mod e ?:(=(10 b) 3 4))))
%= $
a (div a b)
c [(d (mod a b)) ?:(f [?:(=(10 b) ',' '-') c] c)]
e +(e)
==
::
XX document
### `++rup`
++ rup
=+ b=(met 3 a)
^- tape
:- '-'
|- ^- tape
?: (gth (met 5 a) 1)
%+ weld
$(a (rsh 5 1 a), b (sub b 4))
`tape`['-' '-' $(a (end 5 1 a), b 4)]
?: =(0 b)
['~' ~]
?: (lte b 1)
(trip (tos:po a))
|- ^- tape
?: =(2 b)
=+ c=(rsh 3 1 a)
=+ d=(end 3 1 a)
(weld (trip (tod:po c)) (trip (tos:po (mix c d))))
=+ c=(rsh 3 2 a)
=+ d=(end 3 2 a)
(weld ^$(a c, b (met 3 c)) `tape`['-' $(a (mix c d), b 2)])
::
XX document
### `++ruv`
++ ruv
^- tape
:+ '0'
'v'
%^ rum
64
~
|= b=@
?: =(63 b)
'+'
?: =(62 b)
'-'
?:((lth b 26) (add 65 b) ?:((lth b 52) (add 71 b) (sub b 4)))
::
XX document
### `++rux`
++ rux `tape`['0' 'x' (rum 16 ~ |=(b=@ (add b ?:((lth b 10) 48 87))))]
--
:::::::::::::::::::::::::::::::::::::::::::::::::::::: ::
XX document
------------------------------------------------------------------------

View File

@ -1,67 +0,0 @@
section 3bA, lite number theory
===============================
### `++fu`
++ fu :: modulo (mul p q)
|= a=[p=@ q=@]
=+ b=?:(=([0 0] a) 0 (~(inv fo p.a) (~(sit fo p.a) q.a)))
|%
XX document
### `++dif`
++ dif
|= [c=[@ @] d=[@ @]]
[(~(dif fo p.a) -.c -.d) (~(dif fo q.a) +.c +.d)]
::
XX document
### `++exp`
++ exp
|= [c=@ d=[@ @]]
:- (~(exp fo p.a) (mod c (dec p.a)) -.d)
(~(exp fo q.a) (mod c (dec q.a)) +.d)
::
XX document
### `++out`
++ out :: garner's formula
|= c=[@ @]
%+ add
+.c
(mul q.a (~(pro fo p.a) b (~(dif fo p.a) -.c (~(sit fo p.a) +.c))))
::
XX document
### `++pro`
++ pro
|= [c=[@ @] d=[@ @]]
[(~(pro fo p.a) -.c -.d) (~(pro fo q.a) +.c +.d)]
::
XX document
### `++sum`
++ sum
|= [c=[@ @] d=[@ @]]
[(~(sum fo p.a) -.c -.d) (~(sum fo q.a) +.c +.d)]
::
XX document
### `++sit`
++ sit
|= c=@
[(mod c p.a) (mod c q.a)]
XX document

View File

@ -1,600 +0,0 @@
section 3bB, cryptosuites
=========================
### `++crua`
++ crua !: :: cryptosuite A (RSA)
^- acru
=| [mos=@ pon=(unit ,[p=@ q=@ r=[p=@ q=@] s=_*fu])]
=> |%
XX document
### `++mx`
++ mx (dec (met 0 mos)) :: bit length
XX document
### `++dap`
++ dap :: OEAP decode
|= [wid=@ xar=@ dog=@] ^- [p=@ q=@]
=+ pav=(sub wid xar)
=+ qoy=(cut 0 [xar pav] dog)
=+ dez=(mix (end 0 xar dog) (shaw %pad-b xar qoy))
[dez (mix qoy (shaw %pad-a pav dez))]
::
XX document
### `++pad`
++ pad :: OEAP encode
|= [wid=@ rax=[p=@ q=@] meg=@] ^- @
=+ pav=(sub wid p.rax)
?> (gte pav (met 0 meg))
^- @
=+ qoy=(mix meg (shaw %pad-a pav q.rax))
=+ dez=(mix q.rax (shaw %pad-b p.rax qoy))
(can 0 [p.rax dez] [pav qoy] ~)
|%
XX document
### `++pull`
++ pull |=(a=@ (~(exp fo mos) 3 a))
XX document
### `++push`
++ push |=(a=@ (~(exp fo mos) 5 a))
XX document
### `++pump`
++ pump
|= a=@ ^- @
?~ pon !!
(out.s.u.pon (exp.s.u.pon p.r.u.pon (sit.s.u.pon a)))
::
XX document
### `++punt`
++ punt
|= a=@ ^- @
?~ pon !!
(out.s.u.pon (exp.s.u.pon q.r.u.pon (sit.s.u.pon a)))
|%
XX document
### `++as`
++ as
=> |%
XX document
### `++haul`
++ haul :: revealing haul
|= a=pass
!!
^?
|% ++ seal
|= [a=pass b=@ c=@]
^- @
!!
XX document
### `++seal`
XX document
###++sign
```
++ sign
|= [a=@ b=@] ^- @
!!
```
XX document
###++sure
```
++ sure
|= [a=@ b=@]
^- (unit ,@)
!!
```
XX document
###++tear
```
++ tear
|= [a=pass b=@]
^- (unit ,[p=@ q=@])
!!
::
```
XX document
###++de
```
++ de
|+ [key=@ cep=@] ^- (unit ,@)
!!
::
```
XX document
###++dy
```
++ dy
|+ [a=@ b=@] ^- @
!!
```
XX document
###++en
```
++ en
|+ [key=@ msg=@] ^- @ux
!!
::
```
XX document
###++ex
```
++ ex ^?
|% ++ fig ^- @uvH (shaf %bfig puc)
```
XX document
###++fig
XX document
### `++pac`
++ pac ^- @uvG (end 6 1 (shaf %acod sec))
XX document
### `++pub`
++ pub ^- pass (cat 3 'b' puc)
XX document
### `++sec`
++ sec ^- ring sed
::
XX document
### `++nu`
++ nu
^?
|% ++ com
|= a=@
^+ ^?(..nu)
..nu(sed ~, puc a)
::
XX document
### `++elcm`
++ elcm
|= [a=@ b=@]
(div (mul a b) d:(egcd a b))
::
XX document
### `++eldm`
++ eldm
|= [a=@ b=@ c=@]
(~(inv fo (elcm (dec b) (dec c))) a)
::
XX document
### `++ersa`
++ ersa
|= [a=@ b=@]
[a b [(eldm 3 a b) (eldm 5 a b)] (fu a b)]
^?
|% ++ com
|= a=@
^+ ^?(..nu)
..nu(mos a, pon ~)
::
XX document
### `++com`
XX document
###++pit
```
++ pit
|= [a=@ b=@]
^+ ^?(..nu)
..nu(sed b, puc (puck:ed b))
::
```
XX document
###++nol
```
++ nol
|= a=@
^+ ^?(..nu)
..nu(sed a, puc (puck:ed a))
```
XX document
###++bruw
```
++ bruw :: create keypair
|= [a=@ b=@] :: width seed
^- acru
(pit:nu:crua a b)
::
```
XX document
###++haul
```
++ haul :: revealing haul
|= a=pass
!!
^?
|% ++ seal
|= [a=pass b=@ c=@]
^- @
!!
```
XX document
###++weur
```
++ weur :: activate secret key
|= a=ring
^- acru
=+ [mag=(end 3 1 a) bod=(rsh 3 1 a)]
?> =('A' mag)
(nol:nu:crua bod)
::
```
XX document
###++trua
```
++ trua :: test rsa
|= msg=@tas
^- @
=+ ali=(bruw 1.024 (shax 'ali'))
=+ bob=(bruw 1.024 (shax 'bob'))
=+ tef=(sign:as.ali [0 msg])
=+ lov=(sure:as.ali [0 tef])
?. &(?=(^ lov) =(msg u.lov))
~|(%test-fail-sign !!)
=+ key=(shax (shax (shax msg)))
=+ sax=(seal:as.ali pub:ex.bob key msg)
=+ tin=(tear:as.bob pub:ex.ali sax)
?. &(?=(^ tin) =(key p.u.tin) =(msg q.u.tin))
~|(%test-fail-seal !!)
msg
::
```
XX document
###++crub
```
++ crub :: cryptosuite B (Ed)
^- acru
=| [puc=pass sed=ring]
=> |%
```
XX document
###++dap
```
++ dap :: OEAP decode
|= [wid=@ xar=@ dog=@] ^- [p=@ q=@]
=+ pav=(sub wid xar)
=+ qoy=(cut 0 [xar pav] dog)
=+ dez=(mix (end 0 xar dog) (shaw %pad-b xar qoy))
[dez (mix qoy (shaw %pad-a pav dez))]
::
```
XX document
###++pad
```
++ pad :: OEAP encode
|= [wid=@ rax=[p=@ q=@] meg=@] ^- @
=+ pav=(sub wid p.rax)
?> (gte pav (met 0 meg))
^- @
=+ qoy=(mix meg (shaw %pad-a pav q.rax))
=+ dez=(mix q.rax (shaw %pad-b p.rax qoy))
(can 0 [p.rax dez] [pav qoy] ~)
|%
```
XX document
###++as
```
++ as
=> |%
```
XX document
###++haul
```
++ haul :: revealing haul
|= a=pass
!!
^?
|% ++ seal
|= [a=pass b=@ c=@]
^- @
!!
```
XX document
###++seal
XX document
### `++sign`
++ sign
|= [a=@ b=@] ^- @
!!
XX document
### `++sure`
++ sure
|= [a=@ b=@]
^- (unit ,@)
!!
XX document
### `++tear`
++ tear
|= [a=pass b=@]
^- (unit ,[p=@ q=@])
!!
::
XX document
### `++de`
++ de
|+ [key=@ cep=@] ^- (unit ,@)
!!
::
XX document
### `++dy`
++ dy
|+ [a=@ b=@] ^- @
!!
XX document
### `++en`
++ en
|+ [key=@ msg=@] ^- @ux
!!
::
XX document
### `++ex`
++ ex ^?
|% ++ fig ^- @uvH (shaf %bfig puc)
XX document
### `++fig`
XX document
###++pac
```
++ pac ^- @uvG (end 6 1 (shaf %acod sec))
```
XX document
###++pub
```
++ pub ^- pass (cat 3 'b' puc)
```
XX document
###++sec
```
++ sec ^- ring sed
::
```
XX document
###++nu
```
++ nu
^?
|% ++ com
|= a=@
^+ ^?(..nu)
..nu(sed ~, puc a)
::
```
XX document
###++com
XX document
### `++pit`
++ pit
|= [a=@ b=@]
^+ ^?(..nu)
..nu(sed b, puc (puck:ed b))
::
XX document
### `++nol`
++ nol
|= a=@
^+ ^?(..nu)
..nu(sed a, puc (puck:ed a))
XX document
### `++brew`
++ brew :: create keypair
|= [a=@ b=@] :: width seed
^- acru
(pit:nu:crub a b)
::
XX document
### `++hail`
++ hail :: activate public key
|= a=pass
^- acru
=+ [mag=(end 3 1 a) bod=(rsh 3 1 a)]
?> =('b' mag)
(com:nu:crub bod)
::
XX document
### `++wear`
++ wear :: activate secret key
|= a=ring
^- acru
=+ [mag=(end 3 1 a) bod=(rsh 3 1 a)]
?> =('b' mag)
(nol:nu:crub bod)
::
XX document
### `++trub`
++ trub :: test ed
|= msg=@tas
^- @
=+ ali=(brew 1.024 (shax 'ali'))
=+ bob=(brew 1.024 (shax 'bob'))
=+ tef=(sign:as.ali [0 msg])
=+ lov=(sure:as.ali [0 tef])
?. &(?=(^ lov) =(msg u.lov))
~|(%test-fail-sign !!)
=+ key=(shax (shax (shax msg)))
=+ sax=(seal:as.ali pub:ex.bob key msg)
=+ tin=(tear:as.bob pub:ex.ali sax)
?. &(?=(^ tin) =(key p.u.tin) =(msg q.u.tin))
~|(%test-fail-seal !!)
msg
::
XX document
### `++hmac`
++ hmac :: HMAC-SHA1
|= [key=@ mes=@]
=+ ip=(fil 3 64 0x36)
=+ op=(fil 3 64 0x5c)
=+ ^= kex
?: (gth (met 3 key) 64)
(lsh 3 44 (shan (swap 3 key)))
(lsh 3 (sub 64 (met 3 key)) (swap 3 key))
=+ inn=(shan (swap 3 (cat 3 (swap 3 mes) (mix ip kex))))
(shan (swap 3 (cat 3 inn (mix op kex))))
::
XX document

View File

@ -1,382 +0,0 @@
section 3bC, Gregorian UTC
==========================
### `++dawn`
Weekday of Jan 1
++ dawn :: weekday of jan 1
|= yer=@ud
=+ yet=(sub yer 1)
%- mod :_ 7
:(add 1 (mul 5 (mod yet 4)) (mul 4 (mod yet 100)) (mul 6 (mod yet 400)))
::
Computes which day of the week January 1st falls on for a year `yer`,
producing an atom. Weeks are zero-indexed beginning on Sunday.
`yer` is an unsigned decimal, [`@ud`]().
~zod/try=> (dawn 2.015)
4
~zod/try=> (dawn 1)
1
~zod/try=> (dawn 0)
! subtract-underflow
! exit
------------------------------------------------------------------------
### `++daws`
Weekday of date
++ daws :: weekday of date
|= yed=date
%- mod :_ 7
(add (dawn y.yed) (sub (yawn [y.yed m.yed d.t.yed]) (yawn y.yed 1 1)))
::
Produces the day of the week of a given date `yed` as an atom. Weeks are
zero-indexed beginning on Sunday.
`yed` is a [`date`]().
~zod/try=> (daws [[a=%.y y=2.014] m=6 t=[d=6 h=21 m=9 s=15 f=~[0xa16]]])
5
~zod/try=> (daws (yore -<-))
2
(second example always returns the current date).
------------------------------------------------------------------------
### `++deal`
Add leap seconds
++ deal :: to leap sec time
|= yer=@da
=+ n=0
=+ yud=(yore yer)
|- ^- date
?: (gte yer (add (snag n lef:yu) ~s1))
(yore (year yud(s.t (add n s.t.yud))))
?: &((gte yer (snag n lef:yu)) (lth yer (add (snag n lef:yu) ~s1)))
yud(s.t (add +(n) s.t.yud))
?: =(+(n) (lent lef:yu))
(yore (year yud(s.t (add +(n) s.t.yud))))
$(n +(n))
::
Produces a [`date`]() with the 25 leap seconds added.
`yer` is an absolute date, [`@da`]().
~zod/try=> (yore (bex 127))
[[a=%.y y=226] m=12 t=[d=5 h=15 m=30 s=8 f=~]]
~zod/try=> (deal `@da`(bex 127))
[[a=%.y y=226] m=12 t=[d=5 h=15 m=30 s=33 f=~]]
~zod/try=> (yore (bex 126))
[[a=%.n y=146.138.512.088] m=6 t=[d=19 h=7 m=45 s=4 f=~]]
------------------------------------------------------------------------
### `++lead`
Subtract leap seconds
++ lead :: from leap sec time
|= ley=date
=+ ler=(year ley)
=+ n=0
|- ^- @da
=+ led=(sub ler (mul n ~s1))
?: (gte ler (add (snag n les:yu) ~s1))
led
?: &((gte ler (snag n les:yu)) (lth ler (add (snag n les:yu) ~s1)))
?: =(s.t.ley 60)
(sub led ~s1)
led
?: =(+(n) (lent les:yu))
(sub led ~s1)
$(n +(n))
::
Produces an absolute date ([`@ud`]()) with the 25 leap seconds
subtracted.
`ley` is a [`date`]().
~zod/try=> (yore `@da`(bex 127))
[[a=%.y y=226] m=12 t=[d=5 h=15 m=30 s=8 f=~]]
~zod/try=> (lead (yore `@da`(bex 127)))
~226.12.5..15.29.43
~zod/try=> (lead (yore `@da`(bex 126)))
~146138512088-.6.19..07.44.39
------------------------------------------------------------------------
### `++dust`
Print UTC format
++ dust :: print UTC format
|= yed=date
^- tape
=+ wey=(daws yed)
;: weld
`tape`(snag wey (turn wik:yu |=(a=tape (scag 3 a))))
", " ~(rud at d.t.yed) " "
`tape`(snag (dec m.yed) (turn mon:yu |=(a=tape (scag 3 a))))
" " (scag 1 ~(rud at y.yed)) (slag 2 ~(rud at y.yed)) " "
~(rud at h.t.yed) ":" ~(rud at m.t.yed) ":" ~(rud at s.t.yed)
" " "+0000"
==
::
Produces a [tape]() of the date in UTC format.
`yed` is a [`date`]().
~zod/try=> (dust (yore ->-))
"Tue, 21 Oct 2014 21:35:12 +0000"
~zod/try=> (dust [[a=%.y y=2.002] m=10 t=[d=11 h=12 m=20 s=55 f=~]])
"Fri, 11 Oct 2002 12:20:55 +0000"
------------------------------------------------------------------------
### `++stud`
Parse UTC format
++ stud :: parse UTC format
|= cud=tape
^- (unit date)
=- ?~ tud ~
`[[%.y &3.u.tud] &2.u.tud &1.u.tud &4.u.tud &5.u.tud &6.u.tud ~]
^= tud
%+ rust cud
;~ plug
;~(pfix (stun [5 5] next) dim:ag)
::
%+ cook
|= a=tape
=+ b=0
|- ^- @
?: =(a (snag b (turn mon:yu |=(a=tape (scag 3 a)))))
+(b)
$(b +(b))
(ifix [ace ace] (star alf))
::
;~(sfix dim:ag ace)
;~(sfix dim:ag col)
;~(sfix dim:ag col)
dim:ag
(cold ~ (star next))
==
::
Accepts a [tape]() containing a date in UTC format and produces the
[unit]() of a [`date`]().
~zod/try=> (stud "Tue, 21 Oct 2014 21:21:55 +0000")
[~ [[a=%.y y=2.014] m=10 t=[d=21 h=21 m=21 s=55 f=~]]]
~zod/try=> (stud "Wed, 11 Oct 2002 12:20:55 +0000")
[~ [[a=%.y y=2.002] m=10 t=[d=11 h=12 m=20 s=55 f=~]]]
~zod/try=> (stud "Wed, 11 Oct 2002")
~
------------------------------------------------------------------------
### `++unt`
UGT to UTC time
++ unt :: UGT to UTC time
|= a=@da
(div (sub a ~1970.1.1) (bex 64))
::
~zod/try=/hom> (unt -<-)
1.413.927.704
~zod/try=> (unt ~20014.1.1)
569.413.670.400
~zod/try=> (unt ~2014.1.1)
1.388.534.400
Transforms Urbit Galactic Time to UTC time, producing an atom.
`a` is an [atom]().
------------------------------------------------------------------------
### `++yu`
UTC format constants
++ yu :: UTC format constants
|%
~zod/try=/hom> yu
<4.pgn 250.tmw 41.cmo 414.rvm 101.jzo 1.ypj %164>
------------------------------------------------------------------------
### `++mon`
Months
++ mon ^- (list tape)
:~ "January" "February" "March" "April" "May" "June" "July"
"August" "September" "October" "November" "December"
==
::
Produces a list of [tapes]() containing the 12 months of the year.
~zod/try=/hom> mon:yu
<<
"January"
"February"
"March"
"April"
"May"
"June"
"July"
"August"
"September"
"October"
"November"
"December"
>>
~zod/try=/hom> (snag 1 mon:yu)
"February"
------------------------------------------------------------------------
### `++wik`
Weeks
++ wik ^- (list tape)
:~ "Sunday" "Monday" "Tuesday" "Wednesday" "Thursday"
"Friday" "Saturday"
==
::
Produces a list of [tapes]() containing the 7 days of the week,
beginning with Sunday.
~zod/try=/hom> wik:yu
<<"Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday">>
~zod/try=/hom> (snag 2 wik:yu)
"Tuesday"
~zod/try=/hom> (snag (daws (yore -<-)) wik:yu)
"Tuesday"
------------------------------------------------------------------------
### `++les`
Leap second dates
++ les ^- (list ,@da)
:~ ~2015.7.1 ~2012.7.1 ~2009.1.1 ~2006.1.1 ~1999.1.1 ~1997.7.1
~1996.1.1 ~1994.7.1 ~1993.7.1 ~1992.7.1 ~1991.1.1 ~1990.1.1
~1988.1.1 ~1985.7.1 ~1983.7.1 ~1982.7.1 ~1981.7.1 ~1980.1.1
~1979.1.1 ~1978.1.1 ~1977.1.1 ~1976.1.1 ~1975.1.1 ~1974.1.1
~1973.1.1 ~1972.7.1
==
Produces a list of the (absolute) dates ([`@da`]) of the 25 leap seconds
~zod/try=/hom> les:yu
~[
~2015.7.1
~2012.7.1
~2009.1.1
~2006.1.1
~1999.1.1
~1997.7.1
~1996.1.1
~1994.7.1
~1993.7.1
~1992.7.1
~1991.1.1
~1990.1.1
~1988.1.1
~1985.7.1
~1983.7.1
~1982.7.1
~1981.7.1
~1980.1.1
~1979.1.1
~1978.1.1
~1977.1.1
~1976.1.1
~1975.1.1
~1974.1.1
~1973.1.1
~1972.7.1
]
~zod/try=/hom> (snag 2 les:yu)
~2006.1.1
------------------------------------------------------------------------
### `++lef`
Back-shifted leap second dates
++ lef ^- (list ,@da)
:~ ~2015.6.30..23.59.59 ~2012.6.30..23.59.59
~2008.12.31..23.59.58 ~2005.12.31..23.59.57
~1998.12.31..23.59.56 ~1997.6.30..23.59.55
~1995.12.31..23.59.54 ~1994.6.30..23.59.53
~1993.6.30..23.59.52 ~1992.6.30..23.59.51
~1990.12.31..23.59.50 ~1989.12.31..23.59.49
~1987.12.31..23.59.48 ~1985.6.30..23.59.47
~1983.6.30..23.59.46 ~1982.6.30..23.59.45
~1981.6.30..23.59.44 ~1979.12.31..23.59.43
~1978.12.31..23.59.42 ~1977.12.31..23.59.41
~1976.12.31..23.59.40 ~1975.12.31..23.59.39
~1974.12.31..23.59.38 ~1973.12.31..23.59.37
~1972.12.31..23.59.36 ~1972.6.30..23.59.35
==
::
Produces a list of absolute dates ([`@da`]()) that represent the Urbit
Galactc Time equivalents of the UTC leap second dates in [`++les`](/doc/hoon/library/3bc#++les).
~zod/try=/hom> lef:yu
~[
~2015.6.30..23.59.59
~2012.6.30..23.59.59
~2008.12.31..23.59.58
~2005.12.31..23.59.57
~1998.12.31..23.59.56
~1997.6.30..23.59.55
~1995.12.31..23.59.54
~1994.6.30..23.59.53
~1993.6.30..23.59.52
~1992.6.30..23.59.51
~1990.12.31..23.59.50
~1989.12.31..23.59.49
~1987.12.31..23.59.48
~1985.6.30..23.59.47
~1983.6.30..23.59.46
~1982.6.30..23.59.45
~1981.6.30..23.59.44
~1979.12.31..23.59.43
~1978.12.31..23.59.42
~1977.12.31..23.59.41
~1976.12.31..23.59.40
~1975.12.31..23.59.39
~1974.12.31..23.59.38
~1973.12.31..23.59.37
~1972.12.31..23.59.36
~1972.6.30..23.59.35
]
~zod/try=/hom> (snag 2 lef:yu)
~2005.12.31..23.59.57

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,267 +0,0 @@
section 3bF, filesystem interface
=================================
### `++feel`
Generate file diff
++ feel :: simple file write
|= [pax=path val=*]
^- miso
=+ dir=((hard arch) .^(%cy pax))
?~ q.dir [%ins val]
:- %mut
^- udon
[%a %a .^(%cx pax) val]
::
Generates a diff between a file located at `pax` and an input value
`val`.
`pax` is a [`++path`]().
`val` is a value as a [noun]().
~zod/try=> + %/mel 'test'
+ /~zod/try/2/mel
~zod/try=> (feel %/mel 'tesh?')
[%mut p=[p=%a q=[%a p=44.903.392.628 q=272.335.332.724]]]
~zod/try=> `@t`44.903.392.628
'''
test
'''
~zod/try=> `@t`272.335.332.724
'tesh?'
### `++file`
Simple file load
++ file :: simple file load
|= pax=path
^- (unit)
=+ dir=((hard arch) .^(%cy pax))
?~(q.dir ~ [~ .^(%cx pax)])
::
Reads the value of a file located at `pax` and renders it as a
[`++unit`]().
`pax` is a [`++path`]().
~zod/try=> %/zak
~zod/try=/zak> :ls %
~zod/try=/zak> + %/mop 20
+ /~zod/try/3/zak/mop
~zod/try=/zak> :ls %
mop
~zod/try=/zak> (file %/mop)
[~ 20]
~zod/try=/zak> (file %/lak)
~
~zod/try=/zak> (file /==2%/mop)
~
### `++foal`
Write high-level change
++ foal :: high-level write
|= [pax=path val=*]
^- toro
?> ?=([* * * *] pax)
[i.t.pax [%& [*cart [[t.t.t.pax (feel pax val)] ~]]]]
::
Produces a [`++toro`](), a change intended for whatever file is located
at `pax`. Handled by `%clay`.
`pax` is a [`++path`]().
`val` is a value as a [noun]().
~zod/try=> + %/mek 'a'
+ /~zod/try/4/mek
~zod/try=> (foal %/mek 'b')
[ p=~.try
q
[%.y q=[p=[p=0v0 q=0v0] q=~[[p=/mek q=[%mut p=[p=%a q=[%a p=97 q=98]]]]]]]
]
~zod/try=> (feel %/mek 'b')
[%mut p=[p=%a q=[%a p=97 q=98]]]
### `++fray`
High-level delete
++ fray :: high-level delete
|= pax=path
^- toro
?> ?=([* * * *] pax)
[i.t.pax [%& [*cart [[t.t.t.pax [%del .^(%cx pax)]] ~]]]]
::
Produces a deletion [`++toro`]() for a file located at path `pax`.
Handled by `%clay`.
`pax` is a [`++path`]().
~zod/try=> + %/mek 'a'
+ /~zod/try/4/mek
~zod/try=> (fray %/mek)
[p=~.try q=[%.y q=[p=[p=0v0 q=0v0] q=~[[p=/mek q=[%del p=97]]]]]]
~zod/try=> `@t`97
'a'
### `++furl`
Unify changes
++ furl :: unify changes
|= [one=toro two=toro]
^- toro
~| %furl
?> ?& =(p.one p.two) :: same path
&(?=(& -.q.one) ?=(& -.q.two)) :: both deltas
==
[p.one [%& [*cart (weld q.q.q.one q.q.q.two)]]]
::
Merge two [`++toro`]()s `one` and `two` that are in the same [`desk`]()
and pointed at the same [`++path`]().
`one` is a [`++toro`]().
`two` is a [`++toro`]().
~zod/try=> %/zak
~zod/try=/zak> :ls %
mop
~zod/try=/zak> (furl (fray %/mop) (foal %/mok 'hi'))
[ p=~.try
q
[ %.y
q
[ p=[p=0v0 q=0v0]
q=~[[p=/zak/mop q=[%del p=20]] [p=/zak/mok q=[%ins p=26.984]]]
]
]
]
### `++meat`
Kite to .\^ path
++ meat :: kite to .^ path
|= kit=kite
^- path
[(cat 3 'c' p.kit) (scot %p r.kit) s.kit (scot `dime`q.kit) t.kit]
::
Converts a type request name to a [`++path`]().
`kit` is a [`++kite`]().
zod/try=/zop> `kite`[%x ud/1 ~zod %main /sur/down/gate/hook]
[p=%x q=[%ud p=1] r=~zod s=%main t=/sur/down/gate/hook]
~zod/try=/zop> (meat [%x ud/1 ~zod %main /sur/down/gate/hook])
/cx/~zod/main/1/sur/down/gate/hook
~zod/try=/zop> .^((meat [%x ud/1 ~zod %main /sur/down/gate/hook]))
8.024.240.839.827.090.233.853.057.929.619.452.695.436.878.709.611.140.677.
745.908.646.440.925.885.935.296.374.867.974.972.908.054.571.544.099.882.490.
677.391.983.737.511.220.072.391.888.081.664.570
~zod/try=/zop> (,@t .^((meat [%x ud/1 ~zod %main /sur/down/gate/hook])))
'''
::
:::: /hoon/gate/down/sur
::
/? 314
/- *markdown
down
'''
### `++tame`
Parse kite path
++ tame :: parse kite path
|= hap=path
^- (unit kite)
?. ?=([@ @ @ @ *] hap) ~
=+ :* hyr=(slay i.hap)
fal=(slay i.t.hap)
dyc=(slay i.t.t.hap)
ved=(slay i.t.t.t.hap)
:: ved=(slay i.t.hap)
:: fal=(slay i.t.t.hap)
:: dyc=(slay i.t.t.t.hap)
tyl=t.t.t.t.hap
==
?. ?=([~ %$ %tas @] hyr) ~
?. ?=([~ %$ %p @] fal) ~
?. ?=([~ %$ %tas @] dyc) ~
?. ?=([~ %$ case] ved) ~
=+ his=`@p`q.p.u.fal
=+ [dis=(end 3 1 q.p.u.hyr) rem=(rsh 3 1 q.p.u.hyr)]
?. ?&(?=(%c dis) ?=(?(%v %w %x %y %z) rem)) ~
[~ rem p.u.ved q.p.u.fal q.p.u.dyc tyl]
::
Parses a clay [.\^]()
[`++path` ]()to request details. Produces the [`++unit`]() of a [`++kite`]().
`hap` is a [`++path`]().
~zod/try=/zop> (tame /cx/~zod/main/1/sur/down/gate/hook)
[~ [p=%x q=[%ud p=1] r=~zod s=%main t=/sur/down/gate/hook]]
~zod/try=/zop> (tame /cx/0/main/1/sur/down/gate/hook)
~
~zod/try=/zop> (tame /~zod/main/0x12/sur/down/gate/hook)
~
### `++tome`
Parse path to beam
++ tome :: parse path to beam
|= pax=path
^- (unit beam)
?. ?=([* * * *] pax) ~
%+ biff (slaw %p i.pax)
|= who=ship
%+ biff (slaw %tas i.t.pax)
|= dex=desk
%+ biff (slay i.t.t.pax)
|= cis=coin
?. ?=([%$ case] cis) ~
`(unit beam)`[~ [who dex `case`p.cis] (flop t.t.t.pax)]
::
Parses a [`++path`]() `pax` to a [\`++beam](), a well-typed location.
~zod/try=/zop> (tome /~fyr/try/2/for/me)
[~ [[p=~fyr q=%try r=[%ud p=2]] s=/me/for]]
~zod/try=/zop> (tome /~zod/main/1)
[~ [[p=~zod q=%main r=[%ud p=1]] s=/]]
~zod/try=/zop> (tome /0/main/1)
~
~zod/try=/zop> (tome /~zod/main/0x12)
~
### `++tope :: beam to path`
Parse beam to path
|= bem=beam
^- path
[(scot %p p.bem) q.bem (scot r.bem) (flop s.bem)]
Parses a [`++beam`]() to a [`++path`](/doc/hoon/library/1#++path).
~zod/try=/zop> (tope [~zod %main ud/1] /hook/down/sur)
/~zod/main/1/sur/down/hook
~zod/try=/zop> (tope [~fyr %try da/~2015.1.1] /txt/test)
/~fyr/try/~2015.1.1/test/txt
~zod/try=/zop> (tope [~doznec %try da/-<-] /txt/test)
/~doznec/try/~2014.10.30..00.32.48..3ae4/test/txt

View File

@ -1,943 +0,0 @@
section 3bG, URL handling
=========================
### `++deft`
Import URL path
++ deft :: import url path
|= rax=(list ,@t)
|- ^- pork
?~ rax
[~ ~]
?~ t.rax
=+ den=(trip i.rax)
=+ ^= vex
%- %- full
;~(plug sym ;~(pose (stag ~ ;~(pfix dot sym)) (easy ~)))
[[1 1] (trip i.rax)]
?~ q.vex
[~ [i.rax ~]]
[+.p.u.q.vex [-.p.u.q.vex ~]]
=+ pok=$(rax t.rax)
:- p.pok
[i.rax q.pok]
::
Parse the extension the from last element of url, which is delimited
either by a `.` or a `/`.
`rax` is a [`++list`]() of [`@t`]().
~zod/try=> (deft /foo/bar/'baz.txt')
[p=[~ ~.txt] q=<|foo bar baz|>]
~zod/try=> (deft /foo/bar/baz)
[p=~ q=<|foo bar baz|>]
### `++fain`
Restructure path
++ fain :: path restructure
|= [hom=path raw=path]
=+ bem=(need (tome raw))
=+ [mer=(flop s.bem) moh=(flop hom)]
|- ^- (pair beam path)
?~ moh
[bem(s hom) (flop mer)]
?> &(?=(^ mer) =(i.mer i.moh))
$(mer t.mer, moh t.moh)
::
Splits a concrete
[`++spur`]() out of a full `++path`, producing a location [`++beam`]() and a remainder [`++path`]().
`hom` is a [`++path`]()
~zod/try=> (fain / %)
[p=[[p=~zod q=%try r=[%da p=~2014.11.1..00.07.17..c835]] s=/] q=/]
~zod/try=> (fain /lok %)
! exit
~zod/try=> (fain / %/mer/lok/tem)
[ p=[[p=~zod q=%try r=[%da p=~2014.11.1..00.08.03..bfdf]] s=/]
q=/tem/lok/mer
]
~zod/try=> (fain /mer %/mer/lok/tem)
[p=[[p=~zod q=%try r=[%da p=~2014.11.1..00.08.15..4da0]] s=/mer] q=/tem/lok]
~zod/try=> (fain /lok/mer %/mer/lok/tem)
[p=[[p=~zod q=%try r=[%da p=~2014.11.1..00.08.24..4d9e]] s=/lok/mer] q=/tem]
~zod/try=> (fain /lok/mer %/mer)
! exit
~zod/try=> (fain /hook/hymn/tor %/tor/hymn/hook/'._req_1234__')
[ p=[[p=~zod q=%try r=[%da p=~2014.11.1..00.09.25..c321]] s=/hook/hymn/tor]
q=/._req_1234__
]
### `++fuel`
Parse fcgi
++ fuel :: parse fcgi
|= [bem=beam but=path]
^- epic
?> ?=([%web @ *] but)
=+ dyb=(slay i.t.but)
?> ?& ?=([~ %many *] dyb)
?=([* * *] p.u.dyb)
:: ?=([%$ %tas *] i.p.u.dyb)
?=([%many *] i.p.u.dyb)
?=([%blob *] i.t.p.u.dyb)
==
=+ ced=((hard cred) p.i.t.p.u.dyb)
:: =+ nep=q.p.i.p.u.dyb
=+ ^= nyp ^- path
%+ turn p.i.p.u.dyb
|= a=coin ^- @ta
?> ?=([%$ %ta @] a)
?>(((sane %ta) q.p.a) q.p.a)
=+ ^= gut ^- (list ,@t)
%+ turn t.t.p.u.dyb
|= a=coin ^- @t
?> ?=([%$ %t @] a)
?>(((sane %t) q.p.a) q.p.a)
=+ ^= quy
|- ^- (list ,[p=@t q=@t])
?~ gut ~
?> ?=(^ t.gut)
[[i.gut i.t.gut] $(gut t.t.gut)]
:* (~(gas by *(map cord cord)) quy)
ced
bem
t.t.but
nyp
==
::
Retrieieves the %eyre FCGI, producing a [`++epic`](). Used primarily in
[`/hook`]() files. See the [`%eyre`]() doc for more detail.
`bem` is a [`++beam`]().
`but` is a [`++path`]().
~zod/main=> (fuel [[p=~zod q=%try r=[%ud p=2]] s=/psal] /web/'._.~-~~~~.gen~-~-_~~05vg0001v09f0n30fbh7dn6ab2jakmmspdq04nef5h70qbd5lh6atr4c5j2qrbldpp62q1df1in0sr1ding0c3qgt7kclj74qb65lm6atrkc5k2qpr5e1mmispdchin4p3fegmiqrjpdlo62p1dchsn4p39comn8pbcehgmsbbef5p7crrifr3o035dhgfrk2b5__')
[ qix={}
ced
[ hut=[p=%.y q=[~ 8.445] r=[%.n p=.0.0.0.0]]
aut={[p=%$ q={'~rovryn-natlet-fidryd-dapmyn--todred-simpeg-hatwel-firfet'}]}
orx='laspex-harnum-fadweb-mipbyn'
acl=[~ 'en-US,en;q=0.8']
cip=[%.y p=.127.0.0.1]
cum={}
]
bem=[[p=~zod q=%try r=[%ud p=2]] s=/psal]
but=/
nyp=/gen
]
### `++sifo`
64-bit encode
++ sifo :: 64-bit encode
|= tig=@
^- tape
=+ poc=(~(dif fo 3) 0 (met 3 tig))
=+ pad=(lsh 3 poc (swap 3 tig))
=+ ^= cha
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
=+ ^= sif
|- ^- tape
?~ pad
~
=+ d=(end 0 6 pad)
[(cut 3 [d 1] cha) $(pad (rsh 0 6 pad))]
(weld (flop (slag poc sif)) (trip (fil 3 poc '=')))
::
Encodes an atom to MIME base64, producing a [`++tape`]().
~zod/main=> (sifo 'foobar')
"Zm9vYmFy"
~zod/main=> (sifo 1)
"Q=="
~zod/main=> (sifo (shax %hi))
"j0NDRmSPa5bfid2pAcUXaxCm2Dlh3TwayItZstwyeqQ="
### `++urle`
Encode URL
++ urle :: URL encode
|= tep=tape
^- tape
%- zing
%+ turn tep
|= tap=char
=+ xen=|=(tig=@ ?:((gte tig 10) (add tig 55) (add tig '0')))
?: ?| &((gte tap 'a') (lte tap 'z'))
&((gte tap 'A') (lte tap 'Z'))
&((gte tap '0') (lte tap '9'))
=('.' tap)
=('-' tap)
=('~' tap)
=('_' tap)
==
[tap ~]
['%' (xen (rsh 0 4 tap)) (xen (end 0 4 tap)) ~]
::
The inverse of [`++urld`](). Accepts a tape `tep` and replaces all
characters other than alphanumerics and `.`, `-`, `~`, and `_`, with URL
escape sequences.
~zod/main=> (urle "hello")
"hello"
~zod/main=> (urle "hello dear")
"hello%20dear"
~zod/main=> (urle "hello-my?=me !")
"hello-my%3F%3Dme%20%20%21"
### `++urld`
Decode URL
++ urld :: URL decode
|= tep=tape
^- (unit tape)
?~ tep [~ ~]
?: =('%' i.tep)
?. ?=([@ @ *] t.tep) ~
=+ nag=(mix i.t.tep (lsh 3 1 i.t.t.tep))
=+ val=(rush nag hex:ag)
?~ val ~
=+ nex=$(tep t.t.t.tep)
?~(nex ~ [~ [`@`u.val u.nex]])
=+ nex=$(tep t.tep)
?~(nex ~ [~ i.tep u.nex])
::
The inverse of [`++urle`](). Parses a URL escaped tape to the
[`++unit`]() of an unescaped `++tape`.
`tep` is a [`++tape`]().
~zod/main=> (urld "hello")
[~ "hello"]
~zod/main=> (urld "hello%20dear")
[~ "hello dear"]
~zod/main=> (urld "hello-my%3F%3Dme%20%20%21")
[~ "hello-my?=me !"]
~zod/main=> (urld "hello-my%3F%3Dme%20%2%21")
~
### `++earl`
Localize purl
++ earl :: localize purl
|= [who=@p pul=purl]
^- purl
pul(q.q [(rsh 3 1 (scot %p who)) q.q.pul])
::
Prepends a ship name to the spur of a [`++purl`]().
`who` is a [`@p`](), a ship name.
`pul` is a [`++purl`]().
~zod/main=> (need (epur 'http://123.1.1.1/me.ham'))
[p=[p=%.n q=~ r=[%.n p=.123.1.1.1]] q=[p=[~ ~.ham] q=<|me|>] r=~]
~zod/main=> (earl ~zod (need (epur 'http://123.1.1.1/me.ham')))
[p=[p=%.n q=~ r=[%.n p=.123.1.1.1]] q=[p=[~ ~.ham] q=<|zod me|>] r=~]
~zod/main=> (earl ~pittyp (need (epur 'http://123.1.1.1/me.ham')))
[p=[p=%.n q=~ r=[%.n p=.123.1.1.1]] q=[p=[~ ~.ham] q=<|pittyp me|>] r=~]
~zod/main=> (earn (earl ~pittyp (need (epur 'http://123.1.1.1/me.ham'))))
"http://123.1.1.1/pittyp/me"
### `++earn`
Purl to tape
++ earn :: purl to tape
|^ |= pul=purl
^- tape
:(weld (head p.pul) "/" (body q.pul) (tail r.pul))
::
Parses a `++purl` `pul` to a [`++tape`]().
`pul` is a [`++purl`]().
~zod/main=> (earn [| ~ [%| .127.0.0.1]] [~ ~] ~)
"http://127.0.0.1/"
~zod/main=> (earn [| ~ `/com/google/www] [~ ~] ~)
"http://www.google.com/"
~zod/main=> (earn [& ~ `/com/google/www] [~ ~] ~)
"https://www.google.com/"
~zod/main=> (earn [& `200 `/com/google/www] [~ ~] ~)
"https://www.google.com:200/"
~zod/main=> (earn [& `200 `/com/google/www] [~ /search] ~)
"https://www.google.com:200/search"
~zod/main=> (earn [& ~ `/com/google/www] [`%html /search] ~)
"https://www.google.com/search"
~zod/main=> (earn [& ~ `/com/google/www] [~ /search] [%q 'urbit'] ~)
"https://www.google.com/search?q=urbit"
~zod/main=> (earn [& ~ `/com/google/www] [~ /search] [%q 'urbit escaping?'] ~)
"https://www.google.com/search?q=urbit%20escaping%3F"
### `++body`
Render URL path
++ body
|= pok=pork ^- tape
?~ q.pok ~
|-
=+ seg=(trip i.q.pok)
?~ t.q.pok
?~(p.pok seg (welp seg '.' (trip u.p.pok)))
(welp seg '/' $(q.pok t.q.pok))
::
Renders URL path `pok` as a [`++tape`]().
~zod/main=> (body:earn ~ /foo/mol/lok)
"foo/mol/lok"
~zod/main=> (body:earn `%htm /foo/mol/lok)
"foo/mol/lok.htm"
~zod/main=> (body:earn `%htm /)
""
### `++head`
Render URL beginning
++ head
|= har=hart
^- tape
;: weld
?:(&(p.har !=([& /localhost] r.har)) "https://" "http://")
::
?- -.r.har
| (trip (rsh 3 1 (scot %if p.r.har)))
& =+ rit=(flop p.r.har)
|- ^- tape
?~(rit ~ (weld (trip i.rit) ?~(t.rit "" `tape`['.' $(rit t.rit)])))
==
::
?~(q.har ~ `tape`[':' (trip (rsh 3 2 (scot %ui u.q.har)))])
==
::
Renders a `++hart`, usually the beginning of a URL, as the [`++tape`]()
of a traditional URL.
~zod/main=> (head:earn | ~ %| .127.0.0.1)
"http://127.0.0.1"
~zod/main=> (head:earn & ~ %| .127.0.0.1)
"https://127.0.0.1"
~zod/main=> (head:earn & [~ 8.080] %| .127.0.0.1)
"https://127.0.0.1:8080"
~zod/main=> (head:earn & [~ 8.080] %& /com/google/www)
"https://www.google.com:8080"
### `++tail`
Render query string
++ tail
|= kay=quay
^- tape
?: =(~ kay) ~
:- '?'
|- ^- tape
?~ kay ~
;: weld
(urle (trip p.i.kay))
"="
(urle (trip q.i.kay))
?~(t.kay ~ `tape`['&' $(kay t.kay)])
==
--
::
Renders a `quay`, a query string in hoon, to the [`++tape`]() of a
traditional query string.
`kay` is a [`++quay`]().
~zod/main=> (tail:earn ~)
""
~zod/main=> (tail:earn [%ask 'bid'] ~)
"?ask=bid"
~zod/main=> (tail:earn [%ask 'bid'] [%make 'well'] ~)
"?ask=bid&make=well"
### `++epur`
Top-level URL parser
++ epur :: url/header parser
=< |=(a=cord (rush a auri))
|%
Toplevel URL parser.
`a` is a [`++cord`](/doc/hoon/library/1#++cord).
~zod/main=> (epur 'http://127.0.0.1/')
[~ [p=[p=%.n q=~ r=[%.n p=.127.0.0.1]] q=[p=~ q=<||>] r=~]]
~zod/main=> (epur 'http://www.google.com/')
[~ [p=[p=%.n q=~ r=[%.y p=<|com google www|>]] q=[p=~ q=<||>] r=~]]
~zod/main=> (epur 'https://www.google.com/')
[~ [p=[p=%.y q=~ r=[%.y p=<|com google www|>]] q=[p=~ q=<||>] r=~]]
~zod/main=> (epur 'https//www.google.com/')
~
~zod/main=> (epur 'https://www.google.com:200/')
[~ [p=[p=%.y q=[~ 200] r=[%.y p=<|com google www|>]] q=[p=~ q=<||>] r=~]]
~zod/main=> (epur 'https://www.google.com:200/search')
[ ~
[p=[p=%.y q=[~ 200] r=[%.y p=<|com google www|>]] q=[p=~ q=<|search|>] r=~]
]
~zod/main=> (epur 'https://www.google.com/search')
[~ [p=[p=%.y q=~ r=[%.y p=<|com google www|>]] q=[p=~ q=<|search|>] r=~]]
~zod/main=> (epur 'https://www.google.com/search?q=urbit')
[ ~
[ p=[p=%.y q=~ r=[%.y p=<|com google www|>]]
q=[p=~ q=<|search|>]
r=~[[p='q' q='urbit']]
]
]
~zod/main=> (epur 'https://www.google.com/search?q=urb it')
~
~zod/main=> (epur 'https://www.google.com/search?q=urb%20it')
[ ~
[ p=[p=%.y q=~ r=[%.y p=<|com google www|>]]
q=[p=~ q=<|search|>]
r=~[[p='q' q='urb it']]
]
]
~zod/main=> (epur 'https://www.google.com/search?q=urbit%20escaping%3F')
[ ~
[ p=[p=%.y q=~ r=[%.y p=<|com google www|>]]
q=[p=~ q=<|search|>]
r=~[[p='q' q='urbit escaping?']]
]
]
### `++apat`
++ apat :: 2396 abs_path
%+ cook deft
(ifix [fas ;~(pose fas (easy ~))] (more fas smeg))
URL path as ++pork
~zod/try=> (scan "/foo/mol/lok" apat:epur)
[p=~ q=<|foo mol lok|>]
~zod/try=> (scan "/foo/mol/lok.htm" apat:epur)
[p=[~ ~.htm] q=<|foo mol lok|>]
### `++auri`
++ auri
%+ cook
|= a=purl
?.(=([& /localhost] r.p.a) a a(p.p &))
;~ plug
;~ plug
%+ sear
|= a=@t
^- (unit ,?)
?+(a ~ %http [~ %|], %https [~ %&])
;~(sfix scem ;~(plug col fas fas))
thor
==
;~(plug ;~(pose apat (easy *pork)) yque)
==
URL parsing rule
~zod/main=> (auri:epur [1 1] "http://127.0.0.1/")
[ p=[p=1 q=18]
q
[ ~
u
[ p=[p=[p=%.n q=~ r=[%.n p=.127.0.0.1]] q=[p=~ q=<||>] r=~]
q=[p=[p=1 q=18] q=""]
]
]
]
~zod/main=> (auri:epur [1 1] "http://www.google.com/")
[ p=[p=1 q=23]
q
[ ~
u
[ p=[p=[p=%.n q=~ r=[%.y p=<|com google www|>]] q=[p=~ q=<||>] r=~]
q=[p=[p=1 q=23] q=""]
]
]
]
~zod/main=> (auri:epur [1 1] "https://www.google.com/")
[ p=[p=1 q=24]
q
[ ~
u
[ p=[p=[p=%.y q=~ r=[%.y p=<|com google www|>]] q=[p=~ q=<||>] r=~]
q=[p=[p=1 q=24] q=""]
]
]
]
~zod/main=> (auri:epur [1 1] "https//www.google.com/")
[ p=[p=1 q=6] q=~]
~zod/main=> (auri:epur [1 1] "https://www.google.com:200/")
[ p=[p=1 q=28]
q=[~ u=[p=[p=[p=%.y q=[~ 200] r=[%.y p=<|com google www|>]] q=[p=~ q=<||>] r=~] q=[p=[p=1 q=28] q=""]]]
]
~zod/main=> (auri:epur [1 1] "https://www.google.com:200/search")
[ p=[p=1 q=34]
q=[~ u=[p=[p=[p=%.y q=[~ 200] r=[%.y p=<|com google www|>]] q=[p=~ q=<|search|>] r=~] q=[p=[p=1 q=34] q=""]]]
]
~zod/main=> (auri:epur [1 1] "https://www.google.com/search")
[ p=[p=1 q=30]
q=[~ u=[p=[p=[p=%.y q=~ r=[%.y p=<|com google www|>]] q=[p=~ q=<|search|>] r=~] q=[p=[p=1 q=30] q=""]]]
]
~zod/main=> (auri:epur [1 1] "https://www.google.com/search?q=urbit")
[ p=[p=1 q=38]
q
[ ~
u
[ p=[p=[p=%.y q=~ r=[%.y p=<|com google www|>]] q=[p=~ q=<|search|>] r=~[[p='q' q='urbit']]]
q=[p=[p=1 q=38] q=""]
]
]
]
~zod/main=> (auri:epur [1 1] "https://www.google.com/search?q=urb it")
[ p=[p=1 q=36]
q
[ ~
u
[ p=[p=[p=%.y q=~ r=[%.y p=<|com google www|>]] q=[p=~ q=<|search|>] r=~[[p='q' q='urb']]]
q=[p=[p=1 q=36] q=" it"]
]
]
]
~zod/main=> (auri:epur [1 1] "https://www.google.com/search?q=urb%20it")
[ p=[p=1 q=41]
q
[ ~
u
[ p=[p=[p=%.y q=~ r=[%.y p=<|com google www|>]] q=[p=~ q=<|search|>] r=~[[p='q' q='urb it']]]
q=[p=[p=1 q=41] q=""]
]
]
]
~zod/main=> (auri:epur [1 1] "https://www.google.com/search?q=urbit%20escaping%3F")
[ p=[p=1 q=52]
q
[ ~
u
[ p=[p=[p=%.y q=~ r=[%.y p=<|com google www|>]] q=[p=~ q=<|search|>] r=~[[p='q' q='urbit escaping?']]]
q=[p=[p=1 q=52] q=""]
]
]
]
### `++cock`
++ cock :: cookie
(most ;~(plug sem ace) ;~(plug toke ;~(pfix tis tosk)))
HTTP cookies, results in associative list of cord to cord.
~zod/try=> (scan "sam=lop" cock:epur)
[['sam' 'lop'] ~]
~zod/try=> (scan "sam=lop; res=\"salo don -keg!mo\"" cock:epur)
[['sam' 'lop'] ~[['res' 'salo don -keg!mo']]]
~zod/try=> (scan "sam=lop; res=\"salo don -keg!mo\"; so" cock:epur)
! {1 34}
! exit
### `++dlab`
++ dlab :: 2396 domainlabel
%+ sear
|= a=@ta
?.(=('-' (rsh 3 (dec (met 3 a)) a)) [~ u=a] ~)
%+ cook cass
;~(plug aln (star alp))
::
Domain label: alphanumeric, with `-` allowed in middle.
~zod/try=> (scan "google" dlab:epur)
~.google
~zod/try=> (scan "lera2" dlab:epur)
~.lera2
~zod/try=> (scan "gor-tem" dlab:epur)
~.gor-tem
~zod/try=> (scan "gortem-" dlab:epur)
! {1 8}
! exit
### `++fque`
++ fque (cook crip (plus pquo)) :: normal query field
One or more query string characters
~zod/try=> (scan "%20" fque:epur)
' '
~zod/try=> (scan "sam" fque:epur)
'sam'
~zod/try=> (scan "les+tor" fque:epur)
'les tor'
~zod/try=> (scan "sore-%22mek%22" fque:epur)
'sore-"mek"'
~zod/try=> (scan "" fque:epur)
! {1 1}
! exit
### `++fquu`
++ fquu (cook crip (star pquo)) :: optional field
Zero or more query string characters
~zod/try=> (scan "%20" fquu:epur)
' '
~zod/try=> (scan "sam" fquu:epur)
'sam'
~zod/try=> (scan "les+tor" fquu:epur)
'les tor'
~zod/try=> (scan "sore-%22mek%22" fquu:epur)
'sore-"mek"'
~zod/try=> (scan "" fquu:epur)
''
### `++pcar`
++ pcar ;~(pose pure pesc psub col pat) :: 2396 path char
Single URL path character: literal, `%` escape, subpath delimiter, `:`
or `@`
~zod/try=> (scan "a" pcar:epur)
~~a
~zod/try=> (scan "ab" pcar:epur)
! {1 2}
! exit
~zod/try=> (scan "-" pcar:epur)
~~-
~zod/try=> (scan "." pcar:epur)
~~~.
~zod/try=> (scan "%20" pcar:epur)
~~.
~zod/try=> (scan "!" pcar:epur)
~~~21.
### `++pcok`
++ pcok ;~(less bas sem com doq prn) :: cookie char
Cookie character
~zod/try=> (scan "a" pcok:epur)
~~a
~zod/try=> (scan "ab" pcok:epur)
! {1 2}
! exit
~zod/try=> (scan "!" pcok:epur)
~~~21.
~zod/try=> (scan ";" pcok:epur)
! {1 2}
! exit
### `++pesc`
++ pesc ;~(pfix cen mes) :: 2396 escaped
URL `%` escape, by two hex characters.
~zod/try=> `@t`(scan "%22" pesc:epur)
'"'
~zod/try=> `@t`(scan "%20" pesc:epur)
' '
### `++pold`
++ pold (cold ' ' (just '+')) :: old space code
Old URL `' '` escape
~zod/try=> `@t`(scan "+" pold:epur)
' '
~zod/try=> `@t`(scan " " pold:epur)
! {1 1}
! exit
### `++pque`
++ pque ;~(pose pcar fas wut) :: 3986 query char
Irregular query string character.
~zod/try=> `@t`(scan "a" pque:epur)
'a'
~zod/try=> `@t`(scan "?" pque:epur)
'?'
~zod/try=> `@t`(scan "%20" pque:epur)
' '
~zod/try=> `@t`(scan "+" pque:epur)
'+'
### `++pquo`
++ pquo ;~(pose pure pesc pold) :: normal query char
Character in query string key/value
~zod/try=> (scan "a" pquo:epur)
'a'
~zod/try=> (scan "ab" pquo:epur)
! {1 2}
! exit
~zod/try=> (scan "%22" pquo:epur)
'"'
~zod/try=> (scan "%20" pquo:epur)
' '
~zod/try=> (scan "+" pquo:epur)
' '
### `++pure`
++ pure ;~(pose aln hep dot cab sig) :: 2396 unreserved
URL-safe character
~zod/try=> (scan "a" pure:epur)
~~a
~zod/try=> (scan "%20" pure:epur)
! {1 1}
! exit
~zod/try=> (scan "." pure:epur)
~~~.
~zod/try=> (scan "-" pure:epur)
~~-
### `++psub`
++ psub ;~ pose :: 3986 sub-delims
zap buc pam soq pel per
tar lus com sem tis
==
URL path subdelimeter
~zod/try=> `@t`(scan "+" psub:epur)
'+'
~zod/try=> `@t`(scan "(" psub:epur)
'('
~zod/try=> `@t`(scan "$" psub:epur)
'$'
~zod/try=> `@t`(scan "a" psub:epur)
! {1 1}
! exit
### `++ptok`
++ ptok ;~ pose :: 2616 token
aln zap hax buc cen pam soq tar lus
hep dot ket cab tec bar sig
==
Character valid in HTTP token
~zod/try=> `tape`(murn =+(a=' ' |-(`tape`?:(=(0x7f a) ~ [a $(a +(a))]))) (curr rush ptok):epur)
"!#$%&'*+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz|~"
~zod/try=> `tape`(skim =+(a=' ' |-(`tape`?:(=(0x7f a) ~ [a $(a +(a))]))) |=(a=char ?=(~ (rush a ptok:epur))))
" "(),/:;<=>?@[\]{}"
### `++scem`
++ scem :: 2396 scheme
%+ cook cass
;~(plug alf (star ;~(pose aln lus hep dot)))
::
URI scheme: alphabetic character, followed by any number of
alphanumeric, `+` `-` or `.`
~zod/try=> `@t`(scan "http" scem:epur)
'http'
~zod/try=> `@t`(scan "https" scem:epur)
'https'
~zod/try=> `@t`(scan "chrome-extension" scem:epur)
'chrome-extension'
### `++smeg`
++ smeg (cook crip (plus pcar)) :: 2396 segment
URL path segment
~zod/try=> (scan "foo" smeg:epur)
'foo'
~zod/try=> (scan "bar%20baz-bam" smeg:epur)
'bar baz-bam'
### `++tock`
++ tock (cook crip (plus pcok)) :: 6265 cookie-value
HTTP cookie value
~zod/try=> (rush 'sam' tock:epur)
[~ 'sam']
~zod/try=> (rush 'las!tore' tock:epur)
[~ 'las!tore']
~zod/try=> (rush '"sop""les"tor' tock:epur)
~
~zod/try=> (rush '"zemug"' tock:epur)
~
### `++tosk`
++ tosk ;~(pose tock (ifix [doq doq] tock)) :: 6265 cookie-value
Possibly quoted HTTP cookie value
~zod/try=> (rush 'sam' tosk:epur)
[~ 'sam']
~zod/try=> (rush 'las!tore' tosk:epur)
[~ 'las!tore']
~zod/try=> (rush '"sop""les"tor' tosk:epur)
~
~zod/try=> (rush '"zemug"' tosk:epur)
[~ 'zemug']
### `++toke`
++ toke (cook crip (plus ptok)) :: 2616 token
HTTP cookie name
~zod/try=> (rush 'sam' toke:epur)
[~ 'sam']
~zod/try=> (rush 'las!tore' toke:epur)
[~ 'las!tore']
~zod/try=> (rush 'sop""les"tor' toke:epur)
~
~zod/try=> (rush '"zemug"' toke:epur)
~
### `++thor`
++ thor :: 2396 host/port
%+ cook |*(a=[* *] [+.a -.a])
;~ plug
thos
;~(pose (stag ~ ;~(pfix col dim:ag)) (easy ~))
==
Parse ++host and unit `@ui` port.
~zod/try=> (scan "localhost" thor:epur)
[~ [%.y i='localhost' t=~]]
~zod/try=> (scan "localhost:8080" thor:epur)
[[~ q=8.080] [%.y i='localhost' t=~]]
~zod/try=> (scan "192.168.0.1:8080" thor:epur)
[[~ q=8.080] [%.n q=3.232.235.521]]
~zod/try=> (scan "www.google.com" thor:epur)
[~ [%.y i='com' t=~['google' 'www']]]
### `++thos`
++ thos :: 2396 host, no local
;~ plug
;~ pose
%+ stag %&
%+ sear :: LL parser weak here
|= a=(list ,@t)
=+ b=(flop a)
?> ?=(^ b)
=+ c=(end 3 1 i.b)
?.(&((gte c 'a') (lte c 'z')) ~ [~ u=b])
(most dot dlab)
::
%+ stag %|
=+ tod=(ape:ag ted:ab)
%+ bass 256
;~(plug tod (stun [3 3] ;~(pfix dot tod)))
==
==
URI host: dot-separated segments, or IP address.
~zod/try=> (scan "localhost" thos:epur)
[%.y i='localhost' t=~]
~zod/try=> (scan "192.168.0.1" thos:epur)
[%.n q=3.232.235.521]
~zod/try=> (scan "192.168.0.1:80" thos:epur)
! {1 12}
! exit
~zod/try=> (scan "www.google.com" thos:epur)
[%.y i='com' t=~['google' 'www']]
### `++yque`
++ yque :: query ending
;~ pose
;~(pfix wut yquy)
(easy ~)
==
Parses query string, or lack thereof. Result type ++quay
~zod/try=> (scan "?sar=tok" yque:epur)
[['sar' 'tok'] ~]
~zod/try=> (scan "?les=urbit%20sep&met=kam" yque:epur)
[['les' 'urbit sep'] ~[['met' 'kam']]]
~zod/try=> (scan "" yque:epur)
~
### `++yquy`
++ yquy :: query
;~ pose :: proper query
%+ more
;~(pose pam sem)
;~(plug fque ;~(pose ;~(pfix tis fquu) (easy '')))
::
%+ cook :: funky query
|=(a=tape [[%$ (crip a)] ~])
(star pque)
==
Parse query string after `?`
~zod/try=> (scan "sar=tok" yquy:epur)
[['sar' 'tok'] ~]
~zod/try=> (scan "les=urbit%20sep&met=kam" yquy:epur)
[['les' 'urbit sep'] ~[['met' 'kam']]]
~zod/try=> (scan "" yquy:epur)
~
### `++zest`
++ zest :: 2616 request-uri
;~ pose
(stag %& (cook |=(a=purl a) auri))
(stag %| ;~(plug apat yque))
==
--
Parse ++quri absolute or relative request path
~zod/try=> (scan "http://www.google.com:80/search?q=foo" zest:epur)
[%.y p=[p=%.n q=[~ 80] r=[%.y p=<|com google www|>]] q=[p=~ q=<|search|>] r=~[[p='q' q='foo']]]
~zod/try=> (scan "/rel/bat" zest:epur)
[%.n [p=~ q=<|rel bat|>] ~]

View File

@ -1,479 +0,0 @@
section 3bH, names etc
======================
### `++clan`
++ clan :: ship to rank
|= who=ship ^- rank
=+ wid=(met 3 who)
?: (lte wid 1) %czar
?: =(2 wid) %king
?: (lte wid 4) %duke
?: (lte wid 8) %earl
?> (lte wid 16) %pawn
::
Ship class
~zod/main=> (clan ~zod)
%czar
~zod/main=> (clan ~tyr)
%czar
~zod/main=> (clan ~doznec)
%king
~zod/main=> (clan ~tasfyn-partyv)
%duke
### `++glam`
++ glam
|= zar=@pD ^- tape
%+ snag zar
^- (list tape)
:~ "Tianming" "Pepin the Short" "Haile Selassie" "Alfred the Great"
"Tamerlane" "Pericles" "Talleyrand" "Yongle" "Seleucus"
"Uther Pendragon" "Louis XVI" "Ahmad Shāh Durrānī" "Constantine"
"Wilhelm I" "Akbar" "Louis XIV" "Nobunaga" "Alexander VI"
"Philippe II" "Julius II" "David" "Niall Noígíallach" "Kublai Khan"
"Öz Beg Khan" "Ozymandias" "Ögedei Khan" "Jiang Jieshi" "Darius"
"Shivaji" "Qianlong" "Bolesław I Chrobry" "Tigranes" "Han Wudi"
"Charles X" "Naresuan" "Frederick II" "Simeon" "Kangxi"
"Suleiman the Magnificent" "Pedro II" "Genghis Khan" "Laozi"
"Porfirio Díaz" "Pakal" "Wu Zetian" "Garibaldi" "Matthias Corvinus"
"Leopold II" "Leonidas" "Sitting Bull" "Nebuchadnezzar II"
"Rhodes" "Henry VIII" "Attila" "Catherine II" "Chulalongkorn"
"Uthmān" "Augustus" "Faustin" "Chongde" "Justinian"
"Afonso de Albuquerque" "Antoninus Pius" "Cromwell" "Innocent X"
"Fidel" "Frederick the Great" "Canute" "Vytautas" "Amina"
"Hammurabi" "Suharto" "Victoria" "Hiawatha" "Paul V" "Shaka"
"Lê Thánh Tông" "Ivan Asen II" "Tiridates" "Nefertiti" "Gwangmu"
"Ferdinand & Isabella" "Askia" "Xuande" "Boris Godunov" "Gilgamesh"
"Maximillian I" "Mao" "Charlemagne" "Narai" "Hanno" "Charles I & V"
"Alexander II" "Mansa Musa" "Zoe Porphyrogenita" "Metternich"
"Robert the Bruce" "Pachacutec" "Jefferson" "Solomon" "Nicholas I"
"Barbarossa" "FDR" "Pius X" "Gwanggaeto" "Abbas I" "Julius Caesar"
"Lee Kuan Yew" "Ranavalona I" "Go-Daigo" "Zenobia" "Henry V"
"Bảo Đại" "Casimir III" "Cyrus" "Charles the Wise" "Sandrokottos"
"Agamemnon" "Clement VII" "Suppiluliuma" "Deng Xiaoping"
"Victor Emmanuel" "Ajatasatru" "Jan Sobieski" "Huangdi" "Xuantong"
"Narmer" "Cosimo de' Medici" "Möngke Khan" "Stephen Dušan" "Henri IV"
"Mehmed Fatih" "Conn Cétchathach" "Francisco Franco" "Leo X"
"Kammu" "Krishnadevaraya" "Elizabeth I" "Norton I" "Washington"
"Meiji" "Umar" "TR" "Peter the Great" "Agustin I" "Ashoka"
"William the Conqueror" "Kongolo Mwamba" "Song Taizu"
"Ivan the Terrible" "Yao" "Vercingetorix" "Geronimo" "Rurik"
"Urban VIII" "Alexios Komnenos" "Maria I" "Tamar" "Bismarck"
"Arthur" "Jimmu" "Gustavus Adolphus" "Suiko" "Basil I" "Montezuma"
"Santa Anna" "Xerxes" "Beyazıt Yıldırım" "Samudragupta" "James I"
"George III" "Kamehameha" "Francesco Sforza" "Trajan"
"Rajendra Chola" "Hideyoshi" "Cleopatra" "Alexander"
"Ashurbanipal" "Paul III" "Vespasian" "Tecumseh" "Narasimhavarman"
"Suryavarman II" "Bokassa I" "Charles Canning" "Theodosius"
"Francis II" "Zhou Wen" "William Jardine" "Ahmad al-Mansur"
"Lajos Nagy" "Theodora" "Mussolini" "Samuil" "Osman Gazi"
"Kim Il-sung" "Maria Theresa" "Lenin" "Tokugawa" "Marcus Aurelius"
"Nzinga Mbande" "Edward III" "Joseph II" "Pulakesi II" "Priam"
"Qin Shi Huang" "Shah Jahan" "Sejong" "Sui Wendi" "Otto I"
"Napoleon III" "Prester John" "Dido" "Joao I" "Gregory I"
"Gajah Mada" "Abd-ar Rahmān III" "Taizong" "Franz Josef I"
"Nicholas II" "Gandhi" "Chandragupta II" "Peter III"
"Oba Ewuare" "Louis IX" "Napoleon" "Selim Yavuz" "Shun"
"Hayam Wuruk" "Jagiełło" "Nicaule" "Sargon" "Saladin" "Charles II"
"Brian Boru" "Da Yu" "Antiochus III" "Charles I"
"Jan Pieterszoon Coen" "Hongwu" "Mithridates" "Hadrian" "Ptolemy"
"Benito Juarez" "Sun Yat-sen" "Raja Raja Chola" "Bolivar" "Pius VII"
"Shapur II" "Taksin" "Ram Khamhaeng" "Hatshepsut" "Alī" "Matilda"
"Ataturk"
==
::
Retrieve carrier name.
~zod/main=> (glam ~zod)
"Tianming"
~zod/main=> (glam ~fyr)
"Bolivar"
### `++glon`
++ glon
|= lag=lang
^- (unit tape)
?+ lag ~
%aa [~ "Afar"]
%ab [~ "Abkhazian"]
%ae [~ "Avestan"]
%af [~ "Afrikaans"]
%ak [~ "Akan"]
%am [~ "Amharic"]
%an [~ "Aragonese"]
%ar [~ "Arabic"]
%as [~ "Assamese"]
%av [~ "Avaric"]
%ay [~ "Aymara"]
%az [~ "Azerbaijani"]
%ba [~ "Bashkir"]
%be [~ "Belarusian"]
%bg [~ "Bulgarian"]
%bh [~ "Bihari"]
%bi [~ "Bislama"]
%bm [~ "Bambara"]
%bn [~ "Bengali"]
%bo [~ "Tibetan"]
%br [~ "Breton"]
%bs [~ "Bosnian"]
%ca [~ "Catalan"]
%ce [~ "Chechen"]
%ch [~ "Chamorro"]
%co [~ "Corsican"]
%cr [~ "Cree"]
%cs [~ "Czech"]
%cu [~ "Slavonic"]
%cv [~ "Chuvash"]
%cy [~ "Welsh"]
%da [~ "Danish"]
%de [~ "German"]
%dv [~ "Maldivian"]
%dz [~ "Dzongkha"]
%ee [~ "Ewe"]
%el [~ "Greek"]
%en [~ "English"]
%eo [~ "Esperanto"]
%es [~ "Spanish"]
%et [~ "Estonian"]
%eu [~ "Basque"]
%fa [~ "Persian"]
%ff [~ "Fulah"]
%fi [~ "Finnish"]
%fj [~ "Fijian"]
%fo [~ "Faroese"]
%fr [~ "French"]
%fy [~ "Frisian"]
%ga [~ "Irish Gaelic"]
%gd [~ "Scottish Gaelic"]
%gl [~ "Galician"]
%gn [~ "Guarani"]
%gu [~ "Gujarati"]
%gv [~ "Manx"]
%ha [~ "Hausa"]
%he [~ "Hebrew"]
%hi [~ "Hindi"]
%ho [~ "Hiri Motu"]
%hr [~ "Croatian"]
%ht [~ "Haitian Creole"]
%hu [~ "Hungarian"]
%hy [~ "Armenian"]
%hz [~ "Herero"]
%ia [~ "Interlingua"]
%id [~ "Indonesian"]
%ie [~ "Occidental"]
%ig [~ "Igbo"]
%ii [~ "Nuosu"]
%ik [~ "Inupiaq"]
%io [~ "Ido"]
%is [~ "Icelandic"]
%it [~ "Italian"]
%iu [~ "Inuktitut"]
%ja [~ "Japanese"]
%jv [~ "Javanese"]
%ka [~ "Georgian"]
%kg [~ "Kongo"]
%ki [~ "Kikuyu"]
%kj [~ "Kwanyama"]
%kk [~ "Kazakh"]
%kl [~ "Kalaallisut"]
%km [~ "Central Khmer"]
%kn [~ "Kannada"]
%ko [~ "Korean"]
%kr [~ "Kanuri"]
%ks [~ "Kashmiri"]
%ku [~ "Kurdish"]
%kv [~ "Komi"]
%kw [~ "Cornish"]
%ky [~ "Kyrgyz"]
%la [~ "Latin"]
%lb [~ "Luxembourgish"]
%lg [~ "Ganda"]
%li [~ "Limburgish"]
%ln [~ "Lingala"]
%lo [~ "Lao"]
%lt [~ "Lithuanian"]
%lu [~ "Luba-Katanga"]
%lv [~ "Latvian"]
%mg [~ "Malagasy"]
%mh [~ "Marshallese"]
%mi [~ "Maori"]
%mk [~ "Macedonian"]
%ml [~ "Malayalam"]
%mn [~ "Mongolian"]
%mr [~ "Marathi"]
%ms [~ "Malay"]
%mt [~ "Maltese"]
%my [~ "Burmese"]
%na [~ "Nauru"]
%nb [~ "Norwegian Bokmål"]
%nd [~ "North Ndebele"]
%ne [~ "Nepali"]
%ng [~ "Ndonga"]
%nl [~ "Dutch"]
%nn [~ "Norwegian Nynorsk"]
%no [~ "Norwegian"]
%nr [~ "South Ndebele"]
%nv [~ "Navajo"]
%ny [~ "Chichewa"]
%oc [~ "Occitan"]
%oj [~ "Ojibwa"]
%om [~ "Oromo"]
%or [~ "Oriya"]
%os [~ "Ossetian"]
%pa [~ "Punjabi"]
%pi [~ "Pali"]
%pl [~ "Polish"]
%ps [~ "Pashto"]
%pt [~ "Portuguese"]
%qu [~ "Quechua"]
%rm [~ "Romansh"]
%rn [~ "Rundi"]
%ro [~ "Romanian"]
%ru [~ "Russian"]
%rw [~ "Kinyarwanda"]
%sa [~ "Sanskrit"]
%sc [~ "Sardinian"]
%sd [~ "Sindhi"]
%se [~ "Northern Sami"]
%sg [~ "Sango"]
%si [~ "Sinhala"]
%sk [~ "Slovak"]
%sl [~ "Slovenian"]
%sm [~ "Samoan"]
%sn [~ "Shona"]
%so [~ "Somali"]
%sq [~ "Albanian"]
%sr [~ "Serbian"]
%ss [~ "Swati"]
%st [~ "Sotho"]
%su [~ "Sundanese"]
%sv [~ "Swedish"]
%sw [~ "Swahili"]
%ta [~ "Tamil"]
%te [~ "Telugu"]
%tg [~ "Tajik"]
%th [~ "Thai"]
%ti [~ "Tigrinya"]
%tk [~ "Turkmen"]
%tl [~ "Tagalog"]
%tn [~ "Tswana"]
%to [~ "Tonga"]
%tr [~ "Turkish"]
%ts [~ "Tsonga"]
%tt [~ "Tatar"]
%tw [~ "Twi"]
%ty [~ "Tahitian"]
%ug [~ "Uighur"]
%uk [~ "Ukrainian"]
%ur [~ "Urdu"]
%uz [~ "Uzbek"]
%ve [~ "Venda"]
%vi [~ "Vietnamese"]
%vo [~ "Volapük"]
%wa [~ "Walloon"]
%wo [~ "Wolof"]
%xh [~ "Xhosa"]
%yi [~ "Yiddish"]
%yo [~ "Yoruba"]
%za [~ "Zhuang"]
%zh [~ "Chinese"]
%zu [~ "Zulu"]
==
::
ISO language code
~zod/main=> (glon %cs)
[~ "Czech"]
~zod/main=> (glon %en)
[~ "English"]
~zod/main=> (glon %mz)
~
### `++gnom`
++ gnom :: ship display name
|= [[our=@p now=@da] him=@p] ^- @t
=+ yow=(scot %p him)
=+ pax=[(scot %p our) %name (scot %da now) yow ~]
=+ woy=((hard ,@t) .^(%a pax))
?: =(%$ woy) yow
(rap 3 yow ' ' woy ~)
::
Fetch display name from %ames
~zod/main=> (gnom [->-< -<-] ~zod)
'~zod |Tianming|'
~zod/main=> (gnom [->-< -<-] ~doznec)
'~doznec ~doznec'
~zod/main=> (gnom [->-< -<-] ~tug)
'~tug |Go-Daigo|'
### `++gnow`
++ gnow
|= [who=@p gos=gcos] ^- @t
?- -.gos
%czar (rap 3 '|' (rap 3 (glam who)) '|' ~)
%king (rap 3 '_' p.gos '_' ~)
%earl (rap 3 ':' p.gos ':' ~)
%pawn ?~(p.gos %$ (rap 3 '.' u.p.gos '.' ~))
%duke
?: ?=(%anon -.p.gos) %$
%+ rap 3
^- (list ,@)
?- -.p.gos
%punk ~['"' q.p.gos '"']
?(%lord %lady)
=+ ^= nad
=+ nam=`name`s.p.p.gos
%+ rap 3
:~ p.nam
?~(q.nam 0 (cat 3 ' ' u.q.nam))
?~(r.nam 0 (rap 3 ' (' u.r.nam ')' ~))
' '
s.nam
==
?:(=(%lord -.p.gos) ~['[' nad ']'] ~['(' nad ')'])
==
==
::
XX Document
### `++hunt`
++ hunt :: first of unit dates
|= [one=(unit ,@da) two=(unit ,@da)]
^- (unit ,@da)
?~ one two
?~ two one
?:((lth u.one u.two) one two)
::
XX Document
### `++mojo`
++ mojo :: compiling load
|= [pax=path src=*]
^- (each twig (list tank))
?. ?=(@ src)
[%| ~[[leaf/"musk: malformed: {<pax>}"]]]
=+ ^= mud
%- mule |.
((full vest) [1 1] (trip src))
?: ?=(| -.mud) mud
?~ q.p.mud
:~ %|
leaf/"musk: syntax error: {<pax>}"
leaf/"musk: line {<p.p.p.mud>}, column {<q.p.p.mud>}"
==
[%& p.u.q.p.mud]
::
XX Document
### `++mole`
++ mole :: new to old sky
|= ska=$+(* (unit (unit)))
|= a=*
^- (unit)
=+ b=(ska a)
?~ b ~
?~ u.b ~
[~ u.u.b]
::
XX Document
### `++much`
++ much :: constructing load
|= [pax=path src=*]
^- gank
=+ moj=(mojo pax src)
?: ?=(| -.moj) moj
(mule |.((slap !>(+>.$) `twig`p.moj)))
::
XX Document
### `++musk`
++ musk :: compiling apply
|= [pax=path src=* sam=vase]
^- gank
=+ mud=(much pax src)
?: ?=(| -.mud) mud
(mule |.((slam p.mud sam)))
::
XX Document
### `++saxo`
++ saxo :: autocanon
|= who=ship
^- (list ship)
?: (lth who 256) [who ~]
[who $(who (sein who))]
::
Compute list of ancestors
~zod/main=> (saxo ~pittyp-pittyp)
~[~pittyp-pittyp ~dalnel ~del]
~zod/main=> (saxo ~tasfyn-partyv)
~[~tasfyn-partyv ~doznec ~zod]
~zod/main=> (saxo ~ractul-fodsug-sibryg-modsyl--difrun-mirfun-filrec-patmet)
~[~ractul-fodsug-sibryg-modsyl--difrun-mirfun-filrec-patmet ~zod]
### `++sein`
++ sein :: autoboss
|= who=ship ^- ship
=+ mir=(clan who)
?- mir
%czar who
%king (end 3 1 who)
%duke (end 4 1 who)
%earl (end 5 1 who)
%pawn `@p`0
==
Compute direct senior.
~zod/main=> (sein ~tasfyn-partyv)
~doznec
~zod/main=> (sein ~doznec)
~zod
~zod/main=> (sein ~zod)
~zod
~zod/main=> (sein ~pittyp-pittyp)
~dalnel
~zod/main=> (sein ~dalnel)
~del
~zod/main=> (sein ~ractul-fodsug-sibryg-modsyl--difrun-mirfun-filrec-patmet)
~zod
Compute Phonemic base.
~zod/main=> (saxo ~rabdec-monfer)
~[~rabdec-monfer ~dalnel ~del]
~zod/main=> `@rd`~rabdec-monfer
0x5fd25
[%rlyd 0x5.fd25]
0b1.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000.0000
~zod/main=> `@p`0x5.fd25
~rabdec-monfer
For `@rd` and `@p` see the [odors](../reference/odors) reference

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +0,0 @@
---
logo: black
sort: 2
title: Hoon 101
---
Welcome to Hoon 101!
Ideally, you've installed an Urbit planet (if you have a ticket)
or comet (if you don't). See the [user doc](../../user). We
recommend opening up the dojo and just typing the examples; you
don't know a language until you know it in your fingers.
Hoon 101 is still under construction; new chapters are posted
roughly once a week. So far:
<list></list>

View File

@ -1,286 +0,0 @@
---
next: true
sort: 0
spam: true
title: Hoon 101.0: nouns, spans, and molds
---
# Hoon 101.0: nouns, spans and molds
Hoon is a strict, higher-order typed pure-functional language.
Why Hoon? Typed functional languages are known for a pleasant
phenomenon: once your code compiles, it's quite likely to work.
But most typed functional languages are conceptually dependent on
abstract advanced math, and difficult to understand without it.
Hoon is a typed FP language for the common street programmer.
Well-written Hoon is as concrete and data-oriented as possible.
The less functional magic you use, the better. But the magic is
there, mostly, if you need it.
The main disadvantage of Hoon is that its syntax and semantics
are unfamiliar. The syntax will remind too many of Perl, but
like most human languages (and unlike Perl) it combines a regular
core structure with irregular variations. And Hoon's semantic
complexity is bounded by the size of the compiler: type inference plus code
generation are 2000 lines of Hoon. Most peoples' experience is that the
language is much easier to learn than it looks.
> The name "Hoon" is from the Wallace Stevens poem, _Tea at the
Palaz of Hoon_. It also means "hooligan" in Australian.
## How to use this tutorial
Ideally, you've installed an Urbit planet (if you have a ticket)
or comet (if you don't). See the [user doc](../../../user). We
recommend opening up the dojo and just typing the examples; you
don't know a language until you know it in your fingers.
## Nouns: data made boring
A noun is an atom or a cell. An atom is any unsigned integer. A
cell is an ordered pair of nouns.
Nouns are trees; they have no cycles. Noun comparison is always
by value (the programmer can't test pointer equality). Nouns are
strict; there is no such thing as an infinite noun. And nouns are
immutable. There's just no way to have any real fun with nouns.
> Nouns are Lisp's S-expressions, minus a lot of hacks, tricks,
and features that made sense 50 years ago. In particular,
because atoms are not tagged (an atom can encode a string, for
instance), nouns depend on a static type system at a higher
layer. How do you print an atom if you don't know whether it's a
string or a number?
## A type system for nouns
One obstacle to learning Hoon is that it has two quite distinct
concepts that might equally be called a "type." Worse, most
other typed functional languages are mathy and share a basically
mathematical concept of "type." Hoon does not have this concept
at all. We can't avoid using the T-word occasionally, but it has
no precise meaning in Hoon and can be extremely confusing.
Hoon's two kinds of "type" are `span` and `mold`. A span is both
a constructively defined set of nouns, and a semantic convention
for users in that set. A `mold` is a function whose range is
some useful span. A mold is always idempotent (for any noun `x`,
`f(x)` equals `f(f(x))`), and its domain is any noun.
One way to explain this is that while a span is what most
languages call a "type," Hoon has no syntax for the programmer to
define a span directly. Instead, we use inference to define it
as the range of a mold function. This mold can also be used to
validate or normalize untrusted, untyped data -- a common problem
in modern programming, because networks.
> Sending a noun over the network is a good example of why Hoon
is different. In a normal modern language, you serialize and
deserialize a data type by extending your type to implement a
serialization interface. A really good language can process your
type definition and automatically generate this code. In Hoon,
we have one function `jam` that converts any noun to an atom,
and another `cue` that inverts `jam`. To validate, the receiver
applies its own mold to the cued noun, and we've sent typed data
over the network without any attack surface (except `jam` and
`cue`, which fit on a page). No custom serialization code,
manual or generated, is required. The mold itself is not sent;
protocol agreement is out of band.
Hoon's inference algorithm is dumber than the unification
algorithms (Hindley-Milner) used in most typed functional
languages. Hoon thinks only forward, not backward. Eg, Haskell
can infer the result type of a function from its argument
(forward), or the argument type from the result (backward).
Hoon can do the first but not the second.
So Hoon needs more manual annotations, which you usually want
anyway for prosaic software-engineering reasons. Otherwise its
typesystem solves more or less the same job, including
pattern-matching, genericity / typeclasses, etc.
> A good test of a static higher-order typesystem is whether it can
infer the product type of a grammar defined as a combinator
parser. The Hoon parser passes this test; when it typechecks,
the parser's range nests within the span of the expression mold.
## Let's make some nouns
Let's make a noun:
```
~tasfyn-partyv:dojo> 42
```
You'll see the expression you entered, then the result:
```
> 42
42
```
Let's try a different noun. Or is it different?
```
~tasfyn-partyv:dojo> 0x2a
```
You'll see:
```
> 0x2a
0x2a
```
`42` and `0x2a` are actually *the same noun*, because they're the
same number. But we don't just have the noun to print - we have
a `[span noun]` cell (sometimes called a `vase`).
As you recall, a span defines a set of nouns and a semantic
interpretation. As sets, both spans here are "any number". But
semantically, `42` has a decimal span and `0x2a` hexadecimal, so
they print differently.
> It's important to remember that Hoon is a statically typed language.
We don't work with vases unless we're dynamically compiling code,
which is of course what we're doing here in the dojo. In Hoon,
dynamic type equals static type plus runtime compilation.
Let's make some cells. Try these on your own urbit:
```
~tasfyn-partyv:dojo> [42 0x2a]
~tasfyn-partyv:dojo> [42 [0x2a 420]]
~tasfyn-partyv:dojo> [42 0x2a 420]
```
We observe that cells associate right: `[a b c]` is just another
way of writing `[a [b c]]`.
Lisp masters beware: Hoon `[a b]` is Lisp `(a . b)`, Lisp
`(a b)` is Hoon `[a b ~]`. `~` means nil, with value zero. Lisp
and Hoon are both pair-oriented languages down below, but Lisp
has a layer of sugar that makes it look list-oriented. Hoon
loves its "improper lists," ie, tuples.
## Looking at spans
What are these mysterious spans? We can see them with the `?`
prefix, which prints the span along with the result. Moving to
a more compact example format:
```
~tasfyn-partyv:dojo> ? 42
@ud
42
~tasfyn-partyv:dojo> ? 0x2a
@ux
0x2a
```
`@ud` and `@ux` stand for "unsigned decimal" and "unsigned hex,"
obviously.
> What is this span syntax? We only derive spans through
inference. So there's no parsing grammar for a span. We have to
be able to print spans, if only for debugging and diagnostics,
but the syntax is output-only. As in this case, it often looks
like the `mold` syntax, but the two are at opposite ends of the
type food chain.
## Looking at spans, part 2
Usually, good style in Hoon is concrete style. When a Hoon
programmer defines an abstract semantic value in terms of a noun,
we rarely put a conceptual layer of abstraction between value and
noun. We think of the value as an interpretation of the noun.
We don't think of the noun as an implementation of the noun.
But rules are made to be broken. With the `?` command, we *do*
use an abstract layer, by printing our span noun in that custom
syntax. But we can also look at the span noun directly, with the
`??` command. As we'll see, `??` is mainly for newbies, but
newbies love it.
```
~tasfyn-partyv:dojo> ?? 42
[%atom %ud]
42
~tasfyn-partyv:dojo> ?? [42 0x2a]
[%cell [%atom %ud] [%atom %ux]]
[42 0x2a]
```
What is this `%atom` syntax? Is it a real noun? Can anyone
make one?
```
~tasfyn-partyv:dojo> %atom
%atom
~tasfyn-partyv:dojo> %foo
%foo
~tasfyn-partyv:dojo> [%foo %bar]
[%foo %bar]
```
What's the span of one of these symbols?
```
~tasfyn-partyv:dojo> ? %foo
%foo
%foo
~tasfyn-partyv:dojo> ?? %foo
[%cube 7.303.014 [%atom %tas]]
%foo
```
This takes a little bit of explaining. `7.303.014` is just the
Urbit (and German) way of writing the English number `7,303,014`,
or the Urbit hex number `0x6f.6f66`, or the string "foo" as an
unsigned integer with least-significant byte first.
A `%cube` span is a constant -- a set of one noun, the atom
`7.303.014`. But we still need to know how to print that noun.
In this case, it's an `[%atom %tas]`, ie, a text symbol.
Cubes don't have to be symbols -- in fact, we can take the
numbers we've just been using, and make them constants:
```
~tasfyn-partyv:dojo> %42
%42
~tasfyn-partyv:dojo> ? %42
%42
%42
~tasfyn-partyv:dojo> ?? %42
[%cube 42 [%atom %ud]]
%42
```
> Why `??`? Spans are an exception to concrete style, because they
use "manual laziness" to define logically recursive structures.
A recursive span contains Hoon code which is evaluated to apply
it. In practice, this noun often contains the entire Urbit
kernel, so you wouldn't want to try to print it in the dojo. If
you find `??` taking a weirdly long time, this may have happened;
press ^C.
## Our first mold
After seeing a few span examples, are we ready to describe the
set of all spans with a Hoon mold? Well, no, but let's try it
anyway. Ignore the syntax (which we'll explain later; this is a
tutorial, not a reference manual), and you'll get the idea:
```
++ span
$% [%atom p=@tas]
[%cell p=span q=span]
[%cube p=* q=span]
==
```
This mold is not the entire definition of `span`, just the cases
we've seen so far. In English, a valid span is either:
- a cell with head `%atom`, and tail some symbol.
- a cell with head `%cell`, and tail some pair of spans.
- a cell with head `%cube`, and tail a noun-span pair.
The head of a span is essentially the tag in a variant record,
a pattern every programming language has. To use the span, we
look at the head and then decide what to do with the tail.
> A conventional naming strategy for simple, self-explaining
structures is to name the legs of a tuple `p`, `q`, `r`, `s` and
`t`. If you get all the way to `t`, your noun is probably not
simple or self-explaining; meaningful names are recommended.
## Progress
Believe it or not, at this point we understand nouns completely.
We don't understand spans and molds completely, but we get the
basics. In the [next chapter](1-twigs), we'll see how Hoon
expressions (twigs) turn one noun into another.

View File

@ -1,286 +0,0 @@
---
next: true
sort: 1
spam: true
title: Hoon 101.1: twigs and legs
---
# Hoon 101.1: twigs and legs
In the [last chapter](0-nouns), we learned how to make nouns. In
this chapter we'll get into Hoon expressions, or *twigs*.
## How to use this tutorial
Ideally, you've installed an Urbit planet (if you have a ticket)
or comet (if you don't). See the [user doc](../../../user).
We recommend opening up the dojo and just typing the examples;
you don't know a language until you know it in your fingers.
Also, make sure you've worked through the chapters in order.
## Nock for Hoon programmers
Hoon compiles itself to a pico-interpreter called
[Nock](../../nock), a combinator algebra defined in 200 words. This
isn't the place to explain Nock (which relates to Hoon much as
assembly language relates to C), but Nock is just a way to
express a function as a noun.
Nock is a Turing-complete interpreter shaped like (pseudocode):
```
Nock(problem) => product
```
The `problem` is always a cell `[subject formula]`. The
function is the `formula`. The input to the function is the
`subject`. The output is the `product`.
## From Hoon to Nock
The Hoon parser turns an source expression (even one as simple as
`42` from the last chapter) into a noun called a `twig`. If you
know what an AST is, a twig is an AST. (If you don't know what
an AST is, it's not necessarily worth the student loans.)
To simplify slightly, the Hoon compiler is shaped like:
```
Hoon(subject-span function-twig) => [product-span formula-nock]
```
Hoon, like Nock, is a *subject-oriented* language. Your code is
always executed against one input noun, the subject. For any
subject noun in `subject-span` (ie, argument type), the compiler
produces a Nock formula that computes `function-twig` on that
subject, and a `product-span` that is the span of the product
(ie, result type).
> This is really a nontrivial difference. In a normal,
non-subject-oriented language, your code executes against a
scope, stack, environment, or other variable context, probably
not even a regular user-level value. For ordinary coders,
"subject-oriented programming" is one of the hardest things to
understand about Hoon; for some reason, your brain keeps wanting
the interpreter state to be more interesting.
## From constants to twigs
In the last chapter we were entering degenerate twigs like `42`.
Obviously a numeric constant doesn't use the subject at all, so
it's not a very interesting example.
Let's save a test subject as a dojo variable:
```
~tasfyn-partyv:dojo> =test [[[8 9] 5] [6 7]]
```
The `=test` command tells the dojo to rearrange its stock subject
to include this `test` noun. Let's check that it's there:
```
~tasfyn-partyv:dojo> test
[[[8 9] 5] 6 7]
```
> If you're wondering why `[6 7]` got printed as `6 7`, remember
that `[]` associates to the right. Also, `=test` is not in any
way Hoon syntax; it's dojo syntax. Every Hoon twig is a valid
dojo command, but not vice versa.
We want to use `test`, this harmless little noun, as the subject
for some equally harmless twigs. We can do this with the `:`
syntax, which composes twigs in the functional sense. The twig
`a:b` uses the product of twig `b` as the subject of twig `a`.
Trivial cases:
```
~tasfyn-partyv:dojo> 42:test
42
~tasfyn-partyv:dojo> 42:420
42
```
## Tree addressing
The simplest twigs produce a subtree, or "leg", of the subject.
A cell, of course, is a binary tree. The very simplest twig is
`.`, which produces the root of the tree - the whole subject:
```
~tasfyn-partyv:dojo> .:test
[[[8 9] 5] 6 7]
```
Like human languages, Hoon is full of irregular abbreviations.
The `.` syntax is a shorthand for `+1`:
```
~tasfyn-partyv:dojo> +1:test
[[[8 9] 5] 6 7]
```
Hoon has a simple tree addressing scheme (inherited from Nock):
the root is `1`, the head of `n` is `2n`, the tail is `2n+1`.
The twig syntax for a tree address is `+n`.
In our example noun, each leaf is its own tree address:
```
~tasfyn-partyv:dojo> +2:test
[[8 9] 5]
~tasfyn-partyv:dojo> +3:test
[6 7]
~tasfyn-partyv:dojo> +4:test
[8 9]
~tasfyn-partyv:dojo> +5:test
5
~tasfyn-partyv:dojo> +6:test
6
~tasfyn-partyv:dojo> +7:test
7
```
> An instinct for binary tree geometry develops over time as you
use the system, rather the way most programmers learn to do
binary math. No, really.
## Lark syntax
This alternative syntax for a tree address maps noun geometry
directly to a glyph. Lark syntax creates a recognizable
geometric shape by alternating between two head/tail pairs, read
left to right: `-` and `+`, `<` and `>`.
Thus `-` is `+2`, `+` is `+3`, `+<` is `+6`, `->` is `+5`, `-<+`
is `+9`, etc.
> Why lark syntax? Code full of numbers is ugly and distracting,
and looks like hardcoded constants. We actually almost never use
the `+` syntax.
## Simple faces
Tree addressing is cool, but it would be pretty tough to program
in Hoon if it was the only way of getting data out of a subject.
Let's introduce some new syntax:
```
~tasfyn-partyv:dojo> foo=42
foo=42
~tasfyn-partyv:dojo> ? foo=42
foo=@ud
foo=42
~tasfyn-partyv:dojo> ?? foo=42
[%face %foo [%atom %ud]]
foo=42
```
To extend our `++span` mold from the last chapter:
```
++ span
$% [%atom p=@tas]
[%cell p=span p=span]
[%cube p=* q=span]
[%face p=@tas q=span]
==
```
The `%face` span wraps a label around a noun. Then we can
get a leg by name. Let's make a new dojo variable:
```
~tasfyn-partyv:dojo> =test [[[8 9] 5] foo=[6 7]]
```
The syntax is what you might expect:
```
~tasfyn-partyv:dojo> test
[[[8 9] 5] foo=[6 7]]
~tasfyn-partyv:dojo> foo:test
[6 7]
```
Does this do what you expect it to do?
```
~tasfyn-partyv:dojo> +3:test
foo=[6 7]
~tasfyn-partyv:dojo> ? +3:test
foo=[@ud @ud]
foo=[6 7]
~tasfyn-partyv:dojo> ?? +3:test
[%face %foo [%cell [%atom %ud] [%atom %ud]]]
foo=[6 7]
```
## Interesting faces; wings
Let's look at a few more interesting face cases. First, suppose
we have two cases of `foo`?
```
~tasfyn-partyv:dojo> =test [[foo=[8 9] 5] foo=[6 7]]
~tasfyn-partyv:dojo> foo:test
[8 9]
```
In the tree search, the head wins. We can overcome this with a
`^` prefix, which tells the search to skip its first hit:
```
~tasfyn-partyv:dojo> ^foo:test
[6 7]
```
`^^foo` will skip two foos, `^^^foo` three, *ad infinitum*.
But what about nested labels?
```
~tasfyn-partyv:dojo> =test [[[8 9] 5] foo=[6 bar=7]]
~tasfyn-partyv:dojo> bar:test
/~tasfyn-partyv/home/~2015.11.7..21.40.21..1aec:<[1 1].[1 9]>
-find-limb.bar
find-none
```
We can't search *through* a label. If we want to get our `bar`
out, we need to search *into* it:
```
~tasfyn-partyv:dojo> bar.foo:test
7
```
`bar.foo` is what we call a `wing`, a search path in a noun.
Note that the wing runs from left to right, ie, the opposite of
most languages: `bar.foo` means "bar within foo."
Each step in a wing is a `limb`. (Most languages use metaphors;
Hoon abuses them.) A limb can be a tree address, like `+3` or
`.`, or a label like `foo`. We can combine them in one wing:
```
~tasfyn-partyv:dojo> bar.foo.+3:test
7
```
It's important to note the difference between `bar.foo:test`
and `bar:foo:test`, even though they produce the same product:
```
~tasfyn-partyv:dojo> bar:foo:test
7
```
`bar.foo` is one twig, which we run on the product of `test`.
That's different from running `bar` on the product of `foo` on
the product of `test`.
> You're probably used to name resolution in variable scopes
and flat records, but not in trees. Partly this is because the
tradition in language design is to prefer semantics that make it
easy to build simple symbol tables, because linear search of a
nontrivial tree is a bad idea on '80s hardware.
## Mutation
Mutation? Well, not really. We can't modify nouns; the concept
doesn't even make sense in Hoon (or Nock).
Rather, we build new nouns which are copies of old ones, but
with mutations. Let's build a "mutated" copy of our test noun:
```
~tasfyn-partyv:dojo> test
[[[8 9] 5] foo=[6 bar=7]]
~tasfyn-partyv:dojo> test(foo 42)
[[[8 9] 5] foo=42]
~tasfyn-partyv:dojo> test(+8 %eight, bar.foo [%hello %world])
[[[%eight 9] 5] foo=[6 [%hello %world]]]
```
As we see, there's no need for the mutant noun to be shaped
anything like the old noun. They're different nouns.
A mutation, like `+8 %eight`, specifies a wing and a twig.
The wing, like `+8` or `bar.foo`, defines a leg to replace.
The twig runs against the original subject.
Can we use mutation to build a cyclical noun? Nice try, but no:
```
~tasfyn-partyv:dojo> test(+8 test)
[[[[[[8 9] 5] foo=[6 bar=7]] 9] 5] foo=[6 bar=7]]
```
## Progress
Now, not only can you build a noun, you can get data out of it and
even evolve new, related nouns. We've still seen only two very
restricted kinds of twigs: constants and legs. In the [next chapter](2-syntax), we'll actually write some interesting expressions.

View File

@ -1,475 +0,0 @@
---
next: false
sort: 2
spam: true
title: Hoon 101.2: syntax
---
# Hoon 101.2: full-contact syntax
In [chapter 0](0-nouns), we read about nouns. In [chapter 1](1-twigs),
we discovered twigs and legs.
Up till now, we've done everything in the dojo, Hoon's shell /
REPL. Now it's time to actually write a real Hoon source file,
and get a bit deeper into the syntax.
## How to use this tutorial
Ideally, you've installed an Urbit planet (if you have a ticket)
or comet (if you don't). See the [user doc](../../../user).
We recommend opening up the dojo and just typing the examples;
you don't know a language until you know it in your fingers.
Also, make sure you've worked through the chapters in order.
## Building a simple generator
In Urbit there's a variety of source file roles, distinguished by
the magic paths they're loaded from: `/gen` for generators,
`/ape` for appliances, `/lib` for libraries, etc.
We'll start with a generator, the simplest kind of Urbit program.
### Create a sandbox desk
A desk is the Urbit equivalent of a `git` branch. We're just
playing around here and don't intend to soil our `%home` desk with
test files. So let's make a sandbox:
```
|sync %sandbox our %home
```
You just merged the `%home` desk on your own ship into a new
`%sandbox` desk. `%sandbox` has everything in `%home`, but we'll
add more. Future changes in `%home` (such as our over-the-air
updates) will also propagate into `%sandbox`.
> Desks are always born in merges; it makes no sense to create an
empty desk, because anything you do in a desk depends on other
files in the desk. For instance, your file types (marks) are
defined by source files in the same desk.
### Mount the sandbox from Unix
Run the command
```
~tasfyn-partyv:dojo> |mount /=sandbox=/gen %gen
```
This mounts the `/gen` folder from the `%sandbox` desk in your Unix
directory `~/tasfyn-partyv/gen`.
The mount is a two-way sync, "Dropbox style." When you edit a
Unix file and save, your edit is automatically committed as a
change in the `%sandbox` desk. If you change `%sandbox` files
from Urbit, these changes will also propagate to Unix.
### Execute from the sandbox
Let's set the dojo desk to `%sandbox`:
```
~tasfyn-partyv:dojo> =dir /=sandbox=
=% /~tasfyn-partyv/sandbox/~2015.11.13..02.49.37..9e6c/
```
Your prompt will change to:
```
~tasfyn-partyv:dojo/sandbox
```
### Write hello, world
Let's build the simplest possible kind of generator, a builder.
First, configure your favorite Unix text editor to work with
Hoon. There are Hoon modes for vim, emacs and Sublime in the
`extras/` directory of the github repo.
Second, create the file `~/tasfyn-partyv/gen/test.hoon`.
Paste this text into it:
```
:- %say |= * :- %noun
[%hello %world]
```
Get the spaces exactly right, please. Hoon is not in general a
whitespace-sensitive language, but the difference between one space and
two-or-more matters. And for the moment, think of
```
:- %say |= * :- %noun
```
as gibberish boilerplate, like `#include "stdio.h"` at the start of a C
program.
Now, run your builder:
```
~tasfyn-partyv:dojo/sandbox> +test
[%hello %world]
```
This is your first Hoon *program* per se. Congrats!
## Hoon syntax 101
But what's up with this syntax?
### Some syntactic relatives
The relationship between ASCII and human programming languages
is like the relationship between the electric guitar and
rock-and-roll. If it doesn't have a guitar, it's not rock.
If it doesn't use ASCII, it's not a programming language.
Some great rock guitarists play three chords, like Johnny Ramone;
some shred it up, like Jimmy Page. If Lisp is the Ramones of
syntax, Perl or APL is Led Zeppelin. No one has any right to rag
on Perl or APL, but Hoon is a "metalhead" language that shreds
its ASCII very differently.
### The case for heavy metal
The philosophical case for a metalhead language is threefold.
One, human beings are much better at associating meaning with
symbols than they think they are. Two, a programming language is
a professional tool and not a plastic beach shovel.
> "There's a guitar player, a harp player, a double-bass player,
all holding up their blisters. Imagine if you downloaded a
library off the internet... and it gave you blisters! Right? The
horror! And yet... every musician has overcome a barrier to entry
similar to this." — Rich Hickey
And three, the alternative to heavy metal is keywords. When you
use a keyword language, not only are you forcing the programmer
to tiptoe around a ridiculous maze of reserved words. You're
expressing your program through two translation steps:
symbol->English and English->computation.
When you shred, you are going direct: symbol->computation. A
pure-functional language with syntax on the metalhead principle
creates a sense of "seeing the function" which no keyword
language can quite duplicate. Also, all the words you see on the
screen are actually meaningful terms in the program.
But a great metalhead language should *not* be user-extensible.
That way lies King Crimson. (Maybe Haskell is King Crimson: the
prog-rock of programming languages.) A language is a standard;
if users can do whatever with ASCII, there is no standard. If a
metal language can work, it's only by rigorous consistency and
predictability. No macros, operator overloading, etc, etc.
### A glyphic bestiary
Any metalhead language you don't yet know is line noise. Let's
get you up to speed as fast as possible.
A programming language needs to be not just read but said. But
no one wants to say "ampersand." Therefore, we've taken the
liberty of assigning three-letter names to all ASCII glyphs.
Some of these bindings are obvious and some aren't. You'll be
genuinely surprised at how easy they are to remember:
```
ace [1 space] gal < pel (
bar | gap [>1 space, nl] per )
bas \ gar > sel [
buc $ hax # sem ;
cab _ hep - ser ]
cen % kel { soq '
col : ker } tar *
com , ket ^ tec `
doq " lus + tis =
dot . pam & wut ?
fas / pat @ zap !
```
It's fun to confuse the muggles by using these outside Urbit.
Hoon is not whitespace-sensitive, except that its grammar defines
two distinct whitespace tokens: `ace`, a single space, and `gap`,
anything else. `\t`, `\r`, and `\l` choke the parser and should
not appear in your file.
A few digraphs also have irregular sounds:
```
== stet
-- shed
++ slus
-> lark
-< lush
+> dark
+< dish
```
You might remember wondering where the "lark syntax" of chapter 1
got its name. Lark syntax is read in digraphs from the left, so
`+>+` is `darklus`.
> `+>+` is of course `cdddr` in Lisp.
### The shape of a twig
As we learned in chapter 1, a twig - the parsed form of a Hoon
expression - is a noun. As usual in Hoon, the easiest way to
explain both the syntax that compiles into that noun, and the
semantic meaning of the noun, is the noun's physical structure.
#### Autocons
A twig is always a cell, and any cell of twigs is a twig
producing a cell. As an homage to Lisp, we call this
"autocons."
Where you'd write `(cons a b)` in Lisp, you write `[a b]` in
Hoon. The Lisp expression, in Hoon syntax, would be `[%cons a b
~]`. But the Hoon twig is just `[a b]`.
The `???` prefix prints a twig as a noun instead of running it.
Let's see autocons in action:
```
~tasfyn-partyv:dojo/sandbox> ??? 42
[%dtzy p=%ud q=42]
~tasfyn-partyv:dojo/sandbox> ??? 0x2a
[%dtzy p=%ux q=42]
~tasfyn-partyv:dojo/sandbox> ??? [42 0xa]
[[%dtzy p=%ud q=42] [%dtzy p=%ux q=42]]
```
#### The stem-bulb pattern
If the head of your twig is a cell, it's an autocons. If the
head is an atom, it's an unpronounceable four-letter symbol like
the `%dtzy` above.
Except for the funny autocons case, twigs have the same shape
we see in the `span` mold, which we met in chapter 0. It's
essentially a variant record, the most common data structure
ever. In Hoon it's called a *kelp*.
The head of a kelp (like `%dtzy` above) is called the *stem*.
The tail (like `[%ux 42]`) is the *bulb*.
> Think about how to encode tagged data in a noun. It seems
obvious that the noun is a cell, where the head of the cell is
the tag (stem) and the tail is the data (bulb). Then, all these
nouns are cells whose head is an atom. This leaves two noun
shapes "out of band": atoms, and cells whose head is a cell.
> Since no twig is an atom, a cell `[twig twig]` is always a cell
whose head is a cell. So we can distinguish "autocons" from all
stem-bulb nouns, and assign it specific semantics.
#### Runes and stems
A *rune* is a digraph - a sequence of two ASCII glyphs. If you
know C, you know digraphs like `!=` and `?:` and are used to
reading them as single characters.
In Hoon you can *say* runes as words: "zaptis" and "wutcol"
respectively. If we had to say "exclamation point equals" and
"question-colon" all the time, we'd just die.
Most twig stems are made from runes, by concatenating the glyph
names and removing the vowels. For example, the rune `=+`,
pronounced "tislus," becomes the stem `%tsls`. (Note that in
most noun implementations, this is a 31-bit direct value.)
> Some twig stems (like `%dtzy`) are not runes, simply because
they don't have regular-form syntax and don't need to use
precious ASCII real estate. They are otherwise no different.
An important point to note about runes: they're organized. The
first glyph in the rune defines a category. For instance, runes
starting with `.` compute intrinsics; runes starting with `|`
produce cores; etc.
Another important point about runes: they come in two flavors,
"natural" (stems interpreted directly by the compiler) and
"synthetic" (macros, essentially).
> Language food fight warning: one advantage of Hoon over Lisp
is no gensyms. All Hoon macros are perfectly hygienic. Another
advantage is that Hoon has no (user-level) macros. In Hoon
terms, nobody gets to invent their own runes, because that way
lies DSL write-only chaos. But if we had user-level macros,
they'd be perfectly hygienic as well.
#### Tall and wide regular forms
A good rune example is the simple rune `=+`, pronounced "tislus",
which becomes the stem `%tsls`. A `%tsls` twig has the mold
`[%tsls p=twig q=twig]`.
The very elegance of functional languages creates a visual
problem that imperative languages lack. An imperative language
has distinct statements (with side effects) and (usually pure)
expressions; it's natural that in most well-formatted code,
statements flow vertically down the screen, and expressions grow
horizontally across this. This interplay creates a natural and
relaxing shape on your screen.
In a functional language, there's no difference. The trivial
functional syntax is Lisp's, which has two major problems. One:
piles of expression terminators build up at the bottom of complex
functions. Two: the natural shape of code is diagonal. The more
complex a function, the more it wants to besiege the right
margin. The children of a node have to start to the right of its
parent, so the right margin bounds the tree depth.
Hoon does not completely solve these problems, but alleviates
them. In Hoon, there are actually two regular syntax forms for
most twig cases: "tall" and "wide" form. Tall twigs can contain
wide twigs, but not vice versa, so the visual shape of a program
is very like that of a statements-and-expressions language.
Also, in tall mode, most runes don't need terminators. Take
`=+`, for example. Since the parser knows to expect exactly
two twigs after the `=+` rune, it doesn't need any extra syntax
to tell it that it's done.
Let's try a wide `=+` in the dojo:
```
~tasfyn-partyv:dojo/sandbox> =+(planet=%world [%hello planet])
[%hello %world]
```
(`=+` seems to be some sort of variable declaration? Let's not
worry about it right now. We're on syntax.)
The wide syntax for a `=+` twig, or any binary rune: `(`, the
first subtwig, one space, the second subtwig, and `)`). To read
this twig out loud, you'd say:
```
tislus pel planet tis cen world ace sel cen hello ace planet ser per
```
> Various colloquialisms inevitably creep into this usage. "tis" not
in a rune gets contracted to "is"; "ace" is often just assumed; etc.
Let's try a tall `=+` in `test.hoon`:
```
:- %say |= * :- %noun
=+ planet=%world
[%hello planet]
```
The tall syntax for a `=+` twig, or any binary rune: the rune, at
least two spaces or one newline, the first subtwig, at least two
spaces or one newline, the second subtwig. Again, tall subtwigs
can be tall or wide; wide subtwigs have to be wide.
(Note that our boilerplate line is a bunch of tall runes on one
line, with two-space gaps. This is unusual but quite legal, and
not to be confused with the actual wide form.)
To read this twig out loud, you'd say:
```
tislus gap planet is cen world gap nep cen hello ace planet pen
```
#### Layout conventions
Should you use wide twigs or tall twigs? When? How? What
should your code look like? You're the artist. Except for the
difference between one space (`ace`) and more space (`gap`), the
parser doesn't care how you format your code. Hoon is not Go --
there are no fixed rules for doing it right.
> Keep lines under 80 characters, though. The parser doesn't
enforce this yet. But it will, so watch out!
#### Backstep indentation
Note that the "variable declaration" metaphor of `=+` works
perfectly here. Because `[%hello planet]` -- despite being a
subtree of the the `=+` twig -- is at the same indent level. A
variable declaration shouldn't add indent depth. And `=+`
doesn't. Our code flows down the screen, not down and to the
right, and of course there are no superfluous terminators.
Another example, using a ternary rune with a strange resemblance
to C:
```
:- %say |= * :- %noun
=+ planet=%world
?: =(%world planet)
[%hello planet]
[%goodbye planet]
```
This is called "backstep" indentation. Not all the children of
`?:` ("wutcol", `%wtcl`) are at the same indent as the parent;
but one of them is.
It's not always the case when backstepping that the largest
subtwig is at the bottom and loses no indent, but it often is.
And we do a lot to help you maintain this.
For instance, `=+` ("tislus") is a binary rune: `=+(a b)`. In
most cases of `=+` the heavy twig is `b`, but sometimes it's `a`.
So we can use its friend the `=-` rune ("tishep") to get the same
semantics with the right shape: `=-(b a)`. Similarly, instead of
`?:(a b c)`, we can write `?.(a c b)`.
Not all runes have tuple structure; some are n-ary, and use
the `==` terminator (again, pronounced "stet"):
```
:- %say |= * :- %noun
=+ planet=%world
?+ planet
[%unknown planet]
%world [%hello planet]
%ocean [%goodbye planet]
==
```
So we occasionally lose right-margin as we descend a deep twig.
But we can keep this lossage low with good layout design.
#### Irregular forms
There are more regular forms than we've shown above, but not a
lot more. Hoon would be quite easy to learn if it was only its
regular forms. It wouldn't be as easy to read or use, though.
The learning curve is important, but not all-important.
Some stems (like the `%dtzy` constants above) obviously don't and
can't have any kind of regular form (which is why `%dtzy` is not
a real digraph rune). Many of the true runes have only regular
forms. But some have irregular forms. Irregular forms are
always wide, but there is no other constraint on their syntax.
We've already encountered one of the irregular forms: `foo=42`
from the last chapter, and `planet=%world` here. Let's unpack
this twig:
```
~tasfyn-partyv:dojo/sandbox> ?? %world
[%cube 431.316.168.567 %atom %tas]
%world
~tasfyn-partyv:dojo/sandbox> ??? %world
[%dtzz %tas 431.316.168.567]
```
Clearly, `%dtzz` is one of our non-regulars. But we can wrap it
with our irregular form:
```
~tasfyn-partyv:dojo/sandbox> ?? planet=%world
[%face %planet [%cube 431.316.168.567 %atom %tas]]
planet=%world
~tasfyn-partyv:dojo/sandbox> ??? planet=%world
[%ktts %planet %dtzz %tas 431.316.168.567]
```
Since `%ktts` is "kettis", ie, `^=`, this has to be the irregular
form of
```
~tasfyn-partyv:dojo/sandbox> ^=(planet %world)
planet=world
```
So if we wrote our example without this irregular form, it'd be
```
:- %say |= * :- %noun
=+ ^=(planet %world)
[%hello planet]
```
Or with a gratuitous use of tall form:
```
:- %say |= * :- %noun
=+ ^= planet %world
[%hello planet]
```
## Progress
Now you know how to read Hoon! For fun, try to pronounce more of
the code on this page. Please don't laugh too hard at yourself.
In the [next chapter](3-program), we'll actually write a real program...

View File

@ -1,350 +0,0 @@
---
next: false
sort: 3
spam: true
title: Hoon 101.3: an algorithm
---
# Hoon 101.3: an algorithm
In [chapter 0](0-nouns), we read about nouns. In [chapter 1](1-twigs),
we discovered twigs and legs. In [chapter 2](2-syntax), we learned
Hoon syntax and created our first source file.
Now it's time for an actual, meaningful *algorithm*.
## How to use this tutorial
Ideally, you've installed an Urbit planet (if you have a ticket)
or comet (if you don't). See the [user doc](../../../user).
We recommend opening up the dojo and just typing the examples;
you don't know a language until you know it in your fingers.
Also, make sure you've worked through the chapters in order.
## Goal: a decrement generator
Our algorithm is the classic Urbit example: decrement.
If you learned [Nock](../../nock) before Hoon, you've already
written decrement. If not, all you need to know is that the only
built-in arithmetic operator in Nock is increment. To decrement,
we need to count up to the result with a simple loop.
## A practical subject
As we've seen, Hoon works by running a twig against a subject.
In chapter 1, we made a simple test subject that was just a few
constants, and applied some simple twigs to it.
This time, we'll actually put useful working data in the subject,
building up more and more complex subjects as we go.
## Subject: nil
We'll start with the empty subject `~`:
```
:- %say |= * :- %noun
=> ~
[%hello %world]
```
The `=>` rune ("tisgar", `%tsgr`)), for `=>(p q)` executes `p`
against the subject, then uses that product as the subject of
`q`.
> We've already used an irregular form of `=>`, or to be more
precise its mirror `=<` ("tisgal", `%tsgl`). In chapter 1, when we wrote
`+3:test`, we meant `=>(test +3)` or `=<(+3 test)`.
What is `~`? It's Hoon `nil`, a zero atom:
```
~tasfyn-partyv:dojo/sandbox> ?? ~
[%cube 0 [%atom %n]]
~
```
We use `~` for list terminators and the like. Obviously, since
`[%hello %world]` is just a constant, a nil subject works as
well as any:
```
~tasfyn-partyv:dojo/sandbox> +test
[%hello %world]
```
## Subject: `arg=@`
Above, we used an empty subject to avoid the very complex,
interesting subject your generator twig gets by default.
But a decrement generator needs to get an argument from the
command line -- the number we're trying to decrement.
This involves changing the `test.hoon` boilerplate a little.
Again, don't worry about the boilerplate line just yet:
```
:- %say |= [* [[arg=@ud ~] ~]] :- %noun
=> arg=arg
[%hello arg]
~tasfyn-partyv:dojo/sandbox> +test 42
[%hello 42]
```
> `=> arg=arg` looks a little odd. We wouldn't ordinarily do
this; we're just trying to keep the subject simple.
In case there's any doubt about the subject (remember from
chapter 1 that `.` means `+1`, the whole subject):
```
:- %say |= [* [[arg=@ud ~] ~]] :- %noun
=> arg=arg
.
~tasfyn-partyv:dojo/sandbox> +test 42
arg=42
```
## An increment generator
We can even write a trivial increment generator using `.+`,
or even better its irregular form `+`:
```
:- %say |= [* [[arg=@ud ~] ~]] :- %noun
=> arg=arg
+(arg)
~tasfyn-partyv:dojo/sandbox> +test 42
43
```
We'll assume these same first two lines for the rest of the
examples in this chapter.
## Cores: one more kind of span
To decrement, we need a loop. To write a loop, we need yet
another kind of noun: the *core*. Briefly, a core is a `[code
data]` pair. Our new `span` mold:
```
++ span
$% [%atom p=@tas]
[%cell p=span p=span]
[%core p=span q=(map ,@tas twig)]
[%cube p=* q=span]
[%face p=@tas q=span]
==
```
### Structure of a core
The core is a cell `[battery payload]`. The payload is data, the
battery is code -- a tree of Nock formulas.
In the `%core` span, the payload is described by an arbitrary
span. The battery is described by a map of symbol to twig.
> Yes, the span contains the complete AST of the whole core.
This is a very different approach from most typed languages,
which compute function signatures. To infer the product of an
arm, we retrace the code in theory, but cache in practice.
### Arms are computed attributes
How do we use a core? Remember that Nock is a function
```
Nock(subject formula) -> product
```
To activate a core, we pull one formula from the battery, and
execute with the whole core as the subject. Coincidentally,
Nock has one macro instruction, `9`, that does just this.
So the formula defines an arbitrary function on the core. The
name of this function (as defined in the twig map) is a computed
attribute, or *arm*.
> Is a core an object? Not quite, because an arm is not a method.
Methods in an OO language have arguments. Arms are functions
only of the payload. (A method in Hoon is an arm that produces a
gate, which is another core -- but we're getting too far ahead.)
However, the battery does look a lot like a classic "vtable."
### Arms and wing resolution
It might be a good time to brush up on your [chapter 1](1-twigs).
The wing resolution algorithm gets a little more complicated.
Hoon overloads computed attributes (arms) and literal attributes
(legs) in the same namespace. A label in a wing may refer to
either. when searching a core, we look for a matching arm. If
we find it we're done. If we don't, or if a `^` mark makes us
skip, we search into the payload.
Only the last limb in the wing can activate an arm. If a name
resolves to a core arm, but it's not the last limb in the wing,
the arm produces the core itself. Similarly, when the wing is
not an access but a mutation, the arm refers to the core. Only
the end of the wing is activated.
> Suppose `foo` is a core. `bar` is an arm on foo. Then `bar.foo`
computes the `bar` arm. Perhaps the product is another core.
Even if `moo` is an arm in this new core, `bar.foo`, the wing
`moo.bar.foo` does not compute `moo` on the core `bar.foo`.
Instead, it looks for `moo` within the payload of the core `foo`.
(You're looking for `moo:bar.foo`, ie, `=>(bar.foo moo)`.)
Does this sound too tricky? Hopefully not, but it's about the
most complicated semantic rule you'll find in Hoon.
## Increment with a core
Keeping our two-line boilerplate, let's increment with a core:
```
=< inc
|%
++ inc
+(arg)
--
~tasfyn-partyv:dojo/sandbox> +test 42
43
```
What's going on? We used the `|%` rune ("barcen") to produce a
core. (There are a lot of runes which create cores; they all
start with `|`, and are basically macros that turn into `|%`.)
The payload of a core produced with `|%` is the subject with
which `|%` is compiled. We might say that `|%` wraps a core
around its subject. In this case, the subject of the `|%`,
and thus payload, is our `arg=@ud` argument.
Then we used this core as the subject of the simple wing `inc`.
> Remember that `=<(a b)` is just `=>(b a)`. The core is heavy
and `inc` is light, so we use `=<` to put the heavy part last.
The prettyprinter can even print a core, sort of. Take out the
`=< inc`:
```
|%
++ inc
+(arg)
--
~tasfyn-partyv:dojo/sandbox> +test 42
<1.bgq arg=42>
~tasfyn-partyv:dojo/sandbox> ? +test 42
<1.bgq arg=@ud>
<1.bgq arg=42>
```
In this notation, `1` means the number of arms in the core, `bgq`
is a very short fingerprint, and `arg=42` is the payload (and
`arg=@ud` is the payload span).
> Cores can be large and complex, and we obviously can't render all
the data in them, either when printing a type or a value. At
some point, you'll probably make the mistake of printing a big
core, maybe even the whole kernel, as an untyped noun. Just
press ^C.
## Adding a counter
To decrement, we need to count up to the argument. So we need a
counter in our subject, because where else would it go?
Let's change the subject to add a counter, `pre`:
```
=> [pre=0 .]
=< inc
|%
++ inc
+(arg)
--
~tasfyn-partyv:dojo/sandbox> +test 42
43
```
Once again, `.` is the whole subject, so we're wrapping it in a
cell whose head is `pre=0`. This doesn't change the way we use
`arg`, even though it's one level deeper in the subject tree.
Let's look at the subject again:
```
=> [pre=0 .]
.
~tasfyn-partyv:dojo/sandbox> +test 42
[pre=0 arg=42]
~tasfyn-partyv:dojo/sandbox> ? +test 42
[pre=@ud arg=@ud]
[pre=0 arg=42]
```
There's a less cluttered way to write `=>([a .] b)`. In wide
mode, `=+(a b)`. A tall example:
```
=+ pre=0
.
~tasfyn-partyv:dojo/sandbox> +test 42
[pre=0 arg=42]
```
This rune `=+`, "tislus", `%tsls`, is of course the "variable
declaration" we saw in chapter 2.
## We actually decrement
Now we can write our actual decrement program, combining the
features we've explored above:
```
=+ pre=0
=< dec
|%
++ dec
?: =(arg +(pre))
pre
dec(pre +(pre))
--
~tasfyn-partyv:dojo/sandbox> +test 42
41
```
`=(a b)` is an irregular form of `.=(a b)`, ie, "dottis" or the
noun `[%dtts a b]`. Likewise, `+(a)` is `.+(a)`, ie, "dotlus"
or `[%dtls a]`.
`?:`, "wuttis", `%wtts`, does exactly what it does in C.
The real action is in `dec(pre +(pre))`. We saw this same
mutation form in chapter 1. It's an irregular form of the `%=`
rune, "centis", `%cnts`.
Here, of course, we're computing an arm of a mutated core. We're
recomputing the loop arm, `dec`, against a new core with an
incremented `pre` leg. Basically, everything interesting in Hoon
happens when you compute an arm of a mutated core.
The whole program, using only regular forms, wide and tall:
```
=+ ^=(pre 0)
=< dec
|%
++ dec
?: .=(arg .+(pre))
pre
%= dec
pre .+(pre)
==
--
~tasfyn-partyv:dojo/sandbox> +test 42
41
```
A good illustration of why we need irregular forms.
## Progress
Now we've actually done something useful. Well, if you count
O(n) decrement as something useful.
We've actually seen most of the major tools in Hoon's toolbox,
just in a super-minimalist selection. But we'll need a few more
runes to get to something that looks like real programming.
For instance, we have a decrement algorithm, but we don't have a
decrement *function* - in the Hoon sense of the word, anyway. We
don't see `(dec arg)` in this code. That'll be the next chapter.

View File

@ -1,327 +0,0 @@
---
next: false
sort: 4
spam: true
title: Hoon 101.4: functions
---
# Hoon 4: toward actual functions
In [chapter 0](0-nouns), we read about nouns. In [chapter 1](1-twigs),
we discovered twigs and legs. In [chapter 2](2-syntax), we learned
Hoon syntax and created our first source file. In [chapter 3](3-algorithm)
we wrote an actual algorithm.
Now we'll go a step farther and actually define a *function*.
## Goal: `(decrement arg)`
Of course, Hoon is a functional language and every twig defines a
function of the subject. But we haven't seen the Hoon equivalent
of a function *declaration*. Where is Lisp `defun`?
Also, the Hoon equivalent of a normal function call can't just
involve compiling the function into a Nock formula, whose subject
is the function's argument. As Einstein said, everything must be
as simple as possible, but no simpler.
A function that worked this way would, by definition, have no
access to data or code other than the argument. Where would the
standard library go? Would we have to pass it in the argument?
## Form of the solution
Let's get the boilerplate out of the way. We'll keep the same
external generator interface, but our solution will look like:
```
=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
(decrement arg)
=> ~
!!
```
In place of the `!!`, we'll put a core, effectively a library,
that exports a function `decrement`. We'll then call that
function with `(decrement arg)`, an irregular form of
`%-(decrement arg)`. Again, this core uses `=> ~` to clear
the subject, so we can't cheat and call `(dec arg)`.
> `!!`, or "zapzap" or `[%zpzp ~]`, is a twig that
always crashes. Because it produces the empty span (`%void`), it
doesn't cause type inference problems.
## Not quite a function call
As usual, we'll get to our goal gradually. A first try:
```
=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
=+ gat=decrement
=<(run gat(sam arg))
=> ~
|%
++ decrement
=+ sam=0
=+ pre=0
|%
++ run
?: =(sam +(pre))
pre
run(pre +(pre))
--
--
~tasfyn-partyv:dojo/sandbox> +test 42
41
```
This works, but it's hardly concise or pretty. We'll get there.
We replaced the `!!` with a `|%` twig that produces a library
core. The payload of our library core is `~`, because that's the
subject we sent in. The battery contains one arm, `decrement`.
The `decrement` arm produces an inner core. The payload of this
inner core is `[pre=0 sam=0 +>]`, where `+>` is the library core.
The battery of the inner core has one arm, `run`, which computes
our algorithm from the last chapter.
To run our algorithm, we put the core that `decrement` produces
into a new leg, `gat`. Mutating this core to set `sam` to our
argument `arg`, we evaluate the `run` arm.
> Why do we need this `gat` leg? Why can't we just write `=<(run
decrement(sam arg))`? Remember our `moo:bar.foo` problem from
the previous chapter. `decrement(sam arg)` mutates not the
*product* of the decrement arm, but the core that computes it.
There's no `sam` in that subject, so the twig won't compile.
## Better is worse
To make this code look simpler, we need to make it more complex.
Our next try uses not two nested cores, but *three*:
```
=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
=+ gat=decrement
=<(run gat(sam arg))
=> ~
|%
++ decrement
=+ sam=0
|%
++ run
=+ pre=0
=< loop
|%
++ loop
?: =(sam +(pre))
pre
loop(pre +(pre))
--
--
--
```
This is actually the final structure of our function, but uses
none of the syntactic tricks we'll use to make it pretty.
> Why do we need to make the code more complex? Because we need
it to use the regular form that our synthetic runes, ie macros,
use to express function definitions and calls.
## Loop sugar
Look at little `loop`. It works just like our old `run`. But
there's something nice about it: we don't use the symbol `loop`
anywhere outside these 7 lines of code. It's not exported.
Therefore, the `loop` name is useless and redundant. Making up
names is one of the hard problems in computer science, so why
solve it for no reason?
So Hoon has an *empty name*: `$`. As a constant, `$` is a
zero-length symbol (`%$` instead of `%foo`) As a limb is the
`buc` symbol (`$`).
Replacing `loop` with `$`, our loop becomes:
```
=< $
|%
++ $
?: =(sam +(pre))
pre
$(sam +(run))
--
```
This may not seem like a huge improvement. It's not. But it
lets us match and move to the synthetic rune `|-`, "barhep":
```
|- ?: =(sam +(pre))
pre
$(pre +(pre))
```
`|-` is simply the canonical Hoon loop. All we've done to use a
core as a loop is to name our arm `$`, and evaluate it on the
core we just made.
Our program now:
```
=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
=+ gat=decrement
=<(run gat(sam arg))
=> ~
|%
++ decrement
=+ sam=0
|%
++ run
=+ pre=0
|- ?: =(sam +(pre))
pre
$(pre +(pre))
--
--
```
## Almost to lambda
Could we use `$` for `++run`? It certainly sounds like the same
kind of thing as `++loop`. The word "run" just means "do it".
Why should we be saying "do it" all the time?
Our third try, with this change:
```
=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
=+ gat=decrement
=<($ gat(sam arg))
=> ~
|%
++ decrement
=| sam=@ud
|%
++ $
=+ pre=0
|- ?: =(sam +(pre))
pre
$(pre +(pre))
--
--
~tasfyn-partyv:dojo/sandbox> +test 42
41
```
> Besides `run` to `$`, we changed `=+ sam=0` to `=| sam=@ud`.
This is some mold magic we'll explain in the next chapter, but
it basically does the same thing: pushes a leg named `sam`, whose
value is a number we'll later overwrite.
This use of `$` in a core, very similar to the way we used `$` in
our `|-` loop, smells like it too should have a rune. It does:
```
=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
=+ gat=decrement
=<($ gat(sam arg))
=> ~
|%
++ decrement
|= sam=@ud
=+ pre=0
|- ?: =(sam +(pre))
pre
$(pre +(pre))
--
~tasfyn-partyv:dojo/sandbox> +test 42
41
```
Doesn't `decrement` look like a function? Indeed, we're done with
the `decrement` arm. This is what it should look like.
> If you squint a little, `|=` ("bartis") might even be a strange,
deformed ASCII-art lambda.
Since it's doing something simple, we might well even compress
the whole body of `decrement` into one wide-form line:
```
=+(pre=0 |-(?:(=(sam +(pre)) pre $(pre +(pre)))))
```
This is a bit tight for most. But we can get really compact by
dropping the labels and going to full geometry:
```
=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
=+ gat=decrement
=<($ gat(sam arg))
=> ~
|%
++ decrement |=(@ud =+(0 |-(?:(=(+>+< +<) +< $(+< +(+<))))))
--
```
> It's not a good idea to actually program this way. But it does
strengthen your Hoon tree-geometry muscles. To use tree
geometry, you have to really know the shape of your subject.
## Structure of a gate
What is the noun produced by `decrement`? In true Hoonese it's
a *gate*, but nobody will hate you for saying "function." And
while we *slam* our gates, you can feel free to just "call" them.
Every gate is a core; not every core is a gate. All cores are
shaped like `[battery payload]`. A core is a gate if its payload
is a cell, and its battery has one arm, `$`. So a gate is shaped
like `[formula [sample context]]`.
To slam (call) a gate, you replace its sample (`+6` or `+<`,
"lusgal" or "dish") with your argument. "Multiple arguments" are
a single sample that's a tuple. So our code should actually read
```
=+ gat=decrement
=<($ gat(+< arg))
```
This `=+` sequence remains ugly. Once again, `decrement(+< arg)`
is not a mutation to the product of `decrement`, but a mutation
to the core that produces `decrement`. Fortunately, there's a
sugary rune that combines the semantics of both these lines:
```
%*($ decrement +< arg))
```
This mutates the product of `decrement` as specified. (`+< arg`
in the wide form of `$*` is just the first of n comma-separated
pairs; we could write `%*($ decrement +< arg, +> foo, moo 42)`.
> Arguably, %* is oversweetened; $:(decrement +< arg)
would be simpler and better. Hoon isn't perfect.
## Slamming the gate
Anyway, it shouldn't come as a surprise that a synonym for
`%*($ function +< argument)` is `%-(function argument)`. And an
irregular form of this is just `(function argument)`.
The irregular syntax constructs multiple-argument syntax as a
tuple; `(add 2 2)` is `(add [2 2])`, `(rsh 3 1 5)` is `(rsh [3 1 5])`.
If there are no arguments, `(function)`, this means `$:function`,
ie, `=>(function $)`.
We can also take the `=> ~` out, since we now know what we're
doing. The final program:
```
=< :- %say |= [* [[arg=@ud ~] ~]] :- %noun
(decrement arg)
|%
++ decrement
|= sam=@ud
=+ pre=0
|- ?: =(sam +(pre))
pre
$(pre +(pre))
--
```
## Progress
In most functional languages, a function is a primitive. In Hoon
it's a macro, and a pretty complex macro at that. We spent four
chapters building the concept up out of much smaller pieces.
Fortunately, once you have functions you can do anything. We
still have a fair bit to learn, but we've now seen all the
fundamental building blocks of programming in Hoon. In the next
chapter, we'll get back into molds and spans.

View File

@ -1,7 +0,0 @@
References
==========
Aside from the runes and standard library there are a few things worth
knowing about the hoon language. You can find those here.
<list></list>

View File

@ -1,686 +0,0 @@
Odors
=====
Overview
--------
Since Everything in Hoon is a natural number, the interpreter needs to
know both how to render them and subject them to type enforcement.
Odors, which are just ASCII spans beginning with a `@`, carry all of the
information necessary for the interpreter to do this. For instance, the
interpreter knows to render an atom of odor `@t` as UTF-8 text.
The span composing the Odor consists of two parts: a lowercase prefix
carrying type information, and an upper-case suffix containing
information about its size. The prefix is a taxonomy that grows more
specific to the right. For example, atoms of the odor `@ta` are URL-safe
ASCII text, and Atoms of the odor `@tas` are the more specific subset of
ASCII text that is acceptable in hoon.
The general principle of type enforcement is that atoms change freely
either up or down the taxonomy, but not across. You can treat a `@tas`
as a `@t`, as in a strong type system; but you can also treat a `@t` as
a `@tas`, or an `@` as anything. However, passing a `@t` to a function
that expects an `@ux` is a type error.
XXDIAGRAMXX
For example, you can cast a `@t` to a `@tas`, or vice-versa:
~zod/try=> =a `@t`'permitted'
~zod/try=> a
'permitted'
~zod/try=> `@tas`a
%permitted
However, you cannot pass a `@ux` to a function that expects a `@t`
without casting it to a `@` first:
~zod/try=> (|=(a=@t [%foo a]) 0x20)
! type-fail
! exit
~zod/try=> =a 0x21
~zod/try=> (|=(a=@t [%foo a]) `@t`a)
[%foo '!']
Note that when explicitly casting a `@ux` to a `@t`, the interpreter
automatically casts the `@ux` to a `@` first.
Comprehensive list of the Hoon Odors
------------------------------------
@c UTF-32 codepoint
@d date
@da absolute date
@dr relative date (ie, timespan)
@f yes or no (inverse boolean)
@n nil
@p phonemic base
@r IEEE floating-point
@rd double precision (64 bits)
@rh half precision (16 bits)
@rq quad precision (128 bits)
@rs single precision (32 bits)
@s signed integer, sign bit low
@sb signed binary
@sd signed decimal
@sv signed base32
@sw signed base64
@sx signed hexadecimal
@t UTF-8 text (cord)
@ta ASCII text (span)
@tas ASCII symbol (term)
@u unsigned integer
@ub unsigned binary
@ud unsigned decimal
@uv unsigned base32
@uw unsigned base64
@ux unsigned hexadecimal
Odor Size Suffixes
------------------
The suffix of an odor, if present, is a single upper-case character A-Z
`c`, which indicates the size of an atom. This is possible, because in
Hoon, a letter maps to an ASCII code number, thus a number.
Size is specified in bits in the form of `1 << (c - 'A')` resp. `2^c`,
since most data aligns to the power of 2 or can be composed of such
blocks.
The size of a block of size `N` can be calculated for example using
`(bex (sub 'N' 'A'))` in bits or `(div (bex (sub 'N' 'A')) 8)` in bytes.
Thus, `@tD` is one UTF-8 byte (whatever that means) and `@tN` is 1
kilobyte or less of UTF-8.
For reference:
A 1 bit
B 2 bits
C 4 bits
D 1 byte
E 2 bytes
F 4 bytes
G 8 bytes
H 16 bytes
I 32 bytes
J 64 bytes
K 128 bytes
L 256 bytes
M 512 bytes
N 1K
O 2K
P 4K
Q 8K
R 16K
S 32K
T 64K
U 128K
V 256K
W 512K
X 1MB
Y 2MB
Z 4MB
It is possible to construct an atom bigger than 4Mb in size, but the
type system would not be able to express an odor size for it.
There is also the datatype `++bloq` to hold a to-the-power-of block size
(though it is just an alias for `@`).
------------------------------------------------------------------------
### @c
UTF-32 codepoint
Atoms of the odor `@c` represent Unicode text, constructed with a UTF-32
bytestream, with the lowest-significant bit first. Although we usually
use a UTF-8 bytestream, sometimes it's useful to build atoms of one or
more UTF-32 words.
##### Forms
`~-[text]`
##### Examples
~zod/try=> :type; ~-foo
~-foo
@c
~zod/try=> ~-i~2764.u
~-i~2764.u
~zod/try=> (tuft ~-i~2764.u)
'i❤u'
~zod/try=> `@ux`~-foo
0x6f.0000.006f.0000.0066
~zod/try=> `@ux`~-i~2764.u
0x75.0000.2764.0000.0069
~zod/try=> `@ux`(tuft ~-i~2764.u)
0x75.a49d.e269
------------------------------------------------------------------------
### @d
Date
#### @da
Absolute date
Atoms of the odor `@da` represent absolute Urbit dates. Urbit dates
represent 128-bit chronological time, with 2\^64 seconds from the start
of the universe. For example, 2\^127 is 3:30:08 PM on December 5, AD
226. The time of day and/or second fragment is optional. As the last
example shows, BC times are also possible.
##### Forms
`~~[year].[month].[date]..[hour].[minute].[second]..[millisecond]`
Note: the time of day and/or millisecond fragment is optional.
##### Examples
~zod/try=> ~2014.1.1
~2014.1.1
~zod/try=> :type; ~2014.1.1
~2014.1.1
@da
~zod/try=> ~2014.1.1..01.01.01
~2014.1.1..01.01.01
~zod/try=> :type; ~2014.1.1..01.01.01
~2014.1.1..01.01.01
@da
~zod/try=> ~2014.1.1..01.01.01..1234
~2014.1.1..01.01.01..1234
~zod/try=> `@da`(bex 127)
~226.12.5..15.30.08
~zod/try=> `@da`(dec (bex 127))
~226.12.5..15.30.07..ffff.ffff.ffff.ffff
~zod/try=> `@ux`~2013.12.7
0x8000.000d.2140.7280.0000.0000.0000.0000
~zod/try=> `@ux`~2013.12.7..15.30.07
0x8000.000d.2141.4c7f.0000.0000.0000.0000
~zod/try=> `@ux`~2013.12.7..15.30.07..1234
0x8000.000d.2141.4c7f.1234.0000.0000.0000
~zod/try=> `@ux`~2013.12.7..15.30.07..1234
0x8000.000d.2141.4c7f.1234.0000.0000.0000
------------------------------------------------------------------------
#### @dr
Relative date (ie, timespan)
Atoms of the odor `@dr` atoms represent basic time intervals in
milliseconds. There are no `@dr` intervals under a second or over a day
in length.
##### Forms
`~d[day].h[hour]m[minute].s[second]..[fractionals]`
Note: Every measurement is optional, so long as those that are present
are in order. The largest measurement is preceded by a `~`.
##### Examples
~zod/try=> ~d1.h19.m5.s29
~d1.h19.m5.s29
~zod/try=> :type; ~d1.h19.m5.s29
~d1.h19.m5.s29
@dr
~zod/try=> `@dr`(div ~s1 1.000)
~.s0..0041.8937.4bc6.a7ef
~zod/try=> ~d1.h19.m5.s29..0041
~d1.h19.m5.s29..0041
~zod/try=> `@ux`~s1
0x1.0000.0000.0000.0000
~zod/try=> `@ux`~m1
0x3c.0000.0000.0000.0000
~zod/try=> `@dr`(div ~d1 5)
~h4.m48
~zod/try=> (div ~m1 ~s1)
60
~zod/try=> (div ~h1 ~m1)
60
~zod/try=> (div ~h1 ~s1)
3.600
~zod/try=> (div ~d1 ~h1)
24
~zod/try=> `@da`(add ~2013.11.30 ~d1)
~2013.12.1
------------------------------------------------------------------------
#### @f
Loobean(inverse boolean)
Atoms of the odor `@f` represent loobeans, where `0` is yes and `1` is
no. Loobeans are often represented in their cubic and runic forms shown
below.
##### Forms
`0`, `1` as numbers. `%.y`, `%.n` as [`%cube`]()s. `&`, `|` as short
forms.
##### Examples
~zod/try=> `@ud`.y
0
~zod/try=> :type; .y
%.y
{%.y %.n}
~zod/try=> `@ud`.n
1
~zod/try=> .y
%.y
~zod/try=> &
%.y
~zod/try=> |
%.n
------------------------------------------------------------------------
### @n
Nil
Atoms of the odor `@n` indicate an absence of information, as in a list
terminator. The only value is `~`, which is just `0`.
~zod/try=> :type; ~
~
%~
~zod/try=> `@ud`%~
0
~zod/try=> `@ud`~
0
------------------------------------------------------------------------
### @p
Phonemic base
Atoms of `@p` are primarily used to represent ships names, but they can
be used to optimize any short number for memorability. For example, it
is great for checksums.
##### Forms
`~[phonemic]`
Every syllable is a byte. Pairs of two bytes are separated by `-`, and
phrases of four pairs are separated by `--`.
~zod/try=> ~pasnut
~pasnut
~zod/try=> :type; ~pasnut
~pasnut
@p
~zod/try=> `@p`0x4321
~pasnut
~zod/try=> `@p`0x8765.4321
~famsyr-dirwes
~zod/try=> `@p`0x8766.4321
~lidlug-maprec
~zod/try=> `@p`(shaf %foo %bar)
~ralnyl-panned-tinmul-winpex--togtux-ralsem-lanrus-pagrup
------------------------------------------------------------------------
### @r
IEEE floating-points
Hoon does not yet support floating point, so these syntaxes don't work
yet. But the syntax for a single-precision float is the normal English
syntax, with a `.` prefix:
------------------------------------------------------------------------
### @s
Signed integer, sign bit low
Without finite-sized integers, the sign extension trick obviously does
not work. A signed integer in Hoon is a different way to use atoms than
an unsigned integer; even for positive numbers, the signed integer
cannot equal the unsigned.
The prefix for a negative signed integer is a single `-` before the
unsigned syntax. The prefix for a positive signed integer is `--`. The
least significant represents the sign. The representation is similar to
a folded number line.
#### @sb
Signed binary
Atoms of the odor `@sb` represent signed binary numbers.
#### Forms
`-0b[negative_binary]` `--0b[postive_binary]`
#### Examples
~zod/try=> :type; -0b1
-0b1
@sb
~zod/try=> `@sd`-0b1
-1
~zod/try=> `@sd`--0b1
--1
~zod/try=> `@sd`--0b11
--3
~zod/try=> `@sb`(sum:si -0b10 -0b10)
-0b100
------------------------------------------------------------------------
#### @sd
Signed decimal
Atoms of odor `@sd` represent signed decimal numbers.
#### Forms
`-[negative[decimal]()]` `--[postive_[decimal]()]`
#### Examples
~zod/try=> -234
-234
~zod/try=> :type; -234
-234
@sd
~zod/try=> :type; --234
--234
@sd
~zod/try=> (sum:si -234 --234)
--0
------------------------------------------------------------------------
#### @sv
Signed base32
Atoms of odor `@sv` represent signed base32 numbers.
##### Forms
`-0v[negative_base32]` The digits are, in order, `0-9`, `a-v`.
`--0v[positive_base32]`
##### Examples
~zod/try=> -0vv
-0vv
~zod/try=> :type; -0vv
-0vv
@sv
~zod/try=> --0vb
--0vb
~zod/try=> `@sd`-0vv
-31
~zod/try=> `@sd`--0vb
--11
~zod/try=> `@sd`(sum:si -0vv --0vb)
-20
------------------------------------------------------------------------
#### @sw
Signed base64
Atoms of odor `@sw` represent base64 numbers.
##### Forms
`-0w[negative_base64]` The digits are, in order, `0-9`, `a-z`,
`A-Z`,`-`, and `~`. `--0w[positive_base64]` The digits are, in order,
`0-9`
##### Examples
~zod/try=> -0w--
-0w--
~zod/try=> :type; -0w--
-0w--
@sw
~zod/try=> `@sd`(sum:si -0w-A -0w--)
-8.034
#### @sx
Signed hexadecimal
Atoms of odor `@sx` represent signed hexadecimal numbers.
##### Forms
`-[negative_hexadecimal]` `--[positive_hexadecimal]`
##### Examples
~~zod/try=> -0x0
--0x0
~zod/try=> `@sd`--0x17
--23
~zod/try=> `@ux`(bex 20)
0x10.0000
~zod/try=> 0x10. 0000
0x10.0000
~zod/try=> `@sd`(sum:si --0x17 -0x0)
--23
~zod/try=> `@sd`(sum:si --0x17 -0xa)
--13
------------------------------------------------------------------------
### @t
UTF-8 text (cord)
Atoms of the odor `@t` represent a
[cord](http://en.wikipedia.org/wiki/Rope_data_structure), sequence of
UTF-8 bytes, LSB first. It is sometimes called a cord.
##### Forms
`~~[text]` `'[text]'`
##### Examples
~zod/try=> ~~foo
'foo'
~zod/try=> :type; 'foo'
'foo'
@t
~zod/try=> :type; ~~foo
'foo'
@t
------------------------------------------------------------------------
#### @ta
ASCII text (span)
Atoms of the odor `@ta` represent the ASCII text subset used in hoon
literals: `a-z`, `0-9`, `~`, `-`, `.`, `_`.
##### Forms
`~.[text]` There are no escape sequences.
##### Examples
~zod/try=> ~..asdf
~..asdf
~zod/try=> :type; ~.asdf
~.asdf
@ta
~zod/try=> `@t`~.asdf
'asdf'
------------------------------------------------------------------------
#### @tas
ASCII symbol (term)
Atoms of `@tas` represent [`++term`]()s, the most exclusive text odor.
The only characters permitted are lowercase ASCII, except as the first
or last character, and 0-9, except as the first character.
##### Forms
`%[text]` This means a term is always [cubical]().
##### Examples
~zod/try=> %dead-fish9
%dead-fish9
~zod/try=> -:!>(%dead-fish9)
[%cube p=271.101.667.197.767.630.546.276 q=[%atom p=%tas]]
------------------------------------------------------------------------
### @u
Unsigned integer
------------------------------------------------------------------------
#### @ub
Unsigned binary
Atoms of the odor `@ub` represent unsigned binary numbers.
#### Forms
`0b[number]` Numbers are least-significant bit first.
##### Examples
~zod/try=> `@`0b1
1
~zod/try=> :type; 0b1
0b1
@ub
~zod/try=> `@`0b10
2
~zod/try=> `@`0b100
4
------------------------------------------------------------------------
#### @ud
Unsigned decimal
Atoms of `@ud` represent unsigned decimal numbers. It is the default
print format for both `@u` and and `@u`, namely unsigned numbers with no
printing preference, as well as opaque atoms.
##### Forms
Numbers of more than three digits must be delimited by `.`s. Whitespace
and linebreaks can appear between the dot and the next group.
~zod/try=> 0
0
~zod/try=> 19
19
~zod/try=> :type; 19
19
@ud
~zod/try=> 1.024
1.024
~zod/try=> 65.536
65.536
~zod/try=> (bex 20)
1.048.576
------------------------------------------------------------------------
#### @uv
Unsigned base32
Atoms of the odor `@uv` represent unsigned base64 numbers.
##### Forms
`0v[number]` The digits are, in order, `0-9`, `a-v`.
##### Examples
~zod/try=> `@ud`0vv
31
~zod/try=> :type; 0vv
0vv
@uv
~zod/try=> `@ud`(add 0vv 0v9)
40
------------------------------------------------------------------------
#### @uw
Unsigned base64
##### Forms
`ow[number]` The digits are, in order, `0-9`, `a-z`, `A-Z`,`-`, and `~`.
##### Examples
~zod/try=> 0w~
0w~
~zod/try=> :type; 0w~
0w~
@uw
~zod/try=> `@uv`(add 0w~ 0wZ)
0v3s
~zod/try=> `@ud``@uv`(add 0w~ 0wZ)
124
------------------------------------------------------------------------
#### @ux
Unsigned hexadecimal
Atoms of the odor `@ux` represent hexadecimal numbers.
##### Forms
`0x`number. Numbers with more than four digits must be delimited by
`.`s. Hex digits are lowercase only.
~zod/try=> 0x0
0x0
~zod/try=> :type; 0x0
0x0
@ux
~zod/try=> `@ud`0x17
23
~zod/try=> `@ux`(bex 20)
0x10.0000
~zod/try=> 0x10. 0000
0x10.0000
------------------------------------------------------------------------

View File

@ -1,68 +0,0 @@
Pronunciation
=============
Overview
--------
Hoon is a reserved-word-free
language - any text in the program is part of the program.
We use so many of these ASCII glyphs that we like to be able
to read them out loud. A language is meant to be _said_. The
squiggles have conventional names, sort of, some of them easy to
say, others not so much. So we've renamed them:
ace space
bar |
bas \
buc $
cab _
cen %
col :
com ,
doq "
dot .
fas /
gal <
gar >
hax #
hep -
kel {
ker }
ket ^
lus +
pam &
pat @
pel (
per )
sel [
sem ;
ser ]
sig ~
soq '
tar *
tec `
tis =
wut ?
zap !
Memorizing these names seems like a burden, but it actually makes
communicating about hoon code a lot faster and easier. `bartis`
sounds a lot better than 'bar equals'.
To pronounce a rune, concatenate the glyph names, stressing the
first syllable and softening the second vowel into a "schwa."
Hence, to say `~.`, say "sigdot." To say `|=`, say "bartis."
Which has an inevitable tendency to turn into "barts" - a sin
to be encouraged.
There are a few runes with irregular special pronunciations:
-- hephep phep
+- lushep slep
++ luslus slus
== tistis stet
+< lusgal glus
+> lusgar gras
-< hepgal gelp
-> hepgar garp

View File

@ -1,132 +0,0 @@
<div class="short">
Runes
=====
In Hoon there are no reserved words. Instead, [`++twigs`]() (abstract
syntax trees), are formed using a diagraph of two ASCII symbols, which
is called a rune.
Runes are loosely divided into categories by their first character. To
find documentation on each individual category, follow these links:
<list></list>
<search/>
</div>
------------------------------------------------------------------------
Introduction
------------
For example, the rune `?:`, pronounced "wutcol", is a rune that accepts
three `++twig` expressions to form an "if-then-else statement," where
`p` is the predicate, `q` is the "then" statement, and `r` is the "else"
statement:
[%wtcl p=twig q=twig r=twig]
In a program, it is used like so:
++ add
|= [a=@ b=@]
^- @
?: =(0 a) b
$(a (dec a), b +(b))
Here the `=(0 a)` is `p`, the `b` is `q`, and the bottom line is the
`r`.
There are several benefits to using runes in lieu of reserved words.
First, it prevents the programmer from accidentally misusing a reserved
word as a variable name, which also allows her to be sure that any word
in her progam is an identifier. Next, as the first ASCII symbol of the
rune digraphs bears semantic significance, the programmer can look at
any rune and immediately have a basic, intuitive understanding as to
what it does.
Next, rune syntax addresses several issues that arise in other
languages. First, it produces cleaner, less verbose code that
conveniently flows downward. To highlight the verbosity Hoon avoids by
implementing runes, here is the C equivalent of the `++add` source code
printed above:
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))
}
}
What is more, Hoon solves two problems that arise in functional
programming languages with very deep expression trees: first, the
collection of huge piles of closing parens at the end of large blocks;
and second, the fact that the depth of expression trees are thus bounded
by the width of the text box, as subexpressions tend to be indented.
Some languages solve the bracket-terminator problem by parsing
whitespace in order to use indentation to express tree depth:
?:
&
47
52
While this is actually valid Hoon, it does not solve the width problem.
To address this problem, most Hoon `++twigs` have a short, fixed
fan-out. Thus, the parser does not need significant whitespace nor a
terminator to determine how many twigs follow a `?:`--it already knows
that the answer is three. A smart parser allows the Hoon programmer to
format her code using a [backstep pattern]() that allows her to descend
into a deep tree without losing right margin.
Lastly, but perhaps most significantly, code is meant to be seen, and
not read. Anyone who has even slight experience coding Hoon will tell
you that they can understand and connect with properly formatted Hoon
code on a deeper, more intuitive level that cannot be explained but must
be experienced. One doesn't read `++add`, she sees it.
Names and Categories
--------------------
While the second glyph in a rune means little or nothing, the first
defines a rough semantic category:
| bar Core construction
$ buc Tile construction
% cen Invocations
: col Tuple construction
. dot Nock operations
# hax Pretty printing
^ ket Type conversions
; sem Composers (and XML generators)
~ sig Hints
= tis Subject modifiers
? wut Conditionals, booleans, and tests
! zap Special operations
As shown above, each glyph has its own monosyllabic name, designed to be
pronounced quickly in combination with another glyph to form a rune
name. As languages are often read-aloud, this saves the programmer from
having to say "dollar sign, question mark"--"bucwut" is much more
compact.
Irregular pronuncations
-----------------------
To avoid a few tongue-twisters, some runes have irregular pronunciations
that should be noted:
-- hephep phep
+- lushep slep
++ luslus slus
== tistis stet
Note: these runes are not members of any of the categories above, but
are mostly used to....

View File

@ -1,49 +0,0 @@
<div class="short">
`buc $ %buc`
============
Tile construction
-----------------
The `$` runes construct [`++tile`]()s. [`++tile`]()s are one of our
primary building blocks in hoon, they define how we reduce our ASTs into
well typed nouns that nock can compute. You can think of a [`++tile`]()
sort of like a typeclass in Haskell.
</div>
#### Forks
##### [`++tile`]()s that can be one of multiple cases.
[`$?`]() Non-empty list of cases.
[`$|`]() Fork between atom and cell.
[`$&`]() Fork between cells whose head is a cell and cells whose head is
an atom.
<hr></hr>
#### Tuples
[`$:`]() Unlabelled arrays.
[`$=`]() Tuple with [`++face`]()s.
<hr> </hr>
#### Reductions
##### Important convenience methods for working with tiles, and are very broadly used.
[`$*`]() [bunt]()
[`$,`]() [clam]()
[`$@`]() [whip]()
<hr></hr>
<kids></kids>

View File

@ -1,52 +0,0 @@
bucbar `$|` %bcbr
=================
<div class="short">
Atom or cell
------------
`$|` is a tile rune that produces a [`%reed`](), a tile whose [icon]()
is a [fork]() between two nouns: an [atom]() of `tile` `p` and a cell of
`tile` `q`. `$|` is similar to [`$?`](), but is more strict in that in
only contains one atom tile and one cell tile.
</div>
<hr>
</hr>
### Produces
[`Tile`](): `[%reed p=tile q=tile]`
### Sample
`p` is a [`tile`]() `q` is a [`tile`]()
### Tall form
$| p
q
### Wide form
$|(p q)
### Irregular form
None
### Examples
~zod/try=> *$|(~ [~ u=@])
~
~zod/try=> :type; *$|(~ [~ u=@])
~
u(@)
++ list |* a=_,* :: null-terminated list
$|(~ [i=a t=(list a)]) ::
In `++list`, `$|` specifies that every element in a noun that can be
cast to a `++list` is either the atom `~` or the cell
`[i=a t=(list a)]`.

View File

@ -1,43 +0,0 @@
buccab `$_` %bccb
==========================
Default value
`$_` produces a tile-by-example, called a `%weed`. A `%weed` contains
the twig used to make the example.
Produces
--------
Tile: `[%weed p=twig]`
Sample
------
`p` is a [tile]().
Tall form
---------
$_ p
Wide form
---------
$_(p)
Irregular form
--------------
_p
Examples
--------
~zod/try=> *_12
12
~zod/try=> :type; *_12
12
@ud
~zod/try=> ^-(_(add 2 2) 'a')
97

View File

@ -1,44 +0,0 @@
buccol `$:` %bccl
==========================
Tile autocons
`$:` is a tile rune that constructs the tile of a tuple from a tuple of
tiles.
Produces
--------
[Tile](): `[p=tile q=tile]`
Sample
------
`p` is a [tile](). `q` is a [tile]().
Tall form
---------
$: p
q
==
Wide form
---------
$:(p q)
Irregular form
--------------
[p q]
Examples
--------
~zod/try=> *[1 2]
[%1 %2]
~zod/try=> (,[1 2] "ham")
[%1 %2]
~zod/try=> (,[@ 2] "ham")
[104 %2]

View File

@ -1,61 +0,0 @@
buccom `$,` %bccm
==========================
Normalizing gate, `%clam`
`$,` is a synthetic rune that produces a `%leaf`, a normalizing gate or
[clam]() for `p`. `$,` is used to ensure an input value fits a certain
type: if it does match, the value is produced. If it doesn't, the
default value for the desired type is produced.
Produces
--------
[Twig](): `[%bccm p=tile]`
Sample
------
`p` is a [tile]()
Tall form
---------
$, p
Wide form
---------
None
Irregular form
--------------
,p
Examples
--------
++ cord ,@t :: text atom (UTF-8)
In `++cord`, `,` creates a gate that validates atoms of the odor
[`@t`]().
~zod/try=> (,[1 2] "ham")
[%1 %2]
~zod/try=> (,[@ 2] "ham")
[104 %2]
~zod/try=> (,~ %foo)
~
~zod/try=> (,~ [%ba %r])
~
~zod/try=> (,$%([%a @] [%b ^]) [%b 5])
[%b 0 0]
~zod/try=> (,$%([%a @] [%b ^]) [%a 5])
[%a 5]
~zod/try=> (,$%([%a @] [%b ^]) [%a 6 7])
[%a 0]
~zod/try=> (,$%([%a @] [%b ^]) [%b ~])
[%b 0 0]
~zod/try=> (,$%([%a @] [%b ^]) [%b "ame"])
[%b 97 [109 101 0]]

View File

@ -1,64 +0,0 @@
buccen `$%` %bccn
==========================
Tagged union
`$%` is a tile rune that produces a [`%kelp`](), the tile of the
discriminated union. `$%` takes a list of lines which are labeled cases,
called fronds, closed by `==`. Commonly used for pattern matching.
Produces
--------
[Twig](): `[%kelp p=[i=line t=(list line)]]`
Sample
------
`p` is a [`++list`]() of [`++line`]()s.
Tall form
---------
$% p
q
==
Wide form
---------
None
Irregular form
--------------
None
Examples
--------
~zod/try=> $%([%& @p] [%| @t])
<1.dhe [* @n <246.qra 41.uuw 374.glo 100.rip 1.ypj %164>]>
~zod/try=> *$%([%& @p] [%| @t])
[%.y ~zod]
~zod/try=> :type; *$%([%& @p] [%| @t])
[%.y ~zod]
{[%.y @p] [%.n @t]}
~zod/try=> :type; *(each ,@p ,@t)
[%.y p=~zod]
{[%.y p=@p] [%.n p=@t]}
~zod/try=> $%(~ [%a 1])
~ <syntax error at [1 13]>
~zod/try=> $%([%~ ~] [%a 1])
<1.yck [* @n <246.qra 41.uuw 374.glo 100.rip 1.ypj %164>]>
~zod/try=> *$%([%~ ~] [%a 1])
[~ ~]
++ foot $% [%ash p=twig] :: dry, geometric
[%elm p=twig] :: wet, generic
[%oak ~] :: XX not used
[%yew p=(map term foot)] :: XX not used
==
In `++foot`, `$%` creates a list of possible cases. That is, a `++foot`
can be either `%ash`, `%elm`, `%oak` or `%yew`.

View File

@ -1,49 +0,0 @@
bucket `$^` %bckt
==========================
Normalizing gate, `%herb`
`$^`, is a tile rune that declares an [`%herb`](). An `%herb` is a gate,
accepting a sample of \* and normalizing it as you choose. If you use a
twig as a tile, it's treated as an herb.
Produces
--------
Tile: `[%herb p=twig]`
Sample
------
`p` is a [twig]().
Tall form
---------
$^ p
Wide form
---------
$^(p)
Irregular form
--------------
None
Examples
--------
~zod/try=> *$^(cord)
''
~zod/try=> *$^(|=(a=* ?^(a a [~ a])))
[~ 0]
~zod/try=> `$^(|=(a=* ?^(a a [~ a])))`1
! type-fail
! exit
~zod/try=> `$^(|=(a=* ?^(a a [~ a])))`[1 2]
[1 2]
~zod/try=> :type; *$^(|=(a=* ?^(a a [~ a])))
[~ 0]
{[%~ @] [* *]}

View File

@ -1,62 +0,0 @@
buclus `$+` %bcls
==========================
Signature
`$+` a tile for a gate which accepts `p` and produces `q`. `$+` is
similar to a function signature. `$+(p q)` is a `%bark` of a `%weed`, or
`$_(|+(p _q))`.
Produces
--------
Tile: `$_(|+(p _q))`
Sample
------
`p` is a [tile]() `q` is a [tile]()
Tall form
---------
$+ p q
Wide form
---------
$+(p q)
Irregular form
--------------
None
Examples
--------
++ sort :: quicksort
~/ %sort
!:
|* [a=(list) b=$+([* *] ?)]
=> .(a ^.(homo a))
|- ^+ a
?~ a ~
%+ weld
$(a (skim t.a |=(c=_i.a (b c i.a))))
^+ t.a
[i.a $(a (skim t.a |=(c=_i.a !(b c i.a))))]
In ++sort, `$+` is a tile for a comparator gate, which takes two nouns
and produces a loobean.
~zod/try=> |=(a=@ (add 2 a))
<1.sgg [a=@ [[@da @ta] [@p @ta] *''] @n <246.qra 41.uuw 374.glo 100.rip 1.ypj %164>]>
~zod/try=> `$+(@ @)`|=(a=@ (add 2 a))
<1|crm [@ [[@da @ta] [@p @ta] *''] @n <246.qra 41.uuw 374.glo 100.rip 1.ypj %164>]>
~zod/try=> +<:|=(a=@ (add 2 a))
a=0
~zod/try=> +<:`$+(@ @)`|=(a=@ (add 2 a))
! -axis.6
! peek-park
! exit

View File

@ -1,39 +0,0 @@
bucpam `$&` %bcpm
==========================
Pair / tag
`$&` is a tile rune that produces a `%bush`. A `%bush` is a tile whose
[icon]() is a [fork]() between two different kinds of nouns: cells whose
head is a cell and cells whose head is an atom `(tile q)`. Its default
value is the value of `q`. One important use of `$&` is to implement
autocons in [`++twig`]() and [`++tile`]().
Produces
--------
[Tile](): `[%bush p=tile q=tile]`
Sample
------
`p` is a [tile]().
Tall form
---------
$& p
q
Wide form
---------
$&(p q)
Irregular form
--------------
None
Examples
--------

View File

@ -1,37 +0,0 @@
bucpat `$@` %bcpt
==========================
Wing to tile
`$@` is a natural rune that whips (normalizes) wing `p` into tile `q`.
Produces
--------
Tile: `[%bcpt p=wing q=tile]`
Sample
------
`p` is a [`++wing`](). `q` is a [tile]().
Tall form
---------
None
Wide form
---------
None
Irregular form
--------------
p@q
Examples
--------
~zod/try=> =+(a=97 a@cord)
'a'

View File

@ -1,38 +0,0 @@
buctar `$*` %bctr
==========================
Default value
`$*`, is a synthetic rune that produces the [bunt]() (default value) of
a tile as a compile-time constant if possible. If it is not possible,
then it is produced dynamically.
Produces
--------
[Twig](): `[%bctr p=tile]`
Tall form
---------
$* p
Wide form
---------
$*(p)
Irregular form
--------------
*p
Examples
--------
~zod/try=> *@t
''
~zod/try=> *[@p @ux]
[~zod 0x0]
~zod/try=> *(list ,@)
~

View File

@ -1,53 +0,0 @@
buctis `$=` %bcts
==========================
Face for tile
`$=` is a tile rune that produces a `%bark`. A `%bark` is a tile that
wraps a [face]() around another tile. Used primarily to add faces to
[nouns]().
Produces
--------
[Tile](): `[%bark p=term q=tile]`
Sample
------
`p` is a [term]().
`q` is a [tile]().
Tall form
---------
$= p
q
Wide form
---------
None
Irregular form
--------------
None
Examples
--------
`a=*` parses as `[%bark %a %noun]`.
~zod/try=> *$=(a @)
a=0
~zod/try=> :type; *$=(a @)
a=0
a=@
~zod/try=> :type; *a=@
a=0
a=@
~zod/try=> :type; *a=[1 2]
a=[%1 %2]
a=[%1 %2]

View File

@ -1,48 +0,0 @@
bucwut `$?` %bcwt
==========================
Fork
`$?` produces a fork, called a `%fern`. A `%fern` is a non-empty list of
cases.
Produces
--------
[Tile](): `[%fern p=[i=tile t=(list tile)]]`.
Sample
------
`p` is a [list]() of [tiles]().
Tall form
---------
$? p
q
==
Wide form
---------
None
Irregular form
--------------
?(p q)
Examples
--------
++ base ?([%atom p=odor] %noun %cell %bean %null) :: axils, @ * ^ ? ~
`++base`, `?` (the irregular form of `$?`) specifies a list of
orthoganal cases for the `%axil` tile.
~zod/try=> *?(%a %b %c)
%a
~zod/try=> :type; *?(%a %b %c)
%a
{%a %b %c}

View File

@ -1,40 +0,0 @@
buczap `$!` %bczp
==========================
Axil bunt
`$!` is an synthetic internal twig that produces the [bunt]() (default
value) for `[%axil p]`.
Produces
--------
[Twig](): `[%bczp p=base]`
Sample
------
`p` is a [base]() [axil]() type.
Tall form
---------
None
Wide form
---------
None
Irregular form
--------------
None
Examples
--------
~zod/try=> (ream '~')
[%bczp p=%null]
~zod/try=> (make '~')
[%1 p=0]

View File

@ -1,47 +0,0 @@
<div class="short">
`bar | %bar`
============
Core construction
-----------------
The `|` runes construct [core]()s. In the broadest case you can think of
a core as similar to an object with named properties that can contain
either functions or data.
The `|` runes accept an associative array of names ([++term]()) to
([++foot]()), each pair of which are called an [++arm](), producing one
of the three basic categories of core.
</div>
#### The natural, generic core:
[`|%`]() Generic core, with [++arms] generally containing [++twig]()s
<hr></hr>
#### Doors, generic core with a sample:
##### Gates:
Cores with one arm [`$`], the empty name and which takes a sample
`p`. The closest thing in Hoon to a function.
[`|=`]() [`dry`]() gate, where the [sample]() is typechecked at compile
time. [`|*`]() [`wet`]() gate, where the sample is typechecked at
runtime against its product type.
##### Traps:
Traps reduce to a `|%` with one arm `$`, the empty name. A trap is just
some computation that has been put inside of a wrapper so that it may be
passed around.
[`|.`]() Generic trap. [`|-`]() Trap automatically [kick]ed (called)
after construction.
<hr></hr>
<kids></kids>

View File

@ -1,118 +0,0 @@
barcab, `|_`, %brcb
============================
Door: core with sample
`|_` is a synthetic rune that produces a [`%gold`]() [door]() with
sample `p` and [arms]() `q`. The list must be closed with a `--`.
`|_` is similar to `|%`, but defines a sample for the set of arms it
contains. Moreover, `|_` only accepts [dry or `%elm`]() arms. Put
simply, type checking on these arms is performed on the input before
computation. For more on variance, see the [glossary entry]() and the
examples below.
See also
--------
[barcen, `|%`, `%brcn`]() [barfas, `|/`, `%brfs`]()
Produces
--------
Twig: `[%brcb p=tile q=(map term foot)]`
Sample
------
`p` is a [tile](). `q` is a [`map`]() with [`++term`]() keys and
[`++foot`]() values.
Tall form
---------
|_ p
++ p.n.q
q.n.q
--
Wide form
---------
None
Irregular form
--------------
None
Examples
--------
/~zod/try=> =mol
|_ a=@ud
++ succ +(a)
++ prev (dec a)
--
/~zod/try=> ~(succ mol 1)
2
/~zod/try=> ~(succ mol ~(succ mol ~(prev mol 5)))
6
In this example we create a door `mol` that operates on a [`@ud`](),
`a`. We add two arms to our door, `++succ` and `++prev`, and invoke them
with the irregular form of [`%~`](). Doors are commonly invoked with
`%~`, irregular form `~(arm door sample)`, which replaces the door's
sample and pulls the specified arm.
/~zod/try=> =kom
|_ a=(list)
++ hed -.a
++ tal +.a
--
new var %kom
/~zod/try=> =kot
|/ a=(list)
+- hed -.a
+- tal +.a
--
new var %kot
/~zod/try=> ~(tal kom "abc")
t=~[98 99]
/~zod/try=> ~(tal kot "abc")
t="bc"
/~zod/try=> ~(tal kot [1 2 3 ~])
[2 3 ~]
/~zod/try=> ~(tal kom [1 2 3 ~])
t=~[2 3]
Here we're demonstrating the difference between `|_` and `|/`. We create
a nearly identical door using both runes, each with an arm that produces
the tail of the sample, `a`. You can see that our wet gates use the
sample as a tile to produce well-typed output.
++ ne
|_ tig=@
++ d (add tig '0')
++ x ?:((gte tig 10) (add tig 87) d)
++ v ?:((gte tig 10) (add tig 87) d)
++ w ?:(=(tig 63) '~' ?:(=(tig 62) '-' ?:((gte tig 36) (add tig 29) x)))
--
::
`++ne` is used to print a single digit in base 10, 16, 32, or 64 and is
a part of the hoon standard library. You can find it in `hoon.hoon`.
`|_` is very commonly used throughout our standard library for groups of
arms who all take the same sample.
~zod/try=> ~(x ne 12)
99
~zod/try=> `@t`~(x ne 12)
'c'
~zod/try=> `@ux`12
0xc
Here we put `++ne` to work a bit. Our first call renders 12 in base 16.
Since `99` is within the ASCII character range, we can cast it to a
[`@t`]() and get `'c'`. Conveniently, casting `12` to a [`@ux`]()
results in `0xc`.

View File

@ -1,135 +0,0 @@
barcen, `|%`, %brcn
============================
Build Core
`|%` is a natural rune that produces a [core](). `|%` takes a list of
[arm]()s . The list must be closed with a `--`.
The product of `|%` is similar to an object with named properties
containing either functions or data. A `|%` accepts both [dry or
`%elm`]() and [wet or `%ash`]() arms. For more about variance, see the
[glossary]().
See also
--------
[barcab, `|_`, `%brcb`]() [barfas, `|/`, `%brfs`]()
Produces
--------
Twig: `[%brcn p=(map term foot)]`
Sample
------
`p` is a [`map`]() with [`++term`]() keys and [`++foot`]() values, which
are called arms.
Tall form
---------
|%
++ p.n.q
q.n.q
+- p.n.l.q
q.n.l.q
--
Wide form
---------
None
Irregular form
--------------
None
Examples
--------
/~zod/try=>
=a |%
++ n 100
++ g |= b=@
(add b n)
--
new var %a
/~zod/try=>
(g.a 1)
101
Here we create a core with two arms `n`, a constant and `g`, a simple
function. `g` adds our constant `n` to whatever is passed to it.
/~zod/try=>
=a |%
++ l |%
++ r 100
++ s 4
--
++ g |= b=@
(div (add b r:l) s:l)
--
changed %a
/~zod/try=>
(g.a 4)
26
Extending our previous example a bit, we nest a core inside our arm `l`
and make our [gate]() `g` a bit more complicated. `g` now computes the
sum of its argument and the arm `r` inside `l`, and divides that by `s`
inside `l`.
++ yo
|% ++ cet 36.524 :: (add 24 (mul 100 365))
++ day 86.400 :: (mul 24 hor)
++ era 146.097 :: (add 1 (mul 4 cet))
++ hor 3.600 :: (mul 60 mit)
++ jes 106.751.991.084.417 :: (mul 730.692.561 era)
++ mit 60
++ moh `(list ,@ud)`[31 28 31 30 31 30 31 31 30 31 30 31 ~]
++ moy `(list ,@ud)`[31 29 31 30 31 30 31 31 30 31 30 31 ~]
++ qad 126.144.001 :: (add 1 (mul 4 yer))
++ yer 31.536.000 :: (mul 365 day)
--
[`++yo`](), found in `hoon.hoon`, uses `|%` to create a core whose arms
contain constant data for calculating time. As the following examples
shows, `|%` is also used to encapsulate arms that perform calculations.
++ si :: signed integer
|%
++ abs |=(a=@s (add (end 0 1 a) (rsh 0 1 a)))
++ dif |=([a=@s b=@s] (sum a (new !(syn b) (abs b))))
++ dul |=([a=@s b=@] =+(c=(old a) ?:(-.c (mod +.c b) (sub b +.c))))
++ fra |= [a=@s b=@s]
(new =(0 (mix (syn a) (syn b))) (div (abs a) (abs b)))
++ new |=([a=? b=@] `@s`?:(a (mul 2 b) ?:(=(0 b) 0 +((mul 2 (dec b))))))
++ old |=(a=@s [(syn a) (abs a)])
++ pro |= [a=@s b=@s]
(new =(0 (mix (syn a) (syn b))) (mul (abs a) (abs b)))
++ rem |=([a=@s b=@s] (dif a (pro b (fra a b))))
++ sum |= [a=@s b=@s]
~| %si-sum
=+ [c=(old a) d=(old b)]
?: -.c
?: -.d
(new & (add +.c +.d))
?: (gte +.c +.d)
(new & (sub +.c +.d))
(new | (sub +.d +.c))
?: -.d
?: (gte +.c +.d)
(new | (sub +.c +.d))
(new & (sub +.d +.c))
(new | (add +.c +.d))
++ sun |=(a=@u (mul 2 a))
++ syn |=(a=@s =(0 (end 0 1 a)))
--
[`++si`](), found in `hoon.hoon`, uses `|%` to create a core whose arms
contain gates used to calculate with signed integers, [`@s`](). In this
case our core is made up entirely of gates.

View File

@ -1,114 +0,0 @@
bardot, `|.`, %brdt
============================
Trap
`|.`, is a synthetic rune that produces a [dry]() [`%gold`]() trap. A
trap is a [`door`]() with one only arm [`$`](), the empty name.
The default action performed on a trap is kicking it by pulling the arm
`$`. `|.` is similar to `|=` with no arguments. You can think of `|.` as
a function that takes no inputs.
See also
--------
barhep, `|-`, %brhp](#brhp) [bartis, `|=`, %brts
Produces
--------
Twig: `[%brdt p=twig]`
Sample
------
`p` is a [`++twig`]().
Tall form
---------
|. p
Wide form
---------
|.(p)
Irregular form
--------------
None
Examples
--------
/~zod/try=>
=a |.(42)
changed %a
/~zod/try=>
a
< 1.yln
[ a
< 2.yqy
[ a
< 3.kii
[ a
< 2.wvx
[ a=<2.kqf 2.hng 250.qyy 41.raw 414.hhh 100.xkc 1.ypj %164>
<2.hng 250.qyy 41.raw 414.hhh 100.xkc 1.ypj %164>
]
>
<2.hng 250.qyy 41.raw 414.hhh 100.xkc 1.ypj %164>
]
>
<2.hng 250.qyy 41.raw 414.hhh 100.xkc 1.ypj %164>
]
>
<2.hng 250.qyy 41.raw 414.hhh 100.xkc 1.ypj %164>
]
>
/~zod/try=>
(a)
42
/~zod/try=>
$:a
42
This is a simple example. We assign a shell variable `a` to be a trap
that simply produces the atom `42`. Printing `a` prints the core and its
context. Calling `a` using `(`, the irregular form of [`%-`](), produces
its value. As does pulling the arm `$` from inside it using `$:a`.
/~zod/try=>
=a 10
changed %a
/~zod/try=>
=b |. (add a 2)
changed %b
/~zod/try=>
(b)
12
In this case we assign a variable `a` to be `10`, and create a trap `b`
to add `2` to it. This is a trivial example, but is meant to show that
traps are useful when you need a gate that only operates on values that
are already in its context.
/~zod/try=>
=loop =+ reps=10
=+ step=0
=+ outp=0
|.
?: =(step reps)
outp
$(outp (add outp 2), step +(step))
changed %loop
/~zod/try=> (loop)
20
Expanding on our previous example, we create a trap with three local
variables, `reps`, `step`, and `outp`. We use a trap to create a loop,
testing each time if `step` is equal to `reps`, if so producing `outp`
otherwise calling our trap again with `outp` replaced with `outp+2`, and
`step` incremented.

View File

@ -1,105 +0,0 @@
barfas, `|/`, %brfs
============================
Door with tile
`|/` is a synthetic rune that produces a [`%gold`]() [door]() with
sample `[%bctr p]` and list of [arm]()s `q`. The list of arms must be
closed with a `--`.
`|/` is similar to `|_` in that it accepts a sample for the set of arms
, but differs in that it accepts [wet or `%ash`]() arms.
See also
--------
[barcab, `|_`, `%brcb`]() [barcen, `|%`, `%brcn`]()
Produces
--------
Twig: `[%brfs p=tile q=(map term foot)]`
Sample
------
`p` is a tile. `q` is a [`map`]() with [`++term`]() keys and
[`++foot`]() values.
Tall form
---------
|/ p
+- p.n.q
q.n.q
--
Wide form
---------
None
Irregular form
--------------
None
Examples
--------
/~zod/try=> =fas |/
a=@
+- two (mul a 2)
+- for (div a 2)
--
new var %fas
/~zod/try=> ~(two fas 2)
4
/~zod/try=> ~(for fas ~(for fas ~(two fas 12)))
6
In this simple example we're creating a door with two arms. One arm
divides our sample by two, the other divides by two.
/~zod/try=> =kom
|_ a=(list)
++ hed -.a
++ tal +.a
--
new var %kom
/~zod/try=> =kot
|/ a=(list)
+- hed -.a
+- tal +.a
--
new var %kot
/~zod/try=> ~(tal kom "abc")
t=~[98 99]
/~zod/try=> ~(tal kot "abc")
t="bc"
/~zod/try=> ~(tal kot [1 2 3 ~])
[2 3 ~]
/~zod/try=> ~(tal kom [1 2 3 ~])
t=~[2 3]
Here we're demonstrating the difference between `|_` and `|/`. We create
a nearly identical door using both runes, each with an arm that produces
the tail of the sample, `a`. You can see that our wet gates use the
sample as a tile to produce well-typed output.
++ by :: map engine
~/ %by
|/ a=(map)
::
+- all
~/ %all
|* b=$+(* ?)
|- ^- ?
?@ a
&
?&((b q.n.a) $(a l.a) $(a r.a))
All of the container engines in `hoon.hoon` use `|/` to set up the tile
for their operations. In `++by`, the map engine, `|/` creates a door
that takes a map that is passed to its arms. See more about using `++by`
in the [library]().

View File

@ -1,78 +0,0 @@
barhep, `|-`, %brhp
============================
Kicked trap
`|-` is a synthetic rune that produces a dry [`%gold`]() trap and
[kicks]() it. You can think of a trap like a 'trap door', since `|-` is
a [`door`]() with only one arm [`$`](), the empty name.
`|-` is different from `|.` in that it is kicked by default. `|-` is
similar to creating and calling an anonymous function and is quite
commonly used for loops or recursion.
See also
--------
bardot, `|.`, %brdt
Produces
--------
Twig: `[%brhp p=twig]`
Sample
------
`p` is a twig
Tall form
---------
|- p
Wide form
---------
|-(p)
Irregular form
--------------
None
Examples
--------
/~zod/try=> |-(42)
42
In contrast to our `|.` example, `|-` is kicked by default, so its
internals are produced immediately.
/~zod/try=> =+ a=`*`~[41 42]
|-
?~ a
~
[-.a %m $(a +.a)]
[41 %m [42 %m ~]]
In this case we use `|-` for one of its most common applications, a
loop. Here we walk across `a` by calling `$` with `a` replaced by `+.a`,
producing a nested tuple.
++ dec :: decrement
~/ %dec
|= a=@
~| %decrement-underflow
?< =(0 a)
=+ b=0
|- ^- @
?: =(a +(b))
b
$(b +(b))
In `++dec`, found in `hoon.hoon`, `|-` creates a trap that contains the
test and looping semantics. Essentially, we count up to `a-1` by
incrementing `b`. Using `|-` inside an existing core as we do here is
its most common use.

View File

@ -1,103 +0,0 @@
barket, `|^`, %brkt
============================
Kicked book
`|^` is a synthetic rune that produces and then kicks a [`%gold`]()
[book]() with sample `p` as a [`%$(p)`](), and a list of [arm]()s `q`.
The list must be closed with a `--`.
`|^` is similar to `|-`, but differs in that it can contain internal
arms.
See also
--------
barhep, `|-`, %brhp](#brhp) [barcab, `|_`, %brcb
Produces
--------
Twig: `[%brkt p=twig q=(map term foot)]`
Sample
------
`p` is a [twig](). `q` is a [`map`]() with [`++term`]() keys and
[`++foot`]() values, which are called arms.
Tall form
---------
|^ p
++ p.n.q
q.n.q
--
Wide form
---------
None
Irregular form
--------------
None
Examples
--------
/~zod/try=> =+ a=21
|^ [square double]
++ square (mul a a)
++ double (mul 2 a)
--
[441 42]
Here `|^` computes a result by calling its helper arms `++square` and
`++double`. Notice that `a` is also in the context. `|^` is most
commonly used inside another gate or core.
++ mum :: mug with murmur3
~/ %mum
|= a=*
|^ (trim ?@(a a (mix $(a -.a) (mix 0x7fff.ffff $(a +.a)))))
++ spec :: standard murmur3
|= [syd=@ key=@]
?> (lte (met 5 syd) 1)
=+ ^= row
|= [a=@ b=@]
(con (end 5 1 (lsh 0 a b)) (rsh 0 (sub 32 a) b))
=+ mow=|=([a=@ b=@] (end 5 1 (mul a b)))
=+ len=(met 5 key)
=- =. goc (mix goc len)
=. goc (mix goc (rsh 4 1 goc))
=. goc (mow goc 0x85eb.ca6b)
=. goc (mix goc (rsh 0 13 goc))
=. goc (mow goc 0xc2b2.ae35)
(mix goc (rsh 4 1 goc))
^= goc
=+ [inx=0 goc=syd]
|- ^- @
?: =(inx len) goc
=+ kop=(cut 5 [inx 1] key)
=. kop (mow kop 0xcc9e.2d51)
=. kop (row 15 kop)
=. kop (mow kop 0x1b87.3593)
=. goc (mix kop goc)
=. goc (row 13 goc)
=. goc (end 5 1 (add 0xe654.6b64 (mul 5 goc)))
$(inx +(inx))
::
++ trim :: 31-bit nonzero
|= key=@
=+ syd=0xcafe.babe
|- ^- @
=+ haz=(spec syd key)
=+ ham=(mix (rsh 0 31 haz) (end 0 31 haz))
?.(=(0 ham) ham $(syd +(syd)))
--
::
[`++mum`]() is a hashing gate, which uses two helper arms to computes
its results. The `|^` at the top performs the computation.

View File

@ -1,63 +0,0 @@
barlus, `|+`, %brls
============================
`%iron` gate
`|+` is a synthetic rune that produces a [dry]() [`%iron`]() [gate]()
with sample [`$*(p)`]() and [arm]()s `q`. `|+` is similar to `|=`, but
differs in that its sample cannot be read. It can be thought of as
similar to a private function.
See also
--------
bartis, `|=`, %brts
Produces
--------
Twig: `[%brls p=tile q=twig]`
Sample
------
`p` is a [tile](). `q` is a [twig]().
Tall form
---------
|+ p
q
Wide form
---------
|+(p q)
Irregular form
--------------
None
Examples
--------
~zod/try=> +<:|+(a=@ a)
! -axis.6
! peek-park
! exit
~zod/try=> +<:|=(a=@ a)
a=0
Here we're trying to read the sample, using `+<` of two different kinds
of gates. With `|+` you can see we cause an error, whereas with `|=` our
default sample is `a=0`.
~zod/try=> %.(20 |+(a=@ a))
20
~zod/try=> %.(20 |=(a=@ a))
20
~zod/try=> %.(20 |+(a=@ (add a 12)))
32
Kicking a `|+` gate, however, is the same as `|=`.

View File

@ -1,73 +0,0 @@
bartar, `|*`, %brtr
============================
Wet gate
`|*` is a synthetic rune that produces a [wet]() [gate]() with sample
[`$*(p)`](), arm `q`. A gate is a core with one arm, [`$`](), the empty
name.
`|*` is similar to a function in the same way that `|=` is, but differs
in that it does type checking at runtime. With `|*`, the product type is
checked to be the same as the input type, rather than the sample tile.
See also
--------
bartis, `|=`, %brts
============================
Produces
--------
Twig: `[%brtr p=tile q=twig]`
Sample
------
`p` is a [tile](). `q` is a [twig]().
Tall form
---------
|* p
q
Wide form
---------
|*(p q)
Irregular form
--------------
None
Examples
--------
~zod/try=> %.('c' |*(a=@ a))
'c'
~zod/try=> %.('c' |=(a=@ a))
99
This is a concise way of understanding the difference between `|*` and
`|=`. We use `%.` in both cases to slam each gate with the sample `'c'`.
`|=` uses its tile `a=@` to cast `'c'` to an atom (`99` is the ASCII
code for `'c'`). `|*` simply ensures that the product type matches the
input sample type.
++ flop :: reverse
~/ %flop
|* a=(list)
=> .(a (homo a))
^+ a
=+ b=`_a`~
|-
?@ a
b
$(a t.a, b [i.a b])
In [`++flop`](), `|*` is used so the type information within the passed
in list is maintained. Without a `|*`, any cords would be cast to nouns
as in our previous example.

View File

@ -1,71 +0,0 @@
bartis, `|=`, %brts
============================
Dry gate
`|=`, is a synthetic rune that produces a [dry]() [`%gold`]() gate with
sample [`$*(p)`](), arm `q`. A gate is a core with one arm, [`$`](), the
empty name. `|=` checks its input sample against its tile, `p`.
`|=` is similar to a function that takes a defined input and produces
the result of some computation. `|=` differs from `|*` in that its
typechecking occurs at compile-time to ensure that all inputs match its
sample tile.
See also
--------
bartar, `|*`, %brtr
============================
Produces
--------
Twig: `[%brts p=tile q=twig]`
Sample
------
`p` is a [tile](). `q` is a [twig]().
Tall form
---------
|= p
q
Wide form
---------
|=(p q)
Irregular form
--------------
None
Examples
--------
~zod/try=> =inc |=(a=@ +(a))
~zod/try=> (inc 20)
21
Here we create a very simple gate that increments its sample, `a`. You
can think of `|=` as similar to a straightforward function that takes
arguments.
++ add :: add
~/ %add
|= [a=@ b=@]
^- @
?: =(0 a)
b
$(a (dec a), b +(b))
In [++add](), from `hoon.hoon`, `|=` creates a gate whose sample takes
two atoms labeled `a` and `b`, and whose arm evaluates an expression
that produces the sum of the atoms by decrementing `a` until it is `0`
and incrementing `b` at each step. Here, `$` is used for recursion,
calling the gate produced by `|=` with `a` replaced by `(dec a)` and `b`
replaced by `+(b)`.

View File

@ -1,54 +0,0 @@
barwut, `|?`, %brwt
============================
`%lead` trap
`|?` is a synthetic rune that produces a dry [`%lead`]() trap. `%lead`
traps are used when we want to pass one core to another core, as both
the sample and context of the core being passed must must be hidden in
order to avoid type conflicts with a core that has a different sample
and context.
Produces
--------
Twig: `[%brwt q=twig]`
Sample
------
`q` is a [twig]().
Tall form
---------
|? p
Wide form
---------
|?(p)
Irregular form
--------------
None
Examples
--------
~zod/try=> |?(20)
< 1?lld
[[[@da @ta] [@p @ta] *''] @n <250.yum 41.int 414.hhh 100.xkc 1.ypj %164>]
>
~zod/try=> +:|?(20)
! -axis.3
! peek-park
! exit
~zod/try=> +:|.(20)
[ [[~2014.10.22..19.39.41..0440 ~.~2014.10.22..19.39.41..0440] [~zod ~.~zod] <||>]
~
<250.yum 41.int 414.hhh 100.xkc 1.ypj %164>
]
A lead core's payload cannot be read or written.

View File

@ -1,44 +0,0 @@
<div class="short">
`col : %col`
============
Tuples
------
The `:` runes construct [tuples]().
There is no natural `:` rune. Instead, all of them derive from the
autocons property of `++twig`, as show below.
++ twig $& [p=twig q=twig]
Namely, a cell of two twigs is a twig producing a cell of the results of
the two original sub-twigs.
The `:` runes produce one of three categories of tuples
</div>
#### Tuples of determinate size:
[`:-`]() Tuples of two elements, `p` and `q`. [`:_`]() Tuples of two
reversed elements, `q` and `p`. Used to ensure vertical code flow.\
[`:+`]() Tuples of three elements `p`, `q`, and `r`. [`:^`]() Tuples of
four elements `p`, `q`, `r`, and `s`.
<hr></hr>
#### Tuples of indeterminate size:
[`:*`]() Tuples of n elements. [`:~`]() Null-terminated tuples of n
elements.
#### Tuples used for interpolation:
[`:/`]() Tuple designed to be interpolated into an XML structure.
<hr></hr>
<kids></kids>

View File

@ -1,56 +0,0 @@
colcab, `:_`, %clcb
============================
Cell, backwards
`:_`, `colcab`, `[%clcb p=twig q=twig]` is a synthetic rune that
produces the cell `[q p]`.
Produces
--------
Twig: `[%clcb p=twig q=twig]`
Sample
------
`p` is a [twig](). `q` is a [twig]().
Tall form
---------
:_ p
q
Wide form
---------
:_(p q)
Irregular form
--------------
undefined
Examples
--------
~zod/try=> :_(1 2)
[2 1]
A simple example. `:_` produces the cell of any two twigs, but in
reverse order.
~zod/try=> `tape`:_(~ 'a')
"a"
Since a [`++tape`]() is a null-terminated list of characters, casting
the result of `:_(~ 'a')` to a `tape` produces `"a"`.
/~zod/try=>
:_ (add 2 2)
|- (div 4 2)
[2 4]
Most commonly `:_` helps to organize code, allowing you to produce a
cell from nested computation.

View File

@ -1,47 +0,0 @@
colfas, `:/`, %clfs
============================
Internal interpolation
`:/`, `colfas`, is a synthetic rune that produces `[%$ [%$ p ~] ~]`,
i.e., `[0 [0 p 0] 0]`.
See also
--------
[`++manx`]() [`%smdq`](#smdq)
Produces
--------
Twig: `[%clfs p=twig]`
Sample
------
`p` is a [twig]()
Tall form
---------
:/ p
Wide form
---------
:/(p)
Irregular form
--------------
undefined
Examples
--------
~zod/try=> :/(20)
[[%~. [%~. 20] ~] ~]
~zod/try=> :/(add 2 2)
[[%~. [%~. 4] ~] ~]
Wraps twig in `[%$ [%$ .] ~]~`, used for interpolation.

View File

@ -1,85 +0,0 @@
colhep, `:-`, %clhp
============================
Cell
`:-`, `colhep`, `[%clhp p=twig q=twig]` is a synthetic rune that
produces the cell `[p q]`.
Produces
--------
Twig: `[%clhp p=twig q=twig]`
Sample
------
`p` is a [twig](). `q` is a [twig]().
Tall form
---------
:- p
q
Wide form
---------
:-(p q)
Irregular form
--------------
[p q]
Examples
--------
~zod/try=> :-(1 2)
[1 2]
~zod/try=> :- 'a'
%b
['a' %b]
This is the most straightforward case of `:-`, producing a cell of
static data in either tall or wide form.
/~zod/try=>
:- (add 2 2)
|- (div 4 2)
[4 2]
Most commonly `:-` helps to organize code, allowing you to produce a
cell from nested computation.
Some obscure `:-` irregular forms.
==================================
Moveme: irregular form doc
### Infix `^`
~zod/main=/app> 1^2^3
[1 2 3]
`a^b` is equivalent to `:- a b`
### Infix `/`
~zod/main=/app> a/1
[%a 1]
~zod/main=/app> a/'twig'
[%a 'twig']
Like `^`, but first item must be a term, and is cubed. Used to construct
paths and fronds.
### Prefix `` ` ``, postfix `~`
~zod/main=/app> ````20
[~ ~ ~ ~ 20]
~zod/main=/app> [42 30]~
[[42 30] ~]
Complimenting each other, these construct pairs with nil in the head and
tail respectively. Multiple postfix `~` do not work for unknown reasons.

View File

@ -1,68 +0,0 @@
colket, `:^`, %clkt
============================
Tuple of four
`:^` is a synthetic rune that produces a cell `[p q r s]`.
Produces
--------
Twig: `[%clkt p=twig q=twig r=twig s=twig]`
Sample
------
`p` is a [twig](). `q` is a [twig](). `r` is a [twig](). `s` is a
[twig]().
Tall form
---------
Kingside:
:^ p
q
r
s
Queenside:
:^ p q
r
s
:^ p q r
s
Wide form
---------
:^(p q r s)
Irregular form
--------------
undefined
Examples
--------
/~zod/try=> :^(1 2 3 4)
[1 2 3 4]
/~zod/try=> :^ 5 6
7
8
[5 6 7 8]
This is the most straightforward case of `:^`, producing a tuple of four
values in both tall and wide form.
/~zod/try=>
:^ (add 2 4) (add 2 6)
|- (div 4 2)
~
[6 8 2 ~]
Most commonly `:^` helps to organize code, allowing you to produce a
cell from nested computation.

View File

@ -1,61 +0,0 @@
collus, `:+`, %clls
============================
Tuple of three
`:+` is a synthetic rune that produces a cell `[p q r]`.
Produces
--------
Twig: `[%clls p=twig q=twig r=twig]`
Sample
------
`p` is a [twig](). `q` is a [twig](). `r` is a [twig]().
Tall form
---------
Kingside:
:+ p
q
r
Queenside:
:+ p q
r
Wide form
---------
:+(p q r)
Irregular form
--------------
undefined
Examples
--------
/~zod/try=> :+ 1
2
3
[1 2 3]
/~zod/try=> :+(%a ~ 'b')
[%a ~ 'b']
This is the most straightforward case of `:+`, producing a tuple of four
values in both tall and wide form.
/~zod/try=>
:+ (add 2 4) (add 2 6)
|- (div 4 2)
[6 8 2]
Most commonly `:+` helps to organize code, allowing you to produce a
cell from nested computation.

View File

@ -1,69 +0,0 @@
colsig, `:~`, %clsg
============================
Null-terminated tuple
`:~`, `colsig`, `[%clsg p=tusk]` is a synthetic rune that produces a
null-terminated tuple.
Produces
--------
Twig: `[%clsg p=tusk]`
Sample
------
`p` is a [`++tusk`](), a list of twigs.
Tall form
---------
:~ i.p
i.t.p
i.t.t.p
==
Wide form
---------
:~(i.p i.t.p i.t.t.p)
Irregular form
--------------
~[i.p i.t.p i.t.t.p]
Examples
--------
/~zod/try=> :~(5 3 4 2 1)
[5 3 4 2 1 ~]
/~zod/try=> ~[5 3 4 2 1]
[5 3 4 2 1 ~]
/~zod/try=> :~ 5
3
4
2
1
==
[5 3 4 2 1 ~]
This is the most straightforward case of `:~`, producing a tuple of four
values in wide, irregular and tall form.
/~zod/try=> %- flop
%- limo
:~ 5
3
4
2
1
==
~[1 2 4 3 5]
In this example we use `%-` to pass the results of our previous example
to [`++limo`](), which creates a [`++list`](), and [`++flop`](), which
reverses its order. This example shows how `:~` is commonly useful.
Null-terminated tuples are easily converted to lists, which are
frequently encountered in hoon.

View File

@ -1,57 +0,0 @@
coltar, `:*`, %cltr
============================
Tuple
`:*`, `coltar`, `[%cltr p=tusk]` is a synthetic rune that produces a
tuple.
Produces
--------
Twig: `[%cltr p=tusk]`
Sample
------
`p` is a [`++tusk`](), a list of twigs.
Tall form
---------
:~ i.p
i.t.p
i.t.t.p
==
Wide form
---------
:*(i.p i.t.p i.t.t.p)
Irregular form
--------------
[i.p i.t.p i.t.t.p]
Examples
--------
/~zod/try=> :*(5 3 4 1 4 9 0 ~ 'a')
[5 3 4 1 4 9 0 ~ 'a']
/~zod/try=> [5 3 4 1 4 9 0 ~ 'a']
[5 3 4 1 4 9 0 ~ 'a']
/~zod/try=> :* 5
3
4
1
4
9
0
~
'a'
==
[5 3 4 1 4 9 0 ~ 'a']
This is the most straightforward case of `:*`, producing a tuple of n
values in wide, irregular and tall form.

View File

@ -1,41 +0,0 @@
<div class="short">
`cen % %cen`
============
Pulling
-------
The `%` runes [pull]() [`++arms`]() and [`++wings`]() from the
[subject](), often modifying their values. The `%` runes are similar to
function calls, or execution tools. We use them to either compute some
code with changes in the subject, or produce the output from a core.
There are two categories of `%` runes.
</div>
#### Pull with changes:
[`%=`]() The natural `%` rune. Evaluates `p` with the changes specified
in `q`.
[`%_`]() Evaluates `p` with the changes specified in `q`, then
casts the product back to the type of `p`.
[`%*`]() Evaluates `p` from a [door]() `q` with changes `r`.Terminated by `==`.
<hr></hr>
### Pull the empty arm `$`, similar to calling a function:
[`%-`]() [slams]() a core with one argument.
[`%+`]() slams a core with two arguments.
[`%^`]() slams a core with three arguments.
<hr></hr>
<kids></kids>

View File

@ -1,74 +0,0 @@
cencab, `%_`, %cncb
============================
Evaluate with changes, cast
`%_` is a synthetic rune that evaluates `p` with the changes specified
in `q`, then casts the product back to the type of `p`. `%_` is used to
change a batch of [`++wing`]()s all at once, ensuring that the resulting
product is type checked.
See also
--------
[`%=`](#cnts) is similar, but without type-checking.
Produces
--------
Twig: `[%cncb p=wing q=tram]`
Sample
------
`p` is a [`++wing`](), a list of [`++limb`]()s. `q` is a [`++tram`](), a
list of [`++wing`]()s and twigs.
Tall form
---------
%_ p
p.i.q q.i.q
p.i.t.q q.i.t.q
==
Wide form
---------
%_(p p.i.q q.i.q, p.i.t.q q.i.t.q)
Irregular form
--------------
None
Examples
--------
/~zod/try=> =a [b=1 c=2 d=3]
new var %a
/~zod/try=> %_(a b (add 3 b.a), c (add 3 c.a), d (add 3 d.a))
[b=4 c=5 d=6]
Here we're using `%_` to add 3 to all of the values inside of our shell
variable `a`.
/~zod/try=> =a [b='odors' c='twigs' d='tiles']
changed %a
/~zod/try=> %_(a b c.a, c d.a, d b.a)
[b='twigs' c='tiles' d='odors']
In this case we're using `%_` to swap the values of the faces in `a`.
/~zod/try=> =+ a=1
=+ z=|=(b=@ (add a b))
(z 1)
2
/~zod/try=> =+ a=1
=+ z=|=(b=@ (add a b))
(%_(z a 100) 1)
101
At first we set up a simple gate `z` with a variable, `a` in its
context. Subsequently we use `%_` to change the value of `a` within the
context of `z` and compute the output again.

View File

@ -1,55 +0,0 @@
cencol, `%:`, %cncl
============================
Slam, one argument
`%:` is a synthetic rune that that [pull]()s [`$`]() from the [door]()
`p` with its sample set to `q`. `%:` in the most common case simply
[slam]()s `p` with `q`, similar to a function call with one argument.
Unlike its close relative `%-`, `%:` is designed for [gate]()s who take
a single value as their sample.
Produces
--------
Twig: `[%cncl p=twig q=twig]`
Sample
------
`p` is a [twig](), most commonly a [gate]() `q` is a [twig]()
Tall form
---------
%: p
q
Wide form
---------
%:(p q)
Irregular form
--------------
None
Examples
--------
/~zod/try=> %:(dec 42)
41
Here we use `%:` in its most straightforward form, to call an arm that
takes one argument.
/~zod/try=> %: dec
%+ add 2
%+ mul 2 20
41
Here we call [`++dec`]() with the sum of `2` and the product of `2` and
`20` using `%:`. As you can see, `%:` is most useful for code
organization, when you need to compute intermediate products for your
final result

View File

@ -1,62 +0,0 @@
cendot, `%.`, %cndt
============================
Slam, reverse order
`%.` is a synthetic rune that reverses the order of [`%-`](). `%.`
exists primarily for code readability and organization, see the [style
guide]().
Produces
--------
Twig: `[%cndt p=twig q=twig]`
Sample
------
`p` and `q` are [twig]()s.
Tall form
---------
%. p
q
Wide form
---------
%.(p q)
Irregular form
--------------
None
Examples
--------
/~zod/try=> (dec 42)
41
~zod/try=> %.(42 dec)
41
In the most straightforward case `%.` allows us to reverse the order of
arm and arguments.
/~zod/try=> %.
%+ add
%+ mul 2 20
2
dec
41
Here we add `2` to the product of `2` and `20`, and use `%.` to
decrement our result. As you can see, `%.` is most useful for code
organization, when you need to compute intermediate products for your
final result.
Equivalent to
-------------
%-(q p)

View File

@ -1,39 +0,0 @@
cenhep, `%-`, %cnhp
============================
Slam, n-arguments
Slam, 1 (or n) argument(s)
%- is a synthetic rune that that pulls $ from the door p with its sample set to [%cltr q]. %- in both its tall and wide forms is like a function call with one argument. However, %-is most commonly used in its irregular form, where p and q are enclosed within () where q is a list of n arguments.
Produces
--------
Twig: `[%cnhp p=twig q=tusk]`
Sample
------
`p` is a [twig](), most commonly a [gate]() `q` is a [tusk](), a list of
twigs
Tall form
---------
%- p
q
==
Wide form
---------
%-(p q)
Irregular form
--------------
(p q)
Examples
--------

View File

@ -1,46 +0,0 @@
cenket, `%^`, %cnkt
============================
Slam, three arguments
`%^` is a synthetic rune that that [pull]()s [`$`]() from the [door]()
`p` with its sample set to `[%cntr q r s]`. `%^` in the most common case
simply [slam]()s `p` with `q`, `r` and `s`, similar to a function call
with three arguments.
Produces
--------
Twig: `[%cnkt p=twig q=twig r=twig s=twig]`
Sample
------
`p` is a [twig](), most commonly a [gate](). `q`, `r` and `s` are
[twig]()s.
Tall form
---------
%^ p
q
r
s
Wide form
---------
%^(p q r s)
Irregular form
--------------
None
Examples
--------
Equivalent to
-------------
%-(p [q r s])

View File

@ -1,59 +0,0 @@
cenlus, `%+`, %cnls
============================
Slam, two arguments
`%+` is a synthetic rune that that [pull]()s [`$`] from the [door]() `p`
with its sample set to `[%cntr q r]`. `%+` in the most common case
simply [slam]()s `p` with `q` and `r`, similar to a function call with
two arguments.
Produces
--------
Twig: `[%cnls p=twig q=twig r=twig]`
Sample
------
`p` is a [twig](), most commonly a [gate](). `q` and `r` are [twig]()s.
Tall form
---------
%+ p
q
r
Wide form
---------
%+(p q r)
Irregular form
--------------
None
Examples
--------
/~zod/try=> =a |= [b=@ c=@]
(add b c)
new var %a
/~zod/try=> %+ a
2
1
3
/~zod/try=> %+(a 2 3)
5
First we set a shell variable `a` to be a gate that takes two arguments
and produces their sum. Then we use `%+` to pass values to our gate.
`%+` is most useful for code organization, when you need to compute
intermediate products for your final computation.
Equivalent to
-------------
%-(p [q r])

Some files were not shown because too many files have changed in this diff Show More