XXIIVV

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 ;{.

Inline Strings

A lambda can be used to store data, such a text, amongst code. The JSI Lambda { assembles to a subroutine, and puts the return address, or in this case, the location of the data in memory, on the return stack.

{ "hello $1 } STH2r print-lambda

In other words, a lambda block that has no rune will be parsed as a subroutine jump, and so, will be jumped over, and a pointer to the start of the lambda will be pushed to the top of the return stack. The body of the lambda can be unquoted with the STH2r and JSR2 opcodes.

The lambda jump writes the length to jump by, and that length can be read to get the length of the lambda block.

@print-lambda ( {str}* -- )
	DUP2k #0002 SUB2 LDA2 ADD2 SWP2
	&l ( -- )
		LDAk .Console/write 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.

{ =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

Anonymous 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 #00 EQU ?{ will-not-eval }

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 immediate drifblim