2b: List Logic

++fand

All indices in list

Produces the indices of all occurrences of nedl in hstk as a list of atoms.

Accepts

nedl is a list.

hstk is a list.

Produces

A list.

Source

    ++  fand
      ~/  %fand
      |=  [nedl=(list) hstk=(list)]
      =|  i=@ud
      =|  fnd=(list @ud)
      |-  ^+  fnd
      =+  [n=nedl h=hstk]
      |-
      ?:  |(?=($~ n) ?=($~ h))
        (flop fnd)
      ?:  =(i.n i.h)
        ?~  t.n
          ^$(i +(i), hstk +.hstk, fnd [i fnd])
        $(n t.n, h t.h)
      ^$(i +(i), hstk +.hstk)

Examples

    > (fand ~[3] ~[1 2 3])
    ~[2]

    > (fand ~[4] ~[1 2 3])
    ~

    > (fand ~['a'] "cbabab")
    ~[2 4]

    > (fand "ba" "cbabab")
    ~[1 3]

++find

First index in list

Produces the index of the first occurrence of nedl in hstk as the unit of an atom.

Accepts

nedl is a list.

hstk is a list.

Produces

The unit of an atom.

Source

    ++  find
      ~/  %find
      |=  [nedl=(list) hstk=(list)]
      =|  i=@ud
      |-   ^-  (unit @ud)
      =+  [n=nedl h=hstk]
      |-
      ?:  |(?=($~ n) ?=($~ h))
         ~
      ?:  =(i.n i.h)
        ?~  t.n
          `i
        $(n t.n, h t.h)
      ^$(i +(i), hstk +.hstk)

Examples

    > (find [3]~ ~[1 2 3])
    [~ u=2]

    > (find [4]~ ~[1 2 3])
    ~

    > (find ['c']~ "cbabab")
    [~ u=0]

    > (find "ab" "cbabab")
    [~ u=1]

    > (find "bab" "cbabab")
    [~ u=2]

++flop

Reverse

Produces the list a in reverse order.

Accepts

a is a list.

Produces

A list.

Source

    ++  flop
      ~/  %flop
      |*  a=(list)
      =>  .(a (homo a))
      ^+  a
      =+  b=`_a`~
      |-
      ?~  a  b
      $(a t.a, b [i.a b])

Examples

    > =a [1 2 3 ~]
    > (flop a)
    ~[3 2 1]

    > (flop (flop a))
    ~[1 2 3]

++gulf

List from range

Produces a list composed of each consecutive integer starting from a and ending with b. a and b are themselves included.

Accepts

a is an atom.

b is an atom.

Produces

a list.

Source

    ++  gulf
      |=  [a=@ b=@]
      ^-  (list @)
      ?:(=(a +(b)) ~ [a $(a +(a))])

Examples

    > (gulf 1 6)
    ~[1 2 3 4 5 6]

    > `(list @t)`(gulf 99 106)
    <|c d e f g h i j|>

++homo

Homogenize

Produces a list whose type is a fork of all the contained types in the list a. Used when you want to make all the types of the elements of a list the same.

Accepts

a is a list.

Produces

a list.

Source

    ++  homo
      |*  a=(list)
      ^+  =<  $
        |%  +-  $  ?:(*? ~ [i=(snag 0 a) t=$])
        --
      a

Examples

    > lyst
    [i=1 t=[i=97 t=[i=2 t=[i=98 t=[i=[~ u=10] t=~]]]]]

    > (homo lyst)
    ~[1 97 2 98 [~ u=10]]

    > =a (limo [1 2 3 ~])
    > a
    [i=1 t=[i=2 t=[i=3 t=~]]]

    > (homo a)
    ~[1 2 3]

++lent

List length

Produces the length of any list a as an atom.

Accepts

a is a list.

Produces

an atom.

Source

    ++  lent
      ~/  %lent
      |=  a=(list)
      ^-  @
      =+  b=0
      |-
      ?~  a  b
      $(a t.a, b +(b))

Examples

    > (lent [1 2 3 4 ~]))
    4

    > (lent [1 'a' 2 'b' (some 10) ~])
    5

++levy

Logical "and" on list

Computes the Boolean logical "and" on the results of gate b applied to each individual element in list a.

Accepts

a is a list.

b is a gate.

Produces

A boolean.

Source

    ++  levy
      ~/  %levy                                             ::  all of
      |*  [a=(list) b=$-(* ?)]
      |-  ^-  ?
      ?~  a  &
      ?.  (b i.a)  |
      $(a t.a)

Examples

    > =a |=(a=@ (lte a 1))
    > (levy `(list @)`[0 1 2 1 ~] a)
    %.n

    > =a |=(a=@ (lte a 3))
    > (levy `(list @)`[0 1 2 1 ~] a)
    %.y

++lien

Logical "or" on list

Computes the Boolean logical "or" on the results of applying gate b to every element of ++list a.

Accepts

a is a list.

b is a gate.

Source

    ++  lien
      ~/  %lien
      |*  [a=(list) b=$-(* ?)]
      |-  ^-  ?
      ?~  a  |
      ?:  (b i.a)  &
      $(a t.a)

Examples

    > =a |=(a=@ (gte a 1))
    > (lien `(list @)`[0 1 2 1 ~] a)
    %.y

    > =a |=(a=@ (gte a 3))
    > (lien `(list @)`[0 1 2 1 ~]) a)
    %.n

++limo

List Constructor

Turns a null-terminated tuple into a list.

Accepts

a is a null-terminated tuple.

Produces

A ++list.

Source

    ++  limo                                                ::  listify
      |*  a=*
      ^+  =<  $
        |%  +-  $  ?~(a ~ ?:(_? i=-.a t=$ $(a +.a)))
        --
      a

Examples

    > (limo [1 2 3 ~])
    [i=1 t=[i=2 t=[i=3 t=~]]]

++murn

Maybe transform

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 ~.

Accepts

a is a list.

b is a gate that produces a unit.

Produces

A unit.

Source

    ++  murn                                                ::  maybe transform
      ~/  %murn
      |*  [a=(list) b=$-(* (unit))]
      |-
      ?~  a  ~
      =+  c=(b i.a)
      ?~  c
        $(a t.a)
      [i=u.c t=$(a t.a)]

Examples

    > =a |=(a=@ ?.((gte a 2) ~ (some (add a 10))))
    > (murn `(list @)`[0 1 2 3 ~] a)
    [i=12 t=[i=13 t=~]]

++oust

Remove

Removes elements from list c beginning at inclusive index a, removing b number of elements.

Accepts

c is a list.

Produces

A ++list.

Source

    ++  oust                                                ::  remove
      ~/  %oust
      |*  [[a=@ b=@] c=(list)]
      (weld (scag a c) (slag (add a b) c))

Examples

    > (oust [4 5] "good day, urbit!")
    "good urbit!"

    > (oust [2 2] `(list @)`[1 2 3 4 ~])
    ~[1 2]

++reap

Replicate

Replicate: produces a list containing a copies of b.

Accepts

a is an atom.

b is a noun.

Produces

A list.

Source

    ++  reap                                                ::  replicate
      ~/  %reap
      |*  [a=@ b=*]
      |-  ^-  (list _b)
      ?~  a  ~
      [b $(a (dec a))]

Examples

    > (reap 20 %a)
    ~[%a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a %a]

    > (reap 5 ~s1)
    ~[~s1 ~s1 ~s1 ~s1 ~s1]

    > `@dr`(roll (reap 5 ~s1) add)
    ~s5

++reel

Right fold

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.

(To "slam" means to call a gate and give it a sample/samples. In this instance, a is the list of samples that are given to the gate b.)

Accepts

a is a list.

b is a binary gate.

Produces

The accumulator, which is a noun.

Source

    ++  reel
      ~/  %reel
      |*  [a=(list) b=_|=([* *] +<+)]
      |-  ^+  +<+.b
      ?~  a
        +<+.b
      (b i.a $(a t.a))

Examples

    > =sum =|([p=@ q=@] |.((add p q)))
    > (reel (limo [1 2 3 4 5 ~]) sum)
    15

    > =a =|([p=@ q=@] |.((sub p q)))
    > (reel (limo [6 3 1 ~]) a)
    4

    > (reel (limo [3 6 1 ~]) a)
    ! subtract-underflow
    ! exit

++roll

Left fold

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.

(To "slam" means to call a gate and give it a sample/samples. In this instance, a is the list of samples that are given to the gate b.)

Accepts

a is a list.

b is a binary gate.

Produces

The accumulator, which is a noun.

Source

    ++  roll                                                ::  left fold
      ~/  %roll
      |*  [a=(list) b=_|=([* *] +<+)]
      |-  ^+  +<+.b
      ?~  a
        +<+.b
      $(a t.a, b b(+<+ (b i.a +<+.b)))

Examples

    > =sum =|([p=@ q=@] |.((add p q)))
    > (roll (limo [1 2 3 4 5 ~]) sum)
    q=15

    > =a =|([p=@ q=@] |.((sub p q)))
    > (roll (limo [6 3 1 ~]) a)
    ! subtract-underflow
    ! exit

    > (roll (limo [1 3 6 ~]) a)
    q=4

++scag

Prefix

Accepts an atom a and list b, producing the first a elements of the front of the list.

Accepts

a is an atom.

b is a list.

Produces

A list of the same type as b.

Source

    ++  scag                                                ::  prefix
      ~/  %scag
      |*  [a=@ b=(list)]
      |-  ^+  b
      ?:  |(?=(~ b) =(0 a))  ~
      [i.b $(b t.b, a (dec a))]

Examples

    > (scag 2 `(list @)`[1 2 3 4 ~])
    [i=0 t=~[1]]

    > (scag 10 `(list @)`[1 2 3 4 ~])
    [i=1 t=~[2 3 4]]

++skid

Separate

Separates a list a into two lists - Those elements of a who produce true when slammed to gate b and those who produce %.n.

(To "slam" means to call a gate and give it a sample/samples. In this instance, a is the list of samples that are given to the gate b.)

Accepts

a is a list.

b is a gate that accepts one argument and produces a flag.

Produces

A cell of two lists.

Source

    ++  skid                                                ::  separate
      ~/  %skid
      |*  [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]])

Examples

    > =a |=(a=@ (gth a 1))
    > (skid `(list @)`[0 1 2 3 ~]) a)
    (skid `(list @)`[0 1 2 3 ~]) a)

++skim

Suffix

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.

Accepts

a is a list.

b is a gate that accepts one argument and produces a boolean.

Produces

A flag.

Source

    ++  skim                                                ::  only
      ~/  %skim
      |*  [a=(list) b=$-(* ?)]
      |-
      ^+  a
      ?~  a  ~
      ?:((b i.a) [i.a $(a t.a)] $(a t.a))

Examples

    > =a |=(a=@ (gth a 1))
    > (skim `(list @)`[0 1 2 3 ~] a)
    [i=2 t=~[3]]

++skip

Except

Cycles through the members of list a, passing them to a gate b. Produces a list of all of the members that produce %.n. Inverse of skim.

Accepts

a is a list.

b is a gate that accepts one argument and produces a flag.

Produces

A list of the same type as a.

Source

    ++  skip                                                ::  except
      ~/  %skip
      |*  [a=(list) b=$-(* ?)]
      |-
      ^+  a
      ?~  a  ~
      ?:((b i.a) $(a t.a) [i.a $(a t.a)])

Examples

    > =a |=(a=@ (gth a 1))
    > (skip `(l)`[0 1 2 3 ~]) a)
    [i=0 t=[i=1 t=~]]

++slag

Suffix

Accepts an atom a and list b, producing the remaining elements from b starting at a.

Accepts

b is a list.

Produces

A list of the same type as b.

Source

    ++  slag                                                ::  suffix
      ~/  %slag
      |*  [a=@ b=(list)]
      |-  ^+  b
      ?:  =(0 a)  b
      ?~  b  ~
      $(b t.b, a (dec a))

Examples

    > (slag 2 (limo [1 2 3 4 ~]))
    [i=3 t=[i=4 t=~]]
    > (slag 1 (limo [1 2 3 4 ~]))
    [i=2 t=[i=3 t=[i=4 t=~]]]

++snag

Index

Accepts an atom a and a ++list b, producing the element at the index of aand failing if the list is null. Lists are 0-indexed.

Accepts

b is a list.

Produces

Produces an element of b, or crashes if no element exists at that index.

Source

    ++  snag                                                ::  index
      ~/  %snag
      |*  [a=@ b=(list)]
      |-
      ?~  b
        ~|('snag-fail' !!)
      ?:  =(0 a)  i.b
      $(b t.b, a (dec a))

Examples

    > (snag 2 "asdf")
    ~~d
    > (snag 0 `(list @ud)`~[1 2 3 4])
    1

++sort

Quicksort

Quicksort: accepts a ++list a and a gate b which accepts two nouns and produces a flag. ++sort then produces a list of the elements of a, sorted according to b.

Accepts

b is a gate that accepts two nouns and produces a boolean.

Produces

A list

Source

    ++  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))))]

Examples

        > =a =|([p/@ q/@] |.((gth p q)))
        > (sort (limo [0 1 2 3 ~]) a)
        ~[3 2 1 0]

++spin

Gate to list, with state

Accepts a ++list a, a gate b, and some state c. Produces a list with the gate applied to each element of the original list. b is called with a tuple -- the head is an element of a and the tail is the state c, and should produce a tuple of the transformed element and the (potentially modified) state c.

Accepts

a is a ++list.

b is a gate.

c is a noun.

Produces

A list.

Source

    ++  spin
      ~/ %spin
      |* [a=(list) b=* c=_|=(^ [** +<+])]
      => .(c `$-([_?>(?=(^ a) i.a) _b] [_-:(c) _b])`c)
      =/ acc=(list _-:(c)) ~
      |- ^- (pair _acc _b)
      ?~  a
        [(flop acc) b]
      =^ res b (c i.a b)
      $(acc [res acc], a t.a)

Examples

    > %^  spin  (limo ~[4 5 6])         ::  trivial example -- does nothing with the state
        |=([n=@ a=@] [n a])
      0
    ~[4 5 6]

    > %^  spin  (limo ~[4 5 6])         ::  `p` as the index and `q` as the list element
        |=([n=@ a=@] [`(pair)`[a n] +(a)])
      0
    ~[[p=0 q=4] [p=1 q=5] [p=2 q=6]]

    > %^  spin  (reap 10 0)             :: Create 10 random numbers less than `10`
      |=([n=@ rng=_og] (rads:rng 10))
      ~(. og eny)
    ~[5 5 9 4 1 7 9 9 9 6]

Discussion

(~(rads og eny) 2) creates a random number less than 2, seeding the RNG with entropy (eny). The head of the product is the random number, the tail is the continuation of the RNG.


++spun

Gate to list, with state

Accepts a list a and a gate b. c is internal state, initially derived by bunting the tail of the sample of gate b, instead of being passed in explicitly as in ++spin. Produces a list with the gate applied to each element of the original list. b is called with a tuple -- the head is an element of a and the tail is the state c, and should produce a tuple of the transformed element and the (potentially modified) state c.

Accepts

a is a ++list.

b is a gate.

Produces

A list.

Source

    ++  spun
      ~/ %spun
      |* [a=(list) b=_|=(^ [** +<+])]
      p:(spin a +<+.b b)

Examples

    > %+  spun  (limo ~[4 5 6])            ::  `p` as the index and `q` as the list element
      |=([n=@ a=@] [`(pair)`[a n] +(a)])
    ~[[p=0 q=4] [p=1 q=5] [p=2 q=6]]

    > =l (limo ~[7 8 9])
    > %+  spun  (limo ~[4 5 6])            ::  joins two lists into a list of pairs
      |=([n=@ a=@] [`(pair)`[(snag a l) n] +(a)])
    ~[[p=7 q=4] [p=8 q=5] [p=9 q=6]]

++swag

Infix

Similar to substr in Javascript: extracts a string infix, beginning at inclusive index a, producing b number of characters.

Accepts

c is a list.

Produces

A list of the same type as c.

Source

    ++  swag
      |*  [[a=@ a=@] c=(list)]
      (scag +<-> (slag +<-< c))

Examples

    > (swag [2 5] "roly poly")
    "ly po"

    > (swag [2 2] (limo [1 2 3 4 ~]))
    [i=3 t=[i=4 t=~]]

++turn

Gate to list

Accepts a ++list a and a gate b. Produces a list with the gate applied to each element of the original list.

Accepts

b is a gate.

Produces

A list.

Source

    ++  turn
      ~/  %turn
      |*  [a=(list) b=gate]
      |-
      ?~  a  ~
      [i=(b i.a) t=$(a t.a)]

Examples

    > (turn (limo [104 111 111 110 ~]) @t)
    <|h o o n|>

    > =a |=(a=@ (add a 4))
    > (turn (limo [1 2 3 4 ~]) a)
    ~[5 6 7 8]

Discussion

turn is Hoon's version of 'map' in Haskell.


++weld

Concatenate

Concatenate two ++lists a and b.

Accepts

a and b are lists.

Source

    ++  weld
      ~/  %weld
      |*  [a=(list) b=(list)]
      =>  .(a ^.(homo a), b ^.(homo b))
      |-  ^+  b
      ?~  a  b
      [i.a $(a t.a)]

Examples

    > (weld "urb" "it")
    ~[~~u ~~r ~~b ~~i ~~t]

    > (weld (limo [1 2 ~]) (limo [3 4 ~]))
    ~[1 2 3 4]

++welp

Perfect weld

Concatenate two ++lists a and b without losing their type information to homogenization.

Accepts

a is a list.

b is a list.

Produces

A list.

Source

    ++  welp
      =|  [* *]
      |%
      +-  $
        ?~  +<-
          +<-(. +<+)
        +<-(+ $(+<- +<->))
      --

Examples

    > (welp "foo" "bar")
    "foobar"

    > (welp ~[60 61 62] ~[%a %b %c])
    [60 61 62 %a %b %c ~]

    > ? (welp ~[60 61 62] ~[%a %b %c])
      {@ud @ud @ud $a $b $c $~}
    [60 61 62 %a %b %c ~]

    > (welp [sa+1 so+2 ~] si=3)
    [[%sa 1] [%so 2] si=3]

++zing

Cons

Turns a ++list of lists into a single list by promoting the elements of each sublist into the higher.

Accepts

A list of lists.

Produces

A list.

Source

    ++  zing
      =|  *
      |%
      +-  $
        ?~  +<
          +<
        (welp +<- $(+< +<+))
      --

Examples

    > (zing (limo [(limo ['a' 'b' 'c' ~]) (limo ['e' 'f' 'g' ~]) (limo ['h' 'i' 'j' ~]) ~]))
    ~['a' 'b' 'c' 'e' 'f' 'g' 'h' 'i' 'j']

    > (zing (limo [(limo [1 'a' 2 'b' ~]) (limo [3 'c' 4 'd' ~]) ~]))
    ~[1 97 2 98 3 99 4 100]