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]
    

    ++join

    Constructs a new list, placing sep between every element of lit.

    Accepts

    sep is a noun.

    lit is a list.

    Produces

    a list.

    Source

        ++  join
          |*  [sep=* lit=(list)]
          =.  sep  `_?>(?=(^ lit) i.lit)`sep
          ?~  lit  ~
          =|  out=(list _?>(?=(^ lit) i.lit))
          |-  ^+  out
          ?~  t.lit
            (flop [i.lit out])
          $(out [sep i.lit out], lit t.lit)
    

    Examples

        > (join ' ' "hoon")
        "h o o n"
    
        > (join 0 `(list @)`~[1 2 3])
        ~[1 0 2 0 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=1 t=~[2]]
    
        > (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

    a is an atom.

    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

    a is an atom.

    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
    

    ++snoc

    Append

    Accepts a ++list a and a noun b, producing the list of b appended to a.

    Accepts

    a is a list.

    b is a noun.

    Produces

    Produces a list of b appended to a.

    Source

        ++  snoc
          |*  [a/(list) b/*]
          (weld a ^+(a [b]~))
    

    Examples

        > `tape`(zing (snoc `(list tape)`~["a" "bc" "def"] "g"))
        "abcdefg"
        > (snoc `(list @ud)`~[1 2 3] 4)
        ~[1 2 3 4]
    

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

    a is a list.

    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

    a is an atom.

    b is an atom.

    c is a list.

    Produces

    A list of the same type as c.

    Source

        ++  swag
          |*  [[a=@ b=@] 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

    a is a list.

    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]