author: Ted Blackman ~rovnys-ricfer [email protected]
As anyone who's worked with the language can tell you, the overall levels of sanity and practicality in hoon are actually quite high. So why is it so hard to learn?
I believe most of the difficulty comes from the way hoon is taught.
Specifically, the neophyte is bombarded with a bewildering barrage of new concepts and terminology, and most of them are not explained in anywhere enough detail without referencing the other concepts. As you're learning hoon, there are far too many places where you're expected to gloss over something you're looking at without it being explained. It doesn't need to be this hard; the combined semantics of nock and hoon are actually more coherent than most languages, and the docs should make it feel that way.
I propose a new tutorial for hoon that presents concepts slowly, methodically, and thoroughly, adhering to a strict discipline of unidirectional dependency: thou shalt not present a new concept to the student without explaining it in full detail, with examples. Making reference to another concept in the description is only allowed if that other concept has already been fully explained. This tutorial also must not require a priori knowledge of computer programming. This imposes some useful constraints on the order in which hoon concepts should be taught, and on the methods used to elucidate them.
The tutorial will be broken up into chapters, intended to be followed in order. Later chapters may make reference to earlier chapters, but not vice versa, except as footnotes or parentheticals.
-
Introduction
- Hoon
- Nock
- The Dojo
-
The Noun
- The Atom (no auras yet, just unsigned integer)
- The Cell
- Right Association
-
Tree Indexing Syntaxes
axis:tree
Syntax- Numeric Indexing (e.g.
+3:x
)- Axis as Binary Number
- Lark Syntax (e.g.
.:x
,-:x
,+:x
,+<:x
,+>:x
) - Tuple Indexing (e.g.
&2:x
,|2:x
)
-
Hoon To Nock
.*
Overview (No Examples, Tall-Form Only)- The Subject
- The Formula
- Hoon Becomes a Formula
- Tall-Form Syntax
- Single-Line Examples
- Multi-Line Examples
.
Runes Call Nock
- Nock 0
.*
Examples with Nock 0 (Repeat Previous Indexing Examples)
- Nock 1
.*
Examples with Nock 1
!=
(Tall-Form Only)!
Runes are Miscellaneous- Compilation of Hoon Constants to Nock 1
- Reminder that Hoon Becomes a Formula
- Nock Output from Previous Nock 0 Examples
- Nock 7 and
=>
(without Nock 2)
+=
Runes "Modify" the Subject- Modification Means Mutant Copy
- Read
=>
as "With x as Subject, Evaluate y" - Examples of
=>
with Nock 0 (Tall-Form Only)- Bare Tree Indexing (e.g.
.
,-
,+
,+3
,&2
)- Note Compiler Cleverness with
.
- Note Compiler Cleverness with
- Bare Tree Indexing (e.g.
- Examples of
=>
with Nock 1 !=
with=>
- Nock from Previous
=>
Examples - Examples of Nock 7 with Non-Trivial
b
Formula
- Nock from Previous
- Nock 2
!=
of Previous.*
Examples- Comparison With Nock 7
- Examples that Produce the Same Result
- Nock 4,
.+
, and+(x)
- Reminder that
.
Runes Call Nock .+
and+(x)
Hoon Syntaxes- Examples of Formula Nesting (e.g.
+(+3:[5 0])
) - Example of Error on Cell
- Examples of Formula Nesting (e.g.
!=
of+(x)
Examples
- Reminder that
- Nock 3, Loobeans, and
.?
%.y
,%.n
and Compilation.?
and Compilation
- Nock Autocons
- Examples with Nock 0
- Hoon Examples (e.g.
!= [+7 +9]
)
- Hoon Examples (e.g.
- Examples with Nock 1
- Hoon Examples (e.g.
!= [+3 42]
)
- Hoon Examples (e.g.
- Examples With Recursion (More than Two Formulas)
- Examples with Nock 0
- Nock 5,
.=
, and=
- Reminder that
.
Runes Call Nock .=
and Compilation- Examples with Autocons
- Examples of Error on Atom
- Reminder that
- Nock 6 and
?:
(Tall-Form Only)?
Runes Are Conditionals?:
and Compilation- Examples Using Loobean Literal as Conditional
- e.g.
?: %.y 12 13
,?: %.n 12 13
- e.g.
- Examples Using the Subject and
=>
(Single-Line and Multi-Line)- Outside
?:
:=> [5 9] ?: .? - - +
- Inside
?:
:?: %.y => [3 4] - => [3 4] +
- Outside
- Nock 8 and
=+
- Introduction to Faces
=+
and Compilation- Reminder that
=
Runes Modify the Subject - Explanation: Adds a Noun to the Head of the Subject
- Examples without Faces
- Same Examples with Faces, Same Nock
- Explanation of
face=foo
Syntax
- Reminder that
face.noun
Syntax- Examples with Equivalent Axis Lookup
- Differences Between
face.noun
andface:noun
- Error Examples, e.g.
-.[5 9]
- Nesting
=+ a=2 =+ b=3 [a b]
=+ a=2 ?: .= a 2 %.y %.n
=+ [a b]=[2 3] a
=+ [a=[b=2]] b.a
!= [1 b=2]
=+ [1 b=2] b
- Nock 9 and
|%
- Nock 9 Macro Expansion
|%
and Compilation- Simplest Example:
=+ foo |% ++ bar 42 -- bar.foo
- Arm that Calls Another Arm
- Differences between
face.noun
andarm:noun
Syntaxes- Error Examples
- Explain Convention of
face.noun
for Non-Cores
- Simplest Example:
~
Runes and Nock 10~
Runes Are Hints And Don't Affect Product~&
Examples
- Conclusion of Hoon to Nock
-
:
Runes: Making Cells:-
,:_
Forward and Backward Pairs:+
,+^
3- and 4-Tuples:*
N-Tuples==
as Terminator
- Null-Terminated Lists
~
(and!=
to0
):~
,:*
==
As Terminator
[]~
and~[]
Syntaxes- Reminder about
&2
and|2
Syntaxes
-
Axis Swapping
%=
Rune andfoo(axis value)
Irregular Syntax- Compilation Examples and Autocons Refresher
- Examples with Lark Syntax and Face Equivalents
a.b
Examples=+
Examples=>
Examples
-
Molds, Spans, and Gates
-
Intro to Datatypes in Hoon (No Examples)
- Used for Both Type-Checking and Input Validation
- Stripped out of Compiled Nock
- Spans
- A Span Represents the Set of Possible Values
- A Span Does Not Enumerate the Set
- Composed from Built-In Base Spans
?
Dojo Syntax- Dojo Supports Superset of Hoon
- Spans of Atoms
- Spans of Cells
- Spans of
!=
Are*
*
Means Noun, which Means Anything
- Spans of Faces
- Faces Are Stored in Spans
- Transformed into Axes By the Compiler at Compile Time
- Relies on the Compile-Time Subject
- Examples of Different Compile-Time Subjects
=+ a=3 != a
vs.=+ a=3 =+ b=5 != a
- Examples of Different Compile-Time Subjects
- Most Hoon Is Compiled Against the Standard Library
- Relies on the Compile-Time Subject
- A Span Represents the Set of Possible Values
-
Basic Type Conversions:
*
,@
, and^
- A Gate Is a Core with One Arm ($)
- Core Refresher
- Diagram of Battery, Sample, and Context
- Core Refresher
*
: Convert to Noun*
Is a Trivial Function (Gate), with Full Gate Structure*
Compilation- A Compiled Gate Evaluates to a Core
- Prepend Sample to Context: the
8 [1 0]
Section - Autocons of Arm and
[0 1]
To Preserve Payload - "Quoted" (Nock 1) Gate Formula
[0 6]
Produces Sample (Identity)
- Bunting
(func)
Bunting Syntax and Compilation to Nock 9*func
Bunting Syntax- Compiler Cleverness for
**
- Compiler Cleverness for
- Calling
- How Calling Works
- Swapping The Sample
- Examples With
@
e.g.=+ atom=@ $:atom(+< 3)
- Examples With
- Swapping The Sample
(func arg)
and%-
Calling Syntaxes- Use
%-
if Arg is Complex - Examples of Equivalence to Swapping Sample
- Use
- How Calling Works
@
: Convert to Atom@
Is a Function (Gate) like*
- Produces Sample Unless Sample Is Cell
@
Compilation- Comparison to Compiled
*
- "Quoted" (Nock 1) Gate Formula
- Redundant Nock 6 (Compilation Artifact)
- Comparison to Compiled
^
Convert to Cell^
Is Also a Function (Gate)- Produces Sample Unless Sample Is Atom
- Repeat
@
Examples with^
^
Compilation- Comparison to Compiled
*
and@
- "Quoted" (Nock 1) Gate Formula
- Redundant Nock 6, Nock 2s
- Comparison to Compiled
- A Gate Is a Core with One Arm ($)
-
Molds Are Gates (Types Are Functions)
- Calling a Mold as a Function Normalizes to Span
- Idempotence Requirement
@
Normalizes to Atom Span,^
Normalizes to Cell Span- Every Mold Has a Default Value
- Bunt the Mold to Get the Default Value
-
Will It Nest?
?=
Rune- Reminder that
?
Runes Are Conditionals - Examples with Atoms and Cells
- Casting
^-
Rune`mold`
Irregular Syntax- Can Only Cast to More General Type
`*``@`3
Succeeds`@``*`3
Fails`@``^`3
Fails`^``@`3
Fails
- Faces and Casting
- Adding Faces and Examples
- Changing Faces and Examples
~!
Rune and Debugging Type Failures
- Reminder that
-
Atom Auras
- TODO
-
Defining Your Own Gates
|
Runes Create Cores|=
Defines a Gate|= @ +<
- Compilation Removes Types
- Except for Default Sample as Bunted Mold
- Bunting Example
- Calling Examples
- Nest Fail Examples, e.g.
(f [1 2])
- Reminder that
+<
Is the Sample
- Compilation Removes Types
|= a=@ a
and|= b=@ b
- A Mold Can Add Faces
|= a/@ +(a)
- Compilation
- Bunting Example
- Calling Examples
- Recursion
- First, You Must Understand Recursion
arm(foo new-foo)
Syntax- Read as: "arm:new-core where new-core is core(foo new-foo)"
foo
must be in the core's payload: sample or context- Sample: Changing the Argument
- Context: Changing the Execution Environment
- Read as: "arm:new-core where new-core is core(foo new-foo)"
- Reminder:
$
Is Just an Arm |= a/@ ?: =(3 a) a $(a +(a))
- Description
- Call with 0, 1, 2, 3
- Call with 4: Infinite Recursion
- Compilation
- Factorial
- Examples of
++mul
and++sub
Before Definition
- Examples of
-
-
Doors and
|_
- TODO
-
Core and Face Nesting
- Shadowing Outer Faces
- Search Order: Left-Most First, etc.`
- Tree Examples
- Left-Most First, e.g.
a:[[a=1 2] a=3]
- Then Highest-Level First, e.g.
a:[a=[a=1 2] 3]
- Left-Most First, e.g.
=+
Examples=+ a=1 =+ a=2 a
=+ a=[a=1 b=2] a
- Tree Examples
- Skipping Search Results
^face
=+ a=1 =+ a=2 ^a
=+ a=[a=1 b=2] ^a
^^face
=+ a=1 =+ a=2 =+ a=3 ^^a
=+ a=[a=[a=1 b=2]] ^^a
- Search Order: Left-Most First, etc.`
- Cores Inside Cores
- Access with
+>
- Examples and Compilation with
|%
and|_
- Examples and Compilation with
- Name Shadowing in Cores
- Arms
|% ++ a 2 ++ b |% a 3 ++ c ^a -- --
- Legs
|= a=@ =+ g |= a=@ (add a ^a) (g 3)
- Arms
- Access with
- Gates Inside Cores
- Reminder that an Arm Can Call Any Other Arm
- Nock 9 Evaluates the Arm with the Whole Core As Subject
- Examples of Gate Evaluating Another Arm
- Examples of Gate Calling Another Gate
- Examples of Gate Inside Gate
- Use Context in Inner Gate
- Recurse to Outer Gate
- Should I Use a Gate or an Arm?
- Use an Arm if There Are No Arguments
- Reminder that an Arm Can Call Any Other Arm
- Nested Core Design Patterns
- Hierarchical State Machine
++apex
Main Entry Point++abet
"Mutate" Outer Core (Collect Results)++abut
"Cancel" Variant of++abet
- Shadowing Outer Faces
-
Building Molds
- Mold Syntax
+
Runes Define Arms+=
Rune- Contents of
+=
Are Interpreted as a Mold - Comparison with
++
and Compilation+= foo [@ @]
vs.++ foo [@ @]
- Contents of
$
Runes Construct Molds- A
$
Rune Produces a Mold- Often from Other Molds
- All Spans Are Constructed from Base Spans
??
Dojo Syntax to Print Span, and Examples%noun
Base Spans and Examples%atom
Base Spans and Examples%cell
Base Spans and Examples- Cores (
%core
Base Span) Are Big When You Print Them
$:
and[foo bar baz]
: Mold Recognizing a Tuple- Produces
%cell
Base Span ??
Examples
- Produces
$=
Wraps Face around Mold- Produces
%face
Base Span
- Produces
- Union Types
- Examples with
?=
Successes and Failures $?
Union and Examples$@
Union Tagged by Atom or Cell$^
Union Tagged by Whether Head is Atom or Cell$%
Union Tagged by Head Atom
- Examples with
- Recursive Types
- Produce a
%hold
Span - Examples
- Produce a
- Doccords
- Produce a
%help
Span - TODO
- Produce a
- A
- Mold-Building Gates
+ Encapsulate Patterns of Mold Creation
+ Need Polymorphism
|*
Wet Gates and Wet Arms- A Wet Gate Is a Core with One "Wet Arm" (
$
)- What We've Been Calling "Gates" Are Dry Gates
- All Arms We've Seen So Far Have Been Dry
- What We've Been Calling "Gates" Are Dry Gates
- Preserve Type Information
- Often Used as Mold Builders
- Examples from Standard Library
++unit
- Used to Indicate Possible Absence of a Value
`x
Syntax`unit`[~ x]
Adds Face
++list
- Null-Terminated List with Homogeneous Entries
- Reminder of
[]~
,~[]
, and:~
Syntaxes
- Define Some Example Wet Gates
- Define Some Cores with Wet Arms (
+-
)
- A Wet Gate Is a Core with One "Wet Arm" (
$_
,_x
, and^+
: Type By Example- Construct Type from Value
^+
Creates A Type and Casts to It- Examples and Compilation
$-
Gate Types- Can't Use in
?=
- TODO Why not? ask ~pittyp again
- Can't Use in
- Gates with Complex Sample Types
(func arg1 arg2)
and%+
Calling Syntax- Replaces Sample with Pair, Right-Association
- Examples with
++add
,++sub
,++mod
(add 2 3)
vs.(add [2 3])
- Define Some Example Gates
(func arg1 arg2 arg3)
and%^
Calling Syntax++rsh
Explanation and Examples(rsh 0 1 15)
and(rsh [0 1 15])
- Define Some Example Gates
- Mold Syntax
-
TODO
- It might be better to move nock 8 up to have it closer to the tree indexing, so we aren't stuck in numberland too long.
- We could use the macro-expanded nock formula instead.
- Maybe introduce nock 7 first to get the student comfortable with modifying the subject.
- Maybe present
*
,@
, and^
closer together to be less boring than just*
. - Add a section on cords before
$%
. Not sure yet if this should be a full aura listing or just simple cords. The cord section should probably be after a section on molds and?=
so that cold atoms and the$143
and%143
syntaxes can be explained. - Is my definition of
++abut
right? - Where should
$~
go?
This looks like an excellent outline!
I may have some quibbles with the ordering of topics, but first I'll need to think about it some more.
In the meantime, I've pushed the ~mardev docs to github: https://github.com/joemfb/mardev. There's an in-progress atom section that hasn't been published yet. And i've got bits and pieces on cores, data structures, parsers, and so on. I'll try to get that together and push it soon. Feel free to incorporate anything you like!