Urbit Docs
  • What is Urbit?
  • Get on Urbit
  • Build on Urbit
    • Contents
    • Environment Setup
    • Hoon School
      • 1. Hoon Syntax
      • 2. Azimuth (Urbit ID)
      • 3. Gates (Functions)
      • 4. Molds (Types)
      • 5. Cores
      • 6. Trees and Addressing
      • 7. Libraries
      • 8. Testing Code
      • 9. Text Processing I
      • 10. Cores and Doors
      • 11. Data Structures
      • 12. Type Checking
      • 13. Conditional Logic
      • 14. Subject-Oriented Programming
      • 15. Text Processing II
      • 16. Functional Programming
      • 17. Text Processing III
      • 18. Generic and Variant Cores
      • 19. Mathematics
    • App School I
      • 1. Arvo
      • 2. The Agent Core
      • 3. Imports and Aliases
      • 4. Lifecycle
      • 5. Cards
      • 6. Pokes
      • 7. Structures and Marks
      • 8. Subscriptions
      • 9. Vanes
      • 10. Scries
      • 11. Failure
      • 12. Next Steps
      • Appendix: Types
    • App School II (Full-Stack)
      • 1. Types
      • 2. Agent
      • 3. JSON
      • 4. Marks
      • 5. Eyre
      • 6. React app setup
      • 7. React app logic
      • 8. Desk and glob
      • 9. Summary
    • Core Academy
      • 1. Evaluating Nock
      • 2. Building Hoon
      • 3. The Core Stack
      • 4. Arvo I: The Main Sequence
      • 5. Arvo II: The Boot Sequence
      • 6. Vere I: u3 and the Serf
      • 7. Vere II: The Loom
      • 8. Vanes I: Behn, Dill, Kahn, Lick
      • 9. Vanes II: Ames
      • 10. Vanes III: Eyre, Iris
      • 11. Vanes IV: Clay
      • 12. Vanes V: Gall and Userspace
      • 13. Vanes VI: Khan, Lick
      • 14. Vanes VII: Jael, Azimuth
    • Runtime
      • U3
      • Conn.c Guide
      • How to Write a Jet
      • API Overview by Prefix
      • C in Urbit
      • Cryptography
      • Land of Nouns
    • Tools
      • Useful Links
      • JS Libraries
        • HTTP API
      • Docs App
        • File Format
        • Index File
        • Suggested Structure
    • Userspace
      • Command-Line App Tutorial
      • Remote Scry
      • Unit Tests
      • Software Distribution
        • Software Distribution Guide
        • Docket File
        • Glob
      • Examples
        • Building a CLI App
        • Debugging Wrapper
        • Host a Website
        • Serving a JS Game
        • Ship Monitoring
        • Styled Text
  • Urbit ID
    • What is Urbit ID?
    • Azimuth Data Flow
    • Life and Rift
    • Urbit HD Wallet
    • Advanced Azimuth Tools
    • Custom Roller Tutorial
    • Azimuth.eth Reference
    • Ecliptic.eth Reference
    • Layer 2
      • L2 Actions
      • L2 Rollers
      • L2 Roller HTTP RPC-API
      • L2 Transaction Format
  • Urbit OS
    • What is Urbit OS?
    • Base
      • Hood
      • Threads
        • Basics Tutorial
          • Bind
          • Fundamentals
          • Input
          • Output
          • Summary
        • HTTP API Guide
        • Spider API Reference
        • Strandio Reference
        • Examples
          • Child Thread
          • Fetch JSON
          • Gall
            • Poke Thread
            • Start Thread
            • Stop Thread
            • Take Facts
            • Take Result
          • Main-loop
          • Poke Agent
          • Scry
          • Take Fact
    • Kernel
      • Arvo
        • Cryptography
        • Move Trace
        • Scries
        • Subscriptions
      • Ames
        • Ames API Reference
        • Ames Cryptography
        • Ames Data Types
        • Ames Scry Reference
      • Behn
        • Behn API Reference
        • Behn Examples
        • Behn Scry Reference
      • Clay
        • Clay API Reference
        • Clay Architecture
        • Clay Data Types
        • Clay Examples
        • Clay Scry Reference
        • Filesystem Hierarchy
        • Marks
          • Mark Examples
          • Using Marks
          • Writing Marks
        • Using Clay
      • Dill
        • Dill API Reference
        • Dill Data Types
        • Dill Scry Reference
      • Eyre
        • EAuth
        • Eyre Data Types
        • Eyre External API
        • Eyre Internal API
        • Eyre Scry Reference
        • Low-Level Eyre Guide
        • Noun channels
      • Gall
        • Gall API Reference
        • Gall Data Types
        • Gall Scry Reference
      • Iris
        • Iris API Reference
        • Iris Data Types
        • Iris Example
      • Jael
        • Jael API Reference
        • Jael Data Types
        • Jael Examples
        • Jael Scry Reference
      • Khan
        • Khan API Reference
        • Khan Data Types
        • Khan Example
      • Lick
        • Lick API Reference
        • Lick Guide
        • Lick Examples
        • Lick Scry Reference
  • Hoon
    • Why Hoon?
    • Advanced Types
    • Arvo
    • Auras
    • Basic Types
    • Cheat Sheet
    • Cryptography
    • Examples
      • ABC Blocks
      • Competitive Programming
      • Emirp
      • Gleichniszahlenreihe
      • Islands
      • Luhn Number
      • Minimum Path Sum
      • Phone Letters
      • Restore IP
      • Rhonda Numbers
      • Roman Numerals
      • Solitaire Cipher
      • Water Towers
    • Generators
    • Hoon Errors
    • Hoon Style Guide
    • Implementing an Aura
    • Irregular forms
    • JSON
    • Limbs and wings
      • Limbs
      • Wings
    • Mips (Maps of Maps)
    • Parsing Text
    • Runes
      • | bar · Cores
      • $ buc · Structures
      • % cen · Calls
      • : col · Cells
      • . dot · Nock
      • / fas · Imports
      • ^ ket · Casts
      • + lus · Arms
      • ; mic · Make
      • ~ sig · Hints
      • = tis · Subject
      • ? wut · Conditionals
      • ! zap · Wild
      • Constants (Atoms and Strings)
      • --, == · Terminators
    • Sail (HTML)
    • Serialization
    • Sets
    • Standard Library
      • 1a: Basic Arithmetic
      • 1b: Tree Addressing
      • 1c: Molds and Mold-Builders
      • 2a: Unit Logic
      • 2b: List Logic
      • 2c: Bit Arithmetic
      • 2d: Bit Logic
      • 2e: Insecure Hashing
      • 2f: Noun Ordering
      • 2g: Unsigned Powers
      • 2h: Set Logic
      • 2i: Map Logic
      • 2j: Jar and Jug Logic
      • 2k: Queue Logic
      • 2l: Container from Container
      • 2m: Container from Noun
      • 2n: Functional Hacks
      • 2o: Normalizing Containers
      • 2p: Serialization
      • 2q: Molds and Mold-Builders
      • 3a: Modular and Signed Ints
      • 3b: Floating Point
      • 3c: Urbit Time
      • 3d: SHA Hash Family
      • 3e: AES encryption (Removed)
      • 3f: Scrambling
      • 3g: Molds and Mold-Builders
      • 4a: Exotic Bases
      • 4b: Text Processing
      • 4c: Tank Printer
      • 4d: Parsing (Tracing)
      • 4e: Parsing (Combinators)
      • 4f: Parsing (Rule-Builders)
      • 4g: Parsing (Outside Caller)
      • 4h: Parsing (ASCII Glyphs)
      • 4i: Parsing (Useful Idioms)
      • 4j: Parsing (Bases and Base Digits)
      • 4k: Atom Printing
      • 4l: Atom Parsing
      • 4m: Formatting Functions
      • 4n: Virtualization
      • 4o: Molds
      • 5a: Compiler Utilities
      • 5b: Macro Expansion
      • 5c: Compiler Backend & Prettyprinter
      • 5d: Parser
      • 5e: Molds and mold builders
      • 5f: Profiling support
    • Strings
    • The Engine Pattern
    • Udon (Markdown-esque)
    • Vases
    • Zuse
      • 2d(1-5): To JSON, Wains
      • 2d(6): From JSON
      • 2d(7): From JSON (unit)
      • 2e(2-3): Print & Parse JSON
      • 2m: Ordered Maps
  • Nock
    • What is Nock?
    • Decrement
    • Definition
    • Fast Hints and Jets
    • Implementations
    • Specification
  • User Manual
    • Contents
    • Running Urbit
      • Cloud Hosting
      • Home Servers
      • Runtime Reference
      • Self-hosting S3 Storage with MinIO
    • Urbit ID
      • Bridge Troubleshooting
      • Creating an Invite Pool
      • Get an Urbit ID
      • Guide to Factory Resets
      • HD Wallet (Master Ticket)
      • Layer 2 for planets
      • Layer 2 for stars
      • Proxies
      • Using Bridge
    • Urbit OS
      • Basics
      • Configuring S3 Storage
      • Dojo Tools
      • Filesystem
      • Shell
      • Ship Troubleshooting
      • Star and Galaxy Operations
      • Updates
Powered by GitBook

GitHub

  • Urbit ID
  • Urbit OS
  • Runtime

Resources

  • YouTube
  • Whitepaper
  • Awesome Urbit

Contact

  • X
  • Email
  • Gather
On this page
  • Overview
  • => "tisgar"
  • =| "tisbar"
  • =: "tiscol"
  • =, "tiscom"
  • =. "tisdot"
  • =- "tishep"
  • =^ "tisket"
  • =< "tisgal"
  • =+ "tislus"
  • =; "tismic"
  • =/ "tisfas"
  • =~ "tissig"
  • =* "tistar"
  • =? "tiswut"
Edit on GitHub
  1. Hoon
  2. Runes

= tis · Subject

These runes modify the subject. (Or more precisely, they evaluate at least one of their subexpressions with a modified subject.)

Overview

Hoon doesn't have variables in the ordinary sense. If you want to bind a name to a value, e.g., a to 12, you do so by pinning 12 to the subject and associating the name with it. This sort of operation is done with the = family of runes.

Let's say you have some old subject p. To 'pin' a value to the head means to modify the subject by repacing it with a cell of [new-value p]. The head of the cell is the new value. So to pin 12 with the face a the new subject would be: [a=12 p].

Of course there are many variations on ways to modify the subject, useful for different situations. Hence the whole family of = runes.


=> "tisgar"

Compose two expressions.

Syntax

Two arguments, fixed.

=>  p
q
=>(p q)

None

AST

[%tsgr p=hoon q=hoon]

Produces

the product of q, with the product of p taken as the subject.

Examples

> =>([a=1 b=2 c=3] b)
2

> =>  9  .
9

> =>((add 2 4) [. .])
[6 6]

> =>
  |%
  ++  foo
    |=  [a=@ b=@]
    [b a]
  --
  (foo 42 27)
[27 42]

=| "tisbar"

Combine a named noun with the subject by "bunting" (producing the default value) of a given mold.

Syntax

Two arguments, fixed.

=|  p
q
=|(p q)

none

AST

[%tsbr p=spec q=hoon]

Expands to

=+(*p q)

Discussion

The default (or 'bunt') value of p is pinned to the head of the subject. Usually p includes a name for ease of reference.

Speaking more loosely, =| usually "declares a variable" which is "uninitialized," presumably because you'll set it in a loop or similar.

Examples

> =|  a=@ud  a
0

> =|  a=[@t @t @t]  a
['' '' '']

=: "tiscol"

Change multiple legs in the subject.

Syntax

Two arguments: the first a variable number of pairs, the second is fixed.

=:  p1a  p1b
    p2a  p2b
    p3a  p3b
  ==
q
=:(p1a p1b, p2a p2b, p3a p3b q)

None

AST

[%tscl p=(list (pair wing hoon)) q=hoon]

Expands to

=>(%_(. p) q)

Discussion

This rune is like =., but for modifying the values of multiple legs of the subject.

Examples

> =+  a=[b=1 c=2]
  =:  c.a  4
      b.a  3
    ==
  a
[b=3 c=4]

=, "tiscom"

Expose namespace.

Syntax

Two arguments, fixed.

=,  p
q
=,(p q)

None

AST

[%tscm p=hoon q=hoon]

Produces

p evaluates to a noun with some namespace. From within q you may access p's names without a wing path (i.e., you can use face b rather than b.p).

Discussion

This is especially useful for calling arms from an imported library core or for calling arms from a stdlib core repeatedly. For example, JSON reparsers like so:dejs:format and of:dejs:format can be called as so and of after doing:

=,  dejs:format

Examples

With an imported core:

> (sum -7 --7)
-find.sum
dojo: hoon expression failed

> (sum:si -7 --7)
--0

> =,  si  (sum -7 --7)
--0

With a dojo-defined face:

> =/  fan  [bab=2 baz=[3 qux=4]]
  =,  fan
  [bab qux.baz]
[2 4]

=. "tisdot"

Change one leg in the subject.

Syntax

Three arguments, fixed.

=.  p  q
r
=.(p q r)

None

AST

[%tsdt p=wing q=hoon r=hoon]

Expands to

=>(%_(. p q) r)

Discussion

Technically the =. rune doesn't change the subject. It creates a new subject just like the old one except for a changed value at p. Note that the mutation uses %_ ("cencab"), so the type at p doesn't change. Trying to change the value type results in a nest-fail.

Examples

> =+  a=[b=1 c=2]
  =.  b.a  3
  a
[b=3 c=2]

> =+  a=[b=1 c=2]
  =.(b.a 3 a)
[b=3 c=2]

> =+  a=[b=1 c=2]
  =.(b.a "hello" a)
nest-fail

=- "tishep"

Combine a new noun with the subject, inverted.

Syntax

Two arguments, fixed.

=-  p
q
=-(p q)

None

AST

[%tshp p=hoon q=hoon]

Expands to

=>([q .] p)

Discussion

=- is just like =+ but its subexpressions are reversed. =- looks better than =+ when the expression you're pinning to the subject is much larger than the expression that uses it.

Examples

> =foo |=  a=@
       =-  (add a b)
       :*  %a-bunch
           %of-stuff
           %here
           b=2
           %and-perhaps-more
       ==
> (foo 5)
7

=^ "tisket"

Pin the head of a pair; change a leg with the tail.

Syntax

Four arguments, fixed.

=^  p  q
  r
s
=^(p q r s)

None

AST

[%tskt p=skin q=wing r=hoon s=hoon]

Expands to

=/(p -.r =.(q +.r s))

Discussion

  • p is a new name (optionally with type) to pin to the subject.

  • q is the name of an existing wing of the subject.

  • r is an expression that produces [p-value new-q-value].

  • s is some more code to be evaluted against the modified subject.

This is a bit like doing =/ and =. at the same time. It's useful for state machines, where you want to produce both effects and a new state. For example, many arms of a Gall agent produce [effects new-state] in the form of a (quip card _this). In the ++on-poke arm, you might have something like:

=^  cards  state
  (handle-poke !<(action vase))
[cards this]

This may also remind you of Haskell's State monad.

Note that =^ is subject to the same type nesting limitations as =.; e.g., if you have ?~ checked a list for null, you can no longer nest a regular list in the result. (In this case, use a nock =(~ ...) equality check instead or recast the result.)

Examples

The og core is a stateful pseudo-random number generator. We have to change the core state every time we generate a random number, so we use =^:

~zod:dojo> =+  rng=~(. og 420)
           =^  r1  rng  (rads:rng 100)
           =^  r2  rng  (rads:rng 100)
           [r1 r2]
[99 46]

=< "tisgal"

Compose two expressions, inverted.

Syntax

Two arguments, fixed

=<  p
q
=<(p q)
p:q

AST

[%tsgl p=hoon q=hoon]

Expands to

=>(q p)

Discussion

=< is just => backwards.

Examples

> =<(b [a=1 b=2 c=3])
2

> =<  b
  [a=1 b=2 c=3]
2

> b:[a=1 b=2 c=3]
2

> [. .]:(add 2 4)
[6 6]

=+ "tislus"

Combine a new noun with the subject.

Syntax

Two arguments, fixed.

=+  p
q
=+(p q)

None

AST

[%tsls p=hoon q=hoon]

Expands to

=>([p .] q)

Discussion

The subject of the =+ expression, call it a, becomes the cell [p a] for the evaluation of q. That is, =+ 'pins a value', p, to the head of the subject.

Loosely speaking, =+ is the simplest way of "declaring a variable."

Examples

> =+  42  -
42

> =+  x=42  x
42

> =+  [a='foo' b='bar']  a
'foo'

=; "tismic"

Combine a named noun with the subject, possibly with type annotation; inverted order.

Syntax

Three arguments, fixed.

=;  p
  q
r
=;(p q r)

None

AST

[%tsmc p=skin q=hoon r=hoon]

Expands to

=/(p r q)

Discussion

=; is exactly like =/ except that the order of its last two subexpressions is reversed.

Examples

> =foo |=  a=@
       =/   b  1
       =;   c=@
         :(add a b c)
       2
> (foo 5)
8

=/ "tisfas"

Combine a named noun with the subject, possibly with type annotation.

Syntax

Three arguments, fixed.

=/  p
  q
r
=/(p q r)

None

AST

[%tsfs p=skin q=hoon r=hoon]

Expands to

if p is a name, (e.g. a):

=+(^=(p q) r)

if p is a name with a type (e.g., a=@):

=+(^-(p q) r)

Desugaring

?@  p
  =+  p=q
  r
=+  ^-($=(p.p q.p) q)
r

Discussion

p can be either a name or a name=type. If it's just a name, =/ ("tisfas") "declares a type-inferred variable." If it has a type, =/ "declares a type-checked variable."

Examples

> =/  a=@t  'hello'  a
'hello'

> =/  x  [1 2 3]  x
[1 2 3]

> =foo |=  a=@
       =/  b  1
       =/  c=@  2
       :(add a b c)
> (foo 5)
8

=~ "tissig"

Compose many expressions.

Syntax

Variable number of arguments.

=~  p1
    p2
    p3
    pn
==
=~(p1 p2 p3 pn)

None

AST

[%tssg p=(list hoon)]

Produces

The product of the chain composition.

Examples

> =~  10
      [20 .]
      [30 .]
      [40 .]
      .
  ==
[40 30 20 10]

> =~  [sub (mul 3 20) (add 10 20)]
      (sub +)
      +(.)
  ==
31

> =foo =|  n=@
       =<  =~  increment
               increment
               increment
               n
           ==
       |%
       ++  increment
         ..increment(n +(n))
       --
> foo
3

=* "tistar"

Define a deferred expression.

Syntax

Three arguments, fixed.

=*  p
  q
r
=*(p q r)

None

AST

[%tstr p=term q=hoon r=hoon]

Produces

r, compiled with a subject in which p is a deferred expression for q.

Discussion

=* assigns a name to an expression that will be evaluated in each place the name is dereferenced. This allows you to "write" through it to the original subject axis. q is recorded in the type information of p, and q is calculated every time you use p.

This rune has some similarities with macros, and some similarities with aliases, but it is not really either.

This rune is commonly used to give a Gall agent's state the name state like:

=*  state  -

This lets you reference the whole state while also being able to reference its individual elements like foo and bar, without having to do foo.state, bar.state, etc.

Examples

> =+  a=1
  =*  b  a
  [a b]
[1 1]

> =+  a=1
  =*  b  a
  =.  a  2
  [a b]
[2 2]

=? "tiswut"

Conditionally change one leg in the subject.

Syntax

Four arguments, fixed.

=?  p  q
  r
s
=?(p q r s)

None

AST

[%tswt p=wing q=hoon r=hoon s=hoon]

Expands to

=.  p  ?:(q r p)
s

Discussion

Use =? to replace the value of leg p with r on condition q. As usual, we are not actually mutating the subject, just creating a new subject with a changed value. The change in value includes a type check against the old subject; the type of r must nest under the type of p.

Examples

> =a 12

> =?(a =(1 1) 22 a)
22

> =?(a =(1 2) 22 a)
12
Previous~ sig · HintsNext? wut · Conditionals

Last updated 1 day ago