Strandio

Documented below are the many useful functions in the /lib/strandio.hoon helper library.

Send Cards

send-raw-cards

Send a list of cards.

Accepts

A (list card:agent:gall).

Produces

~

Source

++ send-raw-cards
|= cards=(list =card:agent:gall)
=/ m (strand ,~)
^- form:m
|= strand-input:strand
[cards %done ~]

Example

;~ now=@da bind:m get-time
=/ cards=(list card)
:~ [%pass /foo %agent [~zod %foo] %poke %noun !>(~)]
[%pass /bar %arvo %b %wait now]
==
;< ~ bind:m (send-raw-cards cards)

send-raw-card

Send a single card.

Accepts

A card:agent:gall

Produces

~

Source

++ send-raw-card
|= =card:agent:gall
=/ m (strand ,~)
^- form:m
(send-raw-cards card ~)

Example

=/ card [%pass /foo %agent [~zod %foo] %poke %noun !>(~)]
;< ~ bind:m (send-raw-card card)

Bowl

get-bowl

Get the bowl.

Accepts

Nothing.

Produces

A bowl:rand.

Source

++ get-bowl
=/ m (strand ,bowl:strand)
^- form:m
|= tin=strand-input:strand
`[%done bowl.tin]

Example

;< =bowl:rand bind:m get-bowl

get-beak

Get the beak.

Accepts

Nothing.

Produces

A beak.

Source

++ get-beak
=/ m (strand ,beak)
^- form:m
|= tin=strand-input:strand
`[%done [our q.byk da+now]:bowl.tin]

Example

;< =beak bind:m get-beak

get-time

Get the current date-time.

Accepts

Nothing.

Produces

A @da.

Source

++ get-time
=/ m (strand ,@da)
^- form:m
|= tin=strand-input:strand
`[%done now.bowl.tin]

Example

;< now=@da bind:m get-time

get-our

Get our ship.

Accepts

Nothing.

Produces

A @p.

Source

++ get-our
=/ m (strand ,ship)
^- form:m
|= tin=strand-input:strand
`[%done our.bowl.tin]

Example

;< our=@p bind:m get-our

get-entropy

Get some entropy.

Accepts

Nothing.

Produces

A @uvJ.

Source

++ get-entropy
=/ m (strand ,@uvJ)
^- form:m
|= tin=strand-input:strand
`[%done eny.bowl.tin]

Example

;< eny=@uvJ bind:m get-entropy

Misc

install-domain

Install a domain in Eyre, triggering the setup of an SSL certificate.

Accepts

A turf.

Produces

~

Source

++ install-domain
|= =turf
=/ m (strand ,~)
^- form:m
(send-raw-card %pass / %arvo %e %rule %turf %put turf)

Example

;< ~ bind:m (install-domain 'com' 'example' ~)

check-online

Require that a peer respond before timeout.

The peer is pinged with a "hi" and must ack the poke before the timeout.

Accepts

A pair of [ship @dr]. The @dr is the amount of time the peer has to respond before failure.

Produces

~

Source

++ check-online
|= [who=ship lag=@dr]
=/ m (strand ,~)
^- form:m
%+ (map-err ,~) |=(* [%offline *tang])
%+ (set-timeout ,~) lag
;< ~ bind:m
(poke [who %hood] %helm-hi !>(~))
(pure:m ~)

Example

;< ~ bind:m (check-online ~zod ~s10)

take-sign-arvo

Wait for a sign from Arvo.

Accepts

Nothing.

Produces

A pair of [wire sign-arvo].

Source

++ take-sign-arvo
=/ m (strand ,[wire sign-arvo])
^- form:m
|= tin=strand-input:strand
?+ in.tin `[%skip ~]
~
`[%wait ~]
::
[~ %sign *]
`[%done [wire sign-arvo]:u.in.tin]
==

Example

;< [=wire =sign-arvo] bind:m take-sign-arvo

Pokes

poke

Poke an agent, then await a positive ack.

Accepts

A pair of [dock cage], where the dock is the ship and agent you want to poke, and the cage is the data.

Produces

~

Source

++ poke
|= [=dock =cage]
=/ m (strand ,~)
^- form:m
=/ =card:agent:gall [%pass /poke %agent dock %poke cage]
;< ~ bind:m (send-raw-card card)
(take-poke-ack /poke)

Example

;< ~ bind:m (poke [~zod %foo] %noun !>(~))

raw-poke

Poke an agent then await a (n)ack.

This doesn't care whether the ack is positive or negative, unlike the ordinary poke.

Accepts

A pair of [dock cage], where the dock is the ship and agent to poke, and the cage is the data.

Produces

~

Source

++ raw-poke
|= [=dock =cage]
=/ m (strand ,~)
^- form:m
=/ =card:agent:gall [%pass /poke %agent dock %poke cage]
;< ~ bind:m (send-raw-card card)
=/ m (strand ,~)
^- form:m
|= tin=strand-input:strand
?+ in.tin `[%skip ~]
~
`[%wait ~]
::
[~ %agent * %poke-ack *]
?. =(/poke wire.u.in.tin)
`[%skip ~]
`[%done ~]
==

Example

;< ~ bind:m (raw-poke [~zod %foo] %noun !>(~))

raw-poke-our

Poke a local agent then await a (n)ack.

This doesn't care whether the ack is positive or negative, unlike the ordinary poke-our.

Accepts

A pair of [app=term =cage], where app is the local agent to poke and cage is the data.

Produces

~

Source

++ raw-poke-our
|= [app=term =cage]
=/ m (strand ,~)
^- form:m
;< =bowl:spider bind:m get-bowl
(raw-poke [our.bowl app] cage)

Example

;< ~ bind:m (raw-poke-our %foo %noun !>(~))

poke-our

Poke a local agent then await an ack.

Note this fails if it gets a nack back.

Accepts

A pair of [=term =cage] where term is the name of a local agent and cage is the data.

Produces

~

Source

++ poke-our
|= [=term =cage]
=/ m (strand ,~)
^- form:m
;< our=@p bind:m get-our
(poke [our term] cage)

Example

;< ~ bind:m (poke-our %foo %noun !>(~))

take-poke-ack

Take a poke ack on the given wire.

If the ack is a nack, the strand fails.

Accepts

A wire.

Produces

~

Source

++ take-poke-ack
|= =wire
=/ m (strand ,~)
^- form:m
|= tin=strand-input:strand
?+ in.tin `[%skip ~]
~ `[%wait ~]
[~ %agent * %poke-ack *]
?. =(wire wire.u.in.tin)
`[%skip ~]
?~ p.sign.u.in.tin
`[%done ~]
`[%fail %poke-fail u.p.sign.u.in.tin]
==

Example

;< ~ bind:m (take-poke-ack /foo)

take-poke

Wait for a poke with a particular mark.

Accepts

A mark.

Produces

A vase.

Source

++ take-poke
|= =mark
=/ m (strand ,vase)
^- form:m
|= tin=strand-input:strand
?+ in.tin `[%skip ~]
~
`[%wait ~]
::
[~ %poke @ *]
?. =(mark p.cage.u.in.tin)
`[%skip ~]
`[%done q.cage.u.in.tin]
==

Example

;< =vase bind:m (take-poke %noun)

Subscriptions

watch

Watch a subscription path on an agent, then await a positive watch ack.

Note this fails if it gets a watch nack back.

Accepts

A triple of [=wire =dock =path] where dock is the ship and agent, and path is the subscription path.

Produces

~

Source

++ watch
|= [=wire =dock =path]
=/ m (strand ,~)
^- form:m
=/ =card:agent:gall [%pass watch+wire %agent dock %watch path]
;< ~ bind:m (send-raw-card card)
(take-watch-ack wire)

Example

;< ~ bind:m (watch /foo [~zod %foo] /some/path)

watch-one

Subscribe to a watch path on an agent, take a single fact, then await a kick.

Accepts

A triple of [=wire =dock =path] where dock is a ship and agent, and path is the subscription path.

Produces

The cage of the received fact.

Source

++ watch-one
|= [=wire =dock =path]
=/ m (strand ,cage)
^- form:m
;< ~ bind:m (watch wire dock path)
;< =cage bind:m (take-fact wire)
;< ~ bind:m (take-kick wire)
(pure:m cage)

Example

;< [=mark =vase] bind:m (watch-one /foo [~zod %foo] /some/path)

watch-our

Subscribe to a watch path on a local agent, then wait for a positive ack.

This will fail if it gets a watch nack.

Accepts

A triple of [=wire =term =path] where term is the name of the agent and path is the subscription path.

Produces

~

Source

::
++ watch-our
|= [=wire =term =path]
=/ m (strand ,~)
^- form:m
;< our=@p bind:m get-our
(watch wire [our term] path)

Example

;< ~ bind:m (watch-our /foo %foo /some/path)

leave

Leave a subscription.

Accepts

A pair of [=wire =dock] where dock is the ship and agent in question.

Produces

~

Source

++ leave
|= [=wire =dock]
=/ m (strand ,~)
^- form:m
=/ =card:agent:gall [%pass watch+wire %agent dock %leave ~]
(send-raw-card card)

Example

;< ~ bind:m (leave /foo ~zod %foo)

leave-our

Unsubscribe from a local agent.

Accepts

A pair of [=wire =term] where term is the local agent.

Produces

~

Source

++ leave-our
|= [=wire =term]
=/ m (strand ,~)
^- form:m
;< our=@p bind:m get-our
(leave wire [our term])

Example

;< ~ bind:m (leave-our /foo %foo)

rewatch

Resubscribe on kick.

This waits for a kick on a given wire, then rewatches the given ship, agent and path on the same wire. It then waits for a positive watch ack.

Accepts

A triple of [=wire =dock =path] where dock is the ship and agent, and path is the subscription path.

Produces

~

Source

++ rewatch
|= [=wire =dock =path]
=/ m (strand ,~)
;< ~ bind:m ((handle ,~) (take-kick wire))
;< ~ bind:m (flog-text "rewatching {<dock>} {<path>}")
;< ~ bind:m (watch wire dock path)
(pure:m ~)

Exmaple

;< ~ bind:m (rewatch /foo [~zod %foo] /some/path)

take-fact-prefix

Wait for a subscription update on a wire.

Accepts

A wire as the prefix of what you expect. E.g. if /foo is given, a fact with a wire of /foo, /foo/bar, /foo/bar/baz, etc, will be accepted.

Produces

A cell of [wire cage].

Source

++ take-fact-prefix
|= =wire
=/ m (strand ,[path cage])
^- form:m
|= tin=strand-input:strand
?+ in.tin `[%skip ~]
~ `[%wait ~]
[~ %agent * %fact *]
?. =(watch+wire (scag +((lent wire)) wire.u.in.tin))
`[%skip ~]
`[%done (slag (lent wire) wire.u.in.tin) cage.sign.u.in.tin]
==

Example

;< [=wire =mark =vase] bind:m (take-fact-prefix /foo)

take-fact

Wait for a subscription update on a wire.

Accepts

The wire you want to listen on.

Produces

A cage.

Source

++ take-fact
|= =wire
=/ m (strand ,cage)
^- form:m
|= tin=strand-input:strand
?+ in.tin `[%skip ~]
~ `[%wait ~]
[~ %agent * %fact *]
?. =(watch+wire wire.u.in.tin)
`[%skip ~]
`[%done cage.sign.u.in.tin]
==

Example

;< [=mark =vase] bind:m (take-fact /foo)

take-kick

Wait for a subscription close.

Accepts

The wire you want to listen on.

Produces

~

Source

++ take-kick
|= =wire
=/ m (strand ,~)
^- form:m
|= tin=strand-input:strand
?+ in.tin `[%skip ~]
~ `[%wait ~]
[~ %agent * %kick *]
?. =(watch+wire wire.u.in.tin)
`[%skip ~]
`[%done ~]
==

Example

;< ~ bind:m (take-kick /foo)

take-watch-ack

Take a watch ack on a given wire.

If the watch ack is a nack, the strand fails.

Accepts

A wire.

Produces

~

Source

++ take-watch-ack
|= =wire
=/ m (strand ,~)
^- form:m
|= tin=strand-input:strand
?+ in.tin `[%skip ~]
~ `[%wait ~]
[~ %agent * %watch-ack *]
?. =(watch+wire wire.u.in.tin)
`[%skip ~]
?~ p.sign.u.in.tin
`[%done ~]
`[%fail %watch-ack-fail u.p.sign.u.in.tin]
==

Example

;< ~ bind:m (take-watch-ack /foo)

take-watch

Wait for a subscription request.

Accepts

Nothing.

Produces

The subscription path.

Source

++ take-watch
=/ m (strand ,path)
|= tin=strand-input:strand
?+ in.tin `[%skip ~]
~ `[%wait ~]
[~ %watch *]
`[%done path.u.in.tin]
==

Example

;< =path bind:m take-watch

Scries

scry

Scry an agent or vane.

Accepts

A pair of [=mold =path] where mold is the type returned and path has the following format:

/[vane letter and care]/[desk]/[rest of path after beak]

The strand implicitly fills in our and now in the beak.

Produces

Data of the type produced by the mold you specified.

Source

++ scry
|* [=mold =path]
=/ m (strand ,mold)
^- form:m
?> ?=(^ path)
?> ?=(^ t.path)
;< =bowl:spider bind:m get-bowl
%- pure:m
.^(mold i.path (scot %p our.bowl) i.t.path (scot %da now.bowl) t.t.path)

Example

;< has=? bind:m (scry ? %cu %base /gen/vats/hoon)

keen

Make a remote scry request.

Note this doesn't wait for a response, you'd have to use a separate take-tune strand to receive the result.

Accept

A pair of [=wire =spar:ames].

Produces

~

Source

++ keen
|= [=wire =spar:ames]
=/ m (strand ,~)
^- form:m
(send-raw-card %pass wire %arvo %a %keen spar)

Example

;< ~ bind:m (keen /foo ~sampel /c/x/4/base/sys/hoon/hoon)

take-tune

Wait for a remote scry result on a particular wire.

Accepts

A wire.

Produces

A [spar:ames (unit roar:ames)]

Source

++ take-tune
|= =wire
=/ m (strand ,[spar:ames (unit roar:ames)])
^- form:m
|= tin=strand-input:strand
?+ in.tin `[%skip ~]
~ `[%wait ~]
::
[~ %sign * %ames %tune ^ *]
?. =(wire wire.u.in.tin)
`[%skip ~]
`[%done +>.sign-arvo.u.in.tin]
==

Example

;< [spar roar=(unit roar)] bind:m (take-tune /foo)

Time

wait

Send a %wait to Behn and wait for the %wake.

Note there's also sleep to wait for a relative amount of time rather than having to specify an absolute time.

Accepts

A @da of when the timer should fire.

Produces

~

Source

++ wait
|= until=@da
=/ m (strand ,~)
^- form:m
;< ~ bind:m (send-wait until)
(take-wake `until)

Example

;< now=@da bind:m get-time
;< ~ bind:m (wait (add now ~s2))

sleep

Wait for a relative amount of time.

Accepts

A @dr.

Produces

~

Source

++ sleep
|= for=@dr
=/ m (strand ,~)
^- form:m
;< now=@da bind:m get-time
(wait (add now for))

Example

;< ~ bind:m (sleep ~s2)

send-wait

Send Behn a %wait but don't wait for the %wake.

Accepts

A @da.

Produces

~

Source

++ send-wait
|= until=@da
=/ m (strand ,~)
^- form:m
=/ =card:agent:gall
[%pass /wait/(scot %da until) %arvo %b %wait until]
(send-raw-card card)

Example

;< now=@da bind:m get-time
;< ~ bind:m (send-wait (add ~s2 now))

set-timeout

Make a strand fail if it takes too long.

Accepts

This takes the mold produced but the strand you're timing, and produces a gate. The gate takes a pair of the @dr timeout and the strand being timed.

Produces

Data of the type produced by the strand being timed.

Source

++ set-timeout
|* computation-result=mold
=/ m (strand ,computation-result)
|= [time=@dr computation=form:m]
^- form:m
;< now=@da bind:m get-time
=/ when (add now time)
=/ =card:agent:gall
[%pass /timeout/(scot %da when) %arvo %b %wait when]
;< ~ bind:m (send-raw-card card)
|= tin=strand-input:strand
=* loop $
?: ?& ?=([~ %sign [%timeout @ ~] %behn %wake *] in.tin)
=((scot %da when) i.t.wire.u.in.tin)
==
`[%fail %timeout ~]
=/ c-res (computation tin)
?: ?=(%cont -.next.c-res)
c-res(self.next ..loop(computation self.next.c-res))
?: ?=(%done -.next.c-res)
=/ =card:agent:gall
[%pass /timeout/(scot %da when) %arvo %b %rest when]
c-res(cards [card cards.c-res])
c-res

Example

;< ~ bind:m ((set-timeout ,~) ~s10 (poke-our %foo %noun !>(~)))

take-wake

Wait for a wake from Behn.

This is meant for internal use by wait, you'd not typically use it directly.

Accepts

A (unit @da). If the unit is non-null, it'll only accept a %wake whose wire is of the form /wait/(scot %da the-given-time). If the unit is null, it'll accept a %wake with a wire of /wait/(scot %da any-time).

Produces

~

Source

::
++ 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]
==

Example

;< now=@da bind:m get-time
=/ card=card:agent:gall [%pass /wait/(scot %da now) %arvo %b %wait now]
;< ~ bind:m (send-raw-card card)
;< ~ bind:m (take-wake `now)

Errors

retry

Retry a strand that produces a unit if the unit is null, with a backoff.

Accepts

retry first takes a result=mold of the return type and produces a gate. That gate takes two arguments:

  • crash-after=(unit @ud): the number of tries before failing.
  • computation: A strand that produces a (unit result).

Produces

The type of result.

Source

++ retry
|* result=mold
|= [crash-after=(unit @ud) computation=_*form:(strand (unit result))]
=/ m (strand ,result)
=| try=@ud
|- ^- form:m
=* loop $
?: =(crash-after `try)
(strand-fail %retry-too-many ~)
;< ~ bind:m (backoff try ~m1)
;< res=(unit result) bind:m computation
?^ res
(pure:m u.res)
loop(try +(try))

Example

=/ =hiss:eyre [(need (de-purl:html 'http://example.com')) %get ~ ~]
;< =httr:eyre bind:m ((retry httr:eyre) `3 (hiss-request hiss))

backoff

Wait for increasing amounts of time with each try.

Accepts

A pair of [try=@ud limit=@dr], specifying the current try count and the maximum amount of time to wait.

Produces

~

Source

++ backoff
|= [try=@ud limit=@dr]
=/ m (strand ,~)
^- form:m
;< eny=@uvJ bind:m get-entropy
%- sleep
%+ min limit
?: =(0 try) ~s0
%+ add
(mul ~s1 (bex (dec try)))
(mul ~s0..0001 (~(rad og eny) 1.000))

map-err

Rewrite a strand failure error.

Accepts

This function takes the return mold of the strand in question as its argument and returns a gate that takes two arguments:

  • f: a gate that takes a [term tang] and produces a [term tang]. This is the %error-tag and stack trace of the failure you're rewriting.
  • computation: the strand whose errors you're rewriting.

See the example below for usage.

Produces

Data of the type produced by the strand in question.

Source

++ map-err
|* computation-result=mold
=/ m (strand ,computation-result)
|= [f=$-([term tang] [term tang]) computation=form:m]
^- form:m
|= tin=strand-input:strand
=* loop $
=/ c-res (computation tin)
?: ?=(%cont -.next.c-res)
c-res(self.next ..loop(computation self.next.c-res))
?. ?=(%fail -.next.c-res)
c-res
c-res(err.next (f err.next.c-res))

Example

;< ~ bind:m
%+ (map-err ,~)
|= [=term =tang]
?: =(%poke-fail term)
[%foo tang]
[term tang]
(poke-our %foo %noun !>(~))

HTTP

send-request

Make an HTTP request via Iris, but don't wait for the response.

Accepts

A request:http.

Produces

~

Source

++ send-request
|= =request:http
=/ m (strand ,~)
^- form:m
(send-raw-card %pass /request %arvo %i %request request *outbound-config:iris)

Example

;< ~ bind:m (send-request %'GET' 'http://example.com' ~ ~)

send-cancel-request

Cancel a previous Iris HTTP request.

This sends it on the /request wire used by send-request. It won't work if the original request was on a different wire.

Accepts

Nothing.

Produces

~

Source

++ send-cancel-request
=/ m (strand ,~)
^- form:m
(send-raw-card %pass /request %arvo %i %cancel-request ~)

Example

;< ~ bind:m send-cancel-request

take-client-response

Take the HTTP response from a previous HTTP request made with send-request.

This listens on the /request wire, it won't work if you're made a request on a different wire.

Accepts

Nothing.

Produces

A client-response:iris.

Source

++ take-client-response
=/ m (strand ,client-response:iris)
^- form:m
|= tin=strand-input:strand
?+ in.tin `[%skip ~]
~ `[%wait ~]
::
[~ %sign [%request ~] %iris %http-response %cancel *]
::NOTE iris does not (yet?) retry after cancel, so it means failure
:- ~
:+ %fail
%http-request-cancelled
['http request was cancelled by the runtime']~
::
[~ %sign [%request ~] %iris %http-response %finished *]
`[%done client-response.sign-arvo.u.in.tin]
==

Example

;< res=client-response:iris bind:m take-client-response

take-maybe-sigh

Take a unitized raw HTTP response.

Accepts

Nothing

Produces

A (unit httr:eyre). The unit is null if we failed to receive a response.

Source

++ take-maybe-sigh
=/ m (strand ,(unit httr:eyre))
^- form:m
;< rep=(unit client-response:iris) bind:m
take-maybe-response
?~ rep
(pure:m ~)
:: XX s/b impossible
::
?. ?=(%finished -.u.rep)
(pure:m ~)
(pure:m (some (to-httr:iris +.u.rep)))

Example

;< res=(unit httr:eyre) bind:m take-maybe-sigh

take-maybe-response

Take a unitized HTTP response.

Accepts

Nothing

Produces

A (unit client-response:iris). The unit is null if we failed to receive a response.

Source

++ take-maybe-response
=/ m (strand ,(unit client-response:iris))
^- form:m
|= tin=strand-input:strand
?+ in.tin `[%skip ~]
~ `[%wait ~]
[~ %sign [%request ~] %iris %http-response %cancel *]
`[%done ~]
[~ %sign [%request ~] %iris %http-response %finished *]
`[%done `client-response.sign-arvo.u.in.tin]
==

Example

;< res=(unit client-response:iris) bind:m take-maybe-response

extract-body

Extract body from an HTTP response.

Accepts

A client-response:iris

Produces

A cord.

Source

++ extract-body
|= =client-response:iris
=/ m (strand ,cord)
^- form:m
?> ?=(%finished -.client-response)
%- pure:m
?~ full-file.client-response ''
q.data.u.full-file.client-response

fetch-cord

Get the HTTP response body from a URL.

Accepts

The URL in a tape.

Produces

A cord of the response body.

Source

++ fetch-cord
|= url=tape
=/ m (strand ,cord)
^- form:m
=/ =request:http [%'GET' (crip url) ~ ~]
;< ~ bind:m (send-request request)
;< =client-response:iris bind:m take-client-response
(extract-body client-response)

Example

;< bod=@t bind:m (fetch-cord "http://example.com")

fetch-json

Get some JSON from a URL.

Accepts

The URL as a tape.

Produces

A json structure.

Source

++ fetch-json
|= url=tape
=/ m (strand ,json)
^- form:m
;< =cord bind:m (fetch-cord url)
=/ json=(unit json) (de-json:html cord)
?~ json
(strand-fail %json-parse-error ~)
(pure:m u.json)

Example

;< =json bind:m (fetch-json "http://example.com")

hiss-request

Make a raw HTTP request, take a raw response.

Accepts

hiss:eyre

Produces

A (unit httr:eyre). The unit is null if we failed to receive a response.

Source

::
++ hiss-request
|= =hiss:eyre
=/ m (strand ,(unit httr:eyre))
^- form:m
;< ~ bind:m (send-request (hiss-to-request:html hiss))
take-maybe-sigh

Example

=/ =hiss:eyre [(need (de-purl:html 'http://example.com')) %get ~ ~]
;< res=(unit httr:eyre) bind:m (hiss-request hiss)

Build

build-file

Build a source file at the specified beam.

Accepts

A beam.

Produces

A (unit vase). The vase contains the compiled file, the unit is null if it failed.

Source

++ build-file
|= [[=ship =desk =case] =spur]
=* arg +<
=/ m (strand ,(unit vase))
^- form:m
;< =riot:clay bind:m
(warp ship desk ~ %sing %a case spur)
?~ riot
(pure:m ~)
?> =(%vase p.r.u.riot)
(pure:m (some !<(vase q.r.u.riot)))

Example

;< now=@da bind:m get-time
;< res=(unit vase) bind:m (build-file [~zod %base da+now] /gen/hood/hi/hoon)

build-file-hard

Build a source file at the specified beam, crashing if it fails.

Accepts

A beam.

Produces

A vase.

Source

++ build-file-hard
|= [[=ship =desk =case] =spur]
=* arg +<
=/ m (strand ,vase)
^- form:m
;< =riot:clay
bind:m
(warp ship desk ~ %sing %a case spur)
?> ?=(^ riot)
?> ?=(%vase p.r.u.riot)
(pure:m !<(vase q.r.u.riot))

Example

;< now=@da bind:m get-time
;< =vase bind:m (build-file-hard [~zod %base da+now] /gen/hood/hi/hoon)

build-mark

Build a dynamic mark core from file.

Accepts

A pair of [beak mark].

Produces

A dais:clay

Source

++ build-mark
|= [[=ship =desk =case] mak=mark]
=* arg +<
=/ m (strand ,dais:clay)
^- form:m
;< =riot:clay bind:m
(warp ship desk ~ %sing %b case /[mak])
?~ riot
(strand-fail %build-mark >arg< ~)
?> =(%dais p.r.u.riot)
(pure:m !<(dais:clay q.r.u.riot))

Example

;< now=@da bind:m get-time
;< =dais:clay bind:m (build-mark [~zod %base da+now] %noun)

build-tube

Build a dynamic mark conversion gate from file.

Accepts

A pair of [beak mars:clay]. A mars is a pair of the from and to mark.

Produces

A tube:clay

Source

++ build-tube
|= [[=ship =desk =case] =mars:clay]
=* arg +<
=/ m (strand ,tube:clay)
^- form:m
;< =riot:clay bind:m
(warp ship desk ~ %sing %c case /[a.mars]/[b.mars])
?~ riot
(strand-fail %build-tube >arg< ~)
?> =(%tube p.r.u.riot)
(pure:m !<(tube:clay q.r.u.riot))

Example

;< now=@da bind:m get-time
;< =tube:clay bind:m (build-tube [~zod %base da+now] %mime %txt)

build-nave

Build a static mark core from file.

Accepts

A pair of [beak mark].

Produces

A vase.

Source

++ build-nave
|= [[=ship =desk =case] mak=mark]
=* arg +<
=/ m (strand ,vase)
^- form:m
;< =riot:clay bind:m
(warp ship desk ~ %sing %e case /[mak])
?~ riot
(strand-fail %build-nave >arg< ~)
?> =(%nave p.r.u.riot)
(pure:m q.r.u.riot)

Example

;< now=@da bind:m get-time
;< =nave:clay bind:m (build-nave [~zod %base da+now] %txt)

build-cast

Build a static mark conversion gate from file.

Accepts

A pair of [beak mars:clay]. A mars is a pair of the from mark and to mark.

Source

++ build-cast
|= [[=ship =desk =case] =mars:clay]
=* arg +<
=/ m (strand ,vase)
^- form:m
;< =riot:clay bind:m
(warp ship desk ~ %sing %f case /[a.mars]/[b.mars])
?~ riot
(strand-fail %build-cast >arg< ~)
?> =(%cast p.r.u.riot)
(pure:m q.r.u.riot)

Example

;< now=@da bind:m get-time
;< =vase bind:m (build-cast [~zod %base da+now] %mime %txt)

eval-hoon

Evaluate some hoon and produce the result.

Accepts

A pair of [gen=hoon bez=(list beam)]. The gen argument is the hoon to be evaluated. If bez is empty, it will be evaluated against the standard ..zuse subject. If a list of beams are provided in bez, each one will be read from Clay, build, and pinned to the head of the subject, before gen is evaluated against it.

Produces

A vase of the result.

Source

++ eval-hoon
|= [gen=hoon bez=(list beam)]
=/ m (strand ,vase)
^- form:m
=/ sut=vase !>(..zuse)
|-
?~ bez
(pure:m (slap sut gen))
;< vax=vase bind:m (build-file-hard i.bez)
$(bez t.bez, sut (slop vax sut))

Example

;< =vase bind:m (eval-hoon !,(*hoon (add 1 1)))

Clay

warp

Raw read from Clay.

Accepts

A pair of ship and riff:clay.

Produces

A riot:clay.

Source

++ warp
|= [=ship =riff:clay]
=/ m (strand ,riot:clay)
;< ~ bind:m (send-raw-card %pass /warp %arvo %c %warp ship riff)
(take-writ /warp)

Example

;< now=@da bind:m get-time
;< =riot:clay bind:m (warp %base ~ %sing %x da+now /foo/txt)

read-file

Read a file from Clay.

Accepts

A beam.

Produces

A cage.

Source

++ read-file
|= [[=ship =desk =case] =spur]
=* arg +<
=/ m (strand ,cage)
;< =riot:clay bind:m (warp ship desk ~ %sing %x case spur)
?~ riot
(strand-fail %read-file >arg< ~)
(pure:m r.u.riot)

Example

;< now=@da bind:m get-time
;< =cage bind:m (read-file [~zod %base da+now] /foo/txt)

check-for-file

Check for the existence of a file in Clay.

Accepts

A beam.

Produces

A ? which is %.y if the file exists, and %.n if not.

Source

++ check-for-file
|= [[=ship =desk =case] =spur]
=/ m (strand ,?)
;< =riot:clay bind:m (warp ship desk ~ %sing %x case spur)
(pure:m ?=(^ riot))

Example

;< now=@da bind:m get-time
;< has=? bind:m (check-for-file [~zod %base da+now] /foo/txt)

list-tree

Get a list of all files in the given Clay directory.

Accepts

A beam.

Produces

A (list path).

Source

++ list-tree
|= [[=ship =desk =case] =spur]
=* arg +<
=/ m (strand ,(list path))
;< =riot:clay bind:m (warp ship desk ~ %sing %t case spur)
?~ riot
(strand-fail %list-tree >arg< ~)
(pure:m !<((list path) q.r.u.riot))

Example

;< now=@da bind:m get-time
;< paths=(list path) bind:m (list-tree [~zod %base da+now] /sys)

take-writ

Take a Clay read result.

Accepts

The wire to listen on.

Produces

A riot:clay

Source

++ take-writ
|= =wire
=/ m (strand ,riot:clay)
^- form:m
|= tin=strand-input:strand
?+ in.tin `[%skip ~]
~ `[%wait ~]
[~ %sign * ?(%behn %clay) %writ *]
?. =(wire wire.u.in.tin)
`[%skip ~]
`[%done +>.sign-arvo.u.in.tin]
==

Example

;< =riot-clay bind:m (take-writ /warp)

Main Loop

ignore

Try next on failure.

This produces a failure with an %ignore status, which main-loop uses to skip the strand and try the next one. This is of little use outside the context of a main-loop.

Accepts

Nothing.

Produces

Nothing.

Source

++ ignore
|= tin=strand-input:strand
`[%fail %ignore ~]

handle

Convert skips to %ignore failures.

This tells main-loop to try the next strand on skips. This would not be used outside of a main-loop.

Accepts

+handle takes a mold and produces a gate that takes another strand.

Produces

Data of the type produced by the given mold.

Source

++ handle
|* a=mold
=/ m (strand ,a)
|= =form:m
^- form:m
|= tin=strand-input:strand
=/ res (form tin)
=? next.res ?=(%skip -.next.res)
[%fail %ignore ~]
res

Example

;< =vase bind:m ((handle ,vase) (take-poke %foo))

main-loop

A main-loop can be used for three things:

  1. create a loop.
  2. try the same input against multiple strands.
  3. Queue input on %skip and then dequeue from the beginning on %done.

Accepts

It first accepts a mold, specifying the return type, and produces a gate. The gate produced takes a list of gates that take an argument of the specified mold, and produce the form of a strand of that mold.

Produces

Data of the type produced by the given mold.

Source

Click to expand

++ main-loop
|* a=mold
=/ m (strand ,~)
=/ m-a (strand ,a)
=| queue=(qeu (unit input:strand))
=| active=(unit [in=(unit input:strand) =form:m-a forms=(list $-(a form:m-a))])
=| state=a
|= forms=(lest $-(a form:m-a))
^- form:m
|= tin=strand-input:strand
=* top `form:m`..$
=. queue (~(put to queue) in.tin)
|^ (continue bowl.tin)
::
++ continue
|= =bowl:strand
^- output:m
?> =(~ active)
?: =(~ queue)
`[%cont top]
=^ in=(unit input:strand) queue ~(get to queue)
^- output:m
=. active `[in (i.forms state) t.forms]
^- output:m
(run bowl in)
::
++ run
^- form:m
|= tin=strand-input:strand
^- output:m
?> ?=(^ active)
=/ res (form.u.active tin)
=/ =output:m
?- -.next.res
%wait `[%wait ~]
%skip `[%cont ..$(queue (~(put to queue) in.tin))]
%cont `[%cont ..$(active `[in.u.active self.next.res forms.u.active])]
%done (continue(active ~, state value.next.res) bowl.tin)
%fail
?: &(?=(^ forms.u.active) ?=(%ignore p.err.next.res))
%= $
active `[in.u.active (i.forms.u.active state) t.forms.u.active]
in.tin in.u.active
==
`[%fail err.next.res]
==
[(weld cards.res cards.output) next.output]
--

Example

See the separate main-loop example or the echo example below.


echo

Echo a given message to the terminal every 2 seconds until told to stop.

Accepts

This strand takes nothing directly, but expects a poke with a mark of %echo and vase containing a tape with the message to echo. To finish, it expects a poke with a mark of %over.

Produces

~

Source

++ echo
=/ m (strand ,~)
^- form:m
%- (main-loop ,~)
:~ |= ~
^- form:m
;< =vase bind:m ((handle ,vase) (take-poke %echo))
=/ message=tape !<(tape vase)
%- (slog leaf+"{message}..." ~)
;< ~ bind:m (sleep ~s2)
%- (slog leaf+"{message}.." ~)
(pure:m ~)
::
|= ~
^- form:m
;< =vase bind:m ((handle ,vase) (take-poke %over))
%- (slog leaf+"over..." ~)
(pure:m ~)
==

Printing

flog

Send a wrapped Dill task to Dill.

Accepts

A flog:dill

Produces

~

Source

++ flog
|= =flog:dill
=/ m (strand ,~)
^- form:m
(send-raw-card %pass / %arvo %d %flog flog)

Example

;< ~ bind:m (flog %text "foo")

flog-text

Print a message to the terminal via Dill.

Accepts

A tape.

Produces

~

Source

++ flog-text
|= =tape
=/ m (strand ,~)
^- form:m
(flog %text tape)

Example

;< ~ bind:m (flog-text "foo")

flog-tang

Print a tang to the terminal via Dill.

Accepts

A tang

Produces

~

Source

++ flog-tang
|= =tang
=/ m (strand ,~)
^- form:m
=/ =wall
(zing (turn (flop tang) (cury wash [0 80])))
|- ^- form:m
=* loop $
?~ wall
(pure:m ~)
;< ~ bind:m (flog-text i.wall)
loop(wall t.wall)

Example

;< ~ bind:m (flog-tang 'foo' 'bar' 'baz' ~)

trace

Slog a tang to the terminal.

Accepts

A tang.

Produces

~

Source

++ trace
|= =tang
=/ m (strand ,~)
^- form:m
(pure:m ((slog tang) ~))

Example

;< ~ bind:m (trace 'foo' 'bar' 'baz' ~)

app-message

Print a message to the terminal tagged with an app name, like:

my-app: foo bar baz

Then, optionally, print a tang.

Accepts

A triple of [term cord tang]. The term is the app name, the cord is the message, and the tang is any traceback.

Produces

~

Source

++ app-message
|= [app=term =cord =tang]
=/ m (strand ,~)
^- form:m
=/ msg=tape :(weld (trip app) ": " (trip cord))
;< ~ bind:m (flog-text msg)
(flog-tang tang)

Example

;< ~ bind:m (app-message %foo 'foo bar baz' ~)

Threads

send-thread

Run an inline thread via Khan.

Accepts

A triple of:

  • bear:khan: desk or beak.
  • shed:khan: the thread itself.
  • wire: the wire for responses from Khan.

Produces

~

Source

++ send-thread
|= [=bear:khan =shed:khan =wire]
=/ m (strand ,~)
^- form:m
(send-raw-card %pass wire %arvo %k %lard bear shed)

start-thread

Start a child thread.

Accepts

A term, the name of a thread in /ted of this desk.

Produces

A tid:spider, the ID of the child thread.

Source

++ start-thread
|= file=term
=/ m (strand ,tid:spider)
;< =bowl:spider bind:m get-bowl
(start-thread-with-args byk.bowl file *vase)

Example

;< ~ bind:m (start-thread %foo)

start-thread-with-args

Start a child thread with arguments.

Accepts

A triple of:

  • beak: the ship/desk/case where the thread is located.
  • term: the name of the thread in /ted of the given desk.
  • vase: the start argument.

Produces

A tid:spider, the ID of the child thread.

Source

++ start-thread-with-args
|= [=beak file=term args=vase]
=/ m (strand ,tid:spider)
^- form:m
;< =bowl:spider bind:m get-bowl
=/ tid
(scot %ta (cat 3 (cat 3 'strand_' file) (scot %uv (sham file eny.bowl))))
=/ poke-vase !>(`start-args:spider`[`tid.bowl `tid beak file args])
;< ~ bind:m (poke-our %spider %spider-start poke-vase)
;< ~ bind:m (sleep ~s0) :: wait for thread to start
(pure:m tid)

Example

;< now=@da bind:m get-time
;< ~ bind:m (start-thread-with-args [~zod %base da+now] %foo !>(~))

thread-result

Type definition of a thread result.

Source

+$ thread-result
(each vase [term tang])

await-thread

Start a thread with an argument, then await its result.

Accepts

A pair of [term vase] where term is the name of a thread in /ted of this desk, and vase contains the start argument.

Produces

A thread-result

Source

++ await-thread
|= [file=term args=vase]
=/ m (strand ,thread-result)
^- form:m
;< =bowl:spider bind:m get-bowl
=/ tid (scot %ta (cat 3 'strand_' (scot %uv (sham file eny.bowl))))
=/ poke-vase !>(`start-args:spider`[`tid.bowl `tid byk.bowl file args])
;< ~ bind:m (watch-our /awaiting/[tid] %spider /thread-result/[tid])
;< ~ bind:m (poke-our %spider %spider-start poke-vase)
;< ~ bind:m (sleep ~s0) :: wait for thread to start
;< =cage bind:m (take-fact /awaiting/[tid])
;< ~ bind:m (take-kick /awaiting/[tid])
?+ p.cage ~|([%strange-thread-result p.cage file tid] !!)
%thread-done (pure:m %& q.cage)
%thread-fail (pure:m %| ;;([term tang] q.q.cage))
==

Example

;< =thread-result bind:m (await-thread %foo !>(~))