Using anonymous functions in Uxntal
In the context of Uxntal, lambdas is a label designated by a curly bracket that points to its associated closing bracket, and can be nested. Under the hood, the opening bracket assembles to the address of the closing bracket which allows the destination address to be used like any other label such as a JCI ?{, a JMI, !{ or a plain literal ;{.
Counted Strings
Similarly to counted strings, lambdas can encode strings in memory by preceeding their content by the address of the end of the string, so the reading of that string data is not looking for a null byte, but running until reaching the bounds. The advantage is that the address of the next character to append is readily available.
@on-reset ( -> ) ;cstr print-counted BRK @cstr ={ "foo 20 "bar } @print-counted ( cstr* -- ) LDA2k SWP2 INC2 INC2 &l ( -- ) LDAk #18 DEO INC2 GTH2k ?&l POP2 POP2 JMP2r
Data Structures
We can inline a list of items, here's an implementation a function that returns the member in a list, or nil. Notice how the lambda jump requires the list address to be moved from the return stack.
{ =cat =dog =bat } STH2r ;rat member?
@member? ( {items}* target* -- res* ) ,&t STR2 DUP2k #0002 SUB2 LDA2 ADD2 SWP2 &l ( -- ) LDA2k [ LIT2 &t $2 ] EQU2 ?&found INC2 INC2 GTH2k ?&l POP2 ;nil &found NIP2 JMP2r
Unless Blocks
It is important to notice that a in the case of a conditional jump, the lambda's content is jumped over when the flag byte is true.
.button LDZ ?{ skipped-on-button }
Lambdas can also be nested into one another, only the outermost layer of a nested lambda is evaluated at a time:
#01 { { "foo $1 } STH2r !print-lambda } STH2r JCN2
Higher-Order Functions
A higher-order function is a function that takes a function as an argument or returns one as a result. In the following example, the foreach routine is expecting a pointer to a series of bytes, and a pointer to a function to apply on each byte-long item in memory.
{ 01 02 03 04 05 } STH2r ;double foreach
The body of the double
function reads the value of a cell in
memory and writes a result equal to twice its value, and the body of the
foreach
function is merely applying a function to each cell in
memory.
@double ( addr* -- addr* ) STH2k LDAk DUP ADD STH2r STA JMP2r @foreach ( {bytes}* fn* -- bytes* ) ,&t STR2 DUP2k #0002 SUB2 LDA2 ADD2 SWP2 &l ( -- ) [ LIT2 &t $2 ] JSR2 INC2 GTH2k ?&l POP2 POP2 JMP2r
incoming uxntal syntax uxntal macros uxntal immediate drifblim