FossilOrigin-Name: 0b0cd20ed69027a7d9b5f2d905d7b9e033e2976208385652d888da35432a4482
2.1 KiB
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! s:put ] if
Or if it's FALSE
:
#1 #2 eq?
[ 'Not_true! s:put ] -if
There's also a choose
combinator:
#1 #2 eq?
[ 'True! s:put ]
[ 'Not_true! s:put ] choose
RETRO also uses combinators for loops:
A counted loop takes a count and a quote:
#0 #100 [ dup n:put 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 [ c:put ] 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