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

@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

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* )

@foreach ( {bytes}* fn* -- bytes* )
	,&t STR2
	DUP2k #0002 SUB2 LDA2 ADD2 SWP2
	&l ( -- )
		[ LIT2 &t $2 ] JSR2 INC2 GTH2k ?&l

incoming uxntal syntax uxntal macros uxntal immediate drifblim