Urbit Developers
  • Lightning Tutorials

    • Introduction
    • Build a Groups App
    • Build a Chat App
    • Build a Voting App
    • Core Curriculum

      • Hoon School

        • Introduction
        • 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

          • Introduction
          • 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)

            • Introduction
            • 1. Types
            • 2. Agent
            • 3. JSON
            • 4. Marks
            • 5. Eyre
            • 6. React app setup
            • 7. React app logic
            • 8. Desk and glob
            • 9. Summary
          • Environment Setup
          • Additional Guides

            • Threads

              • Fundamentals
              • Bind
              • Input
              • Output
              • Summary
              • Hoon Workbook

                • Rhonda Numbers
                • Roman Numerals
                • Solitaire Cipher
              • Writing Aqua Tests
              • CLI Apps
              • Serving a Browser Game
              • Using the HTTP API
              • Working with JSON
              • Parsing
              • Sail: HTML in Hoon
              • Distributing Software
              • Working with Strings
              • Writing Unit Tests
              Urbit Developers
              • Lightning Tutorials

                • Introduction
                • Build a Groups App
                • Build a Chat App
                • Build a Voting App
                • Core Curriculum

                  • Hoon School

                    • Introduction
                    • 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

                      • Introduction
                      • 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)

                        • Introduction
                        • 1. Types
                        • 2. Agent
                        • 3. JSON
                        • 4. Marks
                        • 5. Eyre
                        • 6. React app setup
                        • 7. React app logic
                        • 8. Desk and glob
                        • 9. Summary
                      • Environment Setup
                      • Additional Guides

                        • Threads

                          • Fundamentals
                          • Bind
                          • Input
                          • Output
                          • Summary
                          • Hoon Workbook

                            • Rhonda Numbers
                            • Roman Numerals
                            • Solitaire Cipher
                          • Writing Aqua Tests
                          • CLI Apps
                          • Serving a Browser Game
                          • Using the HTTP API
                          • Working with JSON
                          • Parsing
                          • Sail: HTML in Hoon
                          • Distributing Software
                          • Working with Strings
                          • Writing Unit Tests
                          Guides/Additional Guides/Threads

                          Input

                          The input to a strand is defined in /lib/strand/hoon as:

                          +$ strand-input [=bowl in=(unit input)]

                          When a thread is first started, spider will populate the bowl and provide it along with an input of ~. If/when new input comes in (such as a poke, sign or watch) it will provide a new updated bowl along with the new input.

                          For example, here's a thread that gets the time from the bowl, runs an IO-less function that takes one or two seconds to compute, and then gets the time again:

                          /- spider
                          /+ *strandio
                          =, strand=strand:spider
                          |%
                          ++ ackermann
                          |= [m=@ n=@]
                          ?: =(m 0) +(n)
                          ?: =(n 0) $(m (dec m), n 1)
                          $(m (dec m), n $(n (dec n)))
                          --
                          ^- thread:spider
                          |= arg=vase
                          =/ m (strand ,vase)
                          ^- form:m
                          ;< t1=@da bind:m get-time
                          =/ ack (ackermann 3 8)
                          ;< t2=@da bind:m get-time
                          (pure:m !>([t1 t2]))

                          Since it never does any IO, t1 and t2 are the same: [~2021.3.17..07.47.39..e186 ~2021.3.17..07.47.39..e186]. However, if we replace the ackermann function with a 2 second sleep from strandio:

                          /- spider
                          /+ *strandio
                          =, strand=strand:spider
                          ^- thread:spider
                          |= arg=vase
                          =/ m (strand ,vase)
                          ^- form:m
                          ;< t1=@da bind:m get-time
                          ;< ~ bind:m (sleep ~s2)
                          ;< t2=@da bind:m get-time
                          (pure:m !>([t1 t2]))

                          ...and run it again we get different values for t1 and t2: [~2021.3.17..07.50.28..8a5d ~2021.3.17..07.50.30..8a66]. This is because sleep gets a %wake sign back from behn, so spider updates the time in the bowl along with it.

                          Now let's look at the contents of bowl and input in detail:

                          bowl

                          bowl is the following:

                          +$ bowl
                          $: our=ship
                          src=ship
                          tid=tid
                          mom=(unit tid)
                          wex=boat:gall
                          sup=bitt:gall
                          eny=@uvJ
                          now=@da
                          byk=beak
                          ==
                          • our - our ship
                          • src - ship where input is coming from
                          • tid - ID of this thread
                          • mom - parent thread if this is a child thread
                          • wex - outgoing subscriptions
                          • sup - incoming subscriptions
                          • eny - entropy
                          • now - current datetime
                          • byk - [p=ship q=desk r=case] path prefix

                          There are a number of functions in strandio to access the bowl contents like get-bowl, get-beak, get-time, get-our and get-entropy.

                          You can also write a function with a gate whose sample is strand-input:strand and access the bowl that way like:

                          /- spider
                          /+ strandio
                          =, strand=strand:spider
                          =>
                          |%
                          ++ bowl-stuff
                          =/ m (strand ,[boat:gall bitt:gall])
                          ^- form:m
                          |= tin=strand-input:strand
                          `[%done [wex.bowl.tin sup.bowl.tin]]
                          --
                          ^- thread:spider
                          |= arg=vase
                          =/ m (strand ,vase)
                          ^- form:m
                          ;< res=[boat:gall bitt:gall] bind:m bowl-stuff
                          (pure:m !>(res))

                          input

                          input is defined in libstrand as:

                          +$ input
                          $% [%poke =cage]
                          [%sign =wire =sign-arvo]
                          [%agent =wire =sign:agent:gall]
                          [%watch =path]
                          ==
                          • %poke incoming poke
                          • %sign incoming sign from arvo
                          • %agent incoming sign from a gall agent
                          • %watch incoming subscription

                          Various functions in strandio will check input and conditionally do things based on its contents. For example, sleep sets a behn timer and then calls take-wake to wait for a %wake sign from behn:

                          ++ take-wake
                          |= until=(unit @da)
                          =/ m (strand ,~)
                          ^- form:m
                          |= tin=strand-input:strand
                          ?+ in.tin `[%skip ~]
                          ~ `[%wait ~]
                          [~ %sign [%wait @ ~] %behn %wake *]
                          ?. |(?=(~ until) =(`u.until (slaw %da i.t.wire.u.in.tin)))
                          `[%skip ~]
                          ?~ error.sign-arvo.u.in.tin
                          `[%done ~]
                          `[%fail %timer-error u.error.sign-arvo.u.in.tin]
                          ==

                          <-

                          Bind

                          Output

                          ->

                          Edit this page on GitHub

                          Last modified October 31, 2022