retroforth/doc/QuotesAndCombinators.md
crc e549b4ced6 no longer use ```` for code blocks; this fence sequence will be used for embedded tests in a later update
FossilOrigin-Name: dfed0de00b8d63672a882b79c4951cce0076007ef208c063b2f4e54fe9bd08f8
2018-04-25 16:57:28 +00:00

104 lines
2.1 KiB
Markdown

# Quotes and Combinators
RETRO makes extensive use of two elements that need some explanation. These
are called quotes and combinators.
A *quote* is an anonymous function. They are nestable and can be created at
any time.
Example:
~~~
#12 [ dup * ] call
~~~
In this, the code stating with `[` and ending with `]` is the quote. Here
it's just `call`ed immediately, but you can also pass it to other words.
We use the word *combinator* to refer to words that operate on quotes.
You'll use quotes and combinators extensively for controlling the flow of
execution. This begins with conditionals.
Assuming that we have a flag on the stack, you can run a quote if the
flag is `TRUE`:
~~~
#1 #2 eq?
[ 'True! puts ] if
~~~
Or if it's `FALSE`:
~~~
#1 #2 eq?
[ 'Not_true! puts ] -if
~~~
There's also a `choose` combinator:
~~~
#1 #2 eq?
[ 'True! puts ]
[ 'Not_true! puts ] choose
~~~
RETRO also uses combinators for loops:
A counted loop takes a count and a quote:
~~~
#0 #100 [ dup putn sp n:inc ] times
~~~
You can also loop while a quote returns a flag of `TRUE`:
~~~
#0 [ n:inc dup #100 lt? ] while
~~~
Or while it returns `FALSE`:
~~~
#100 [ n:dec dup n:zero? ] until
~~~
In RETRO you can also use combinators to iterate over data structures. For
instance, many structures provide a `for-each` combinator which can be run
once for each item in the structure. E.g., with a string:
~~~
'Hello [ putc ] s:for-each
~~~
Moving further, combinators are also used for filters and operations on
data. Again with strings:
~~~
'Hello_World! [ c:-vowel? ] s:filter
~~~
This runs `s:filter` which takes a quote returning a flag. For each `TRUE`
it appends the character into a new string, while `FALSE` results are
discarded.
You might also use a `map`ping combinator to update a data set:
~~~
'Hello_World [ c:to-upper ] s:map
~~~
This takes a quote that modifies a value which is then used to build a
new string.
There are many more combinators. Look in the Glossary to find them. Some
notable ones include:
bi
bi*
bi@
tri
tri*
tri@
dip
sip