Examples of compositional combinator usage (original) (raw)

Consider printing the same message ten times:

: print-10 ( -- ) 10 [ "Hello, world." print ] times ;

if we wanted to abstract out the message into a parameter, we could keep it on the stack between iterations:

: print-10 ( message -- ) 10 [ dup print ] times drop ;

However, keeping loop-invariant values on the stack doesn't always work out nicely. For example, a word to subtract a value from each element of a sequence:

: subtract-n ( seq n -- seq' ) swap [ over - ] map nip ;

Three shuffle words are required to pass the value around. Instead, the loop-invariant value can be partially applied to a quotation using curry, yielding a new quotation that is passed to map:

USING: sequences prettyprint ; : subtract-n ( seq n -- seq' ) [ - ] curry map ; { 10 20 30 } 5 subtract-n .
{ 5 15 25 }

Now consider the word that is dual to the one above; instead of subtracting n from each stack element, it subtracts each element from n.

One way to write this is with a pair of swaps:

: n-subtract ( n seq -- seq' ) swap [ swap - ] curry map ;

Since this pattern comes up often, with encapsulates it:

: n-subtract ( n seq -- seq' ) [ - ] with map ; 30 { 10 20 30 } n-subtract .
{ 20 10 0 }

See also
Examples of fried quotations