A quick-n-dirty guide to function programming concepts in Uxntal.
Functions are the only primitive data types in untyped lambda calculus. It is nevertheless possible to represent numerals, booleans, lists, sets, characters and strings as higher order functions in untyped lambda calculus using Church encoding.
To familiarize yourself with Combinatory Logic, begin with the primer.
Church Booleans
In Uxntal, to apply an operation from a value on the stack, we use the Identity macro, which pops a byte from the stack and writes it in front of the Program Counter. It is possible to put the literal values of opcodes on the stack, operate the stack and apply them at a later time, this is done with the #00 STR 00
pattern.
%I { #00 STR 00 } %True { LIT POP } %False { LIT NIP } %And { DUP I } %Not { False True ROT I } %Or { DUP Not I } %Nand { And Not }
Booleans can be represented as operations that expect two values on the stack, returning the first argument if True, or POP, and the second if False, or NIP.
False True AndFalse True NotFalse True False OrTrue
Currying
Currying is the technique of converting a routine that takes multiple arguments into a sequence of routines that each takes a single argument. Functions are curried when we partially apply their arguments, both invocations returned functions into which the partially applied values are baked.
INCRABC ( a b c -- res ) ROT INC ROT INC ROT INC JMP2r
Running routines over an array
You might want to run a routine over an array of data, in the style of:
array.each(incr)
You can create a each
routine that way, but remember that this is not immutable.
|0100 ;array ;incr ,each JSR ;send ,each JSR POP2 BRK @each ( arr* fn* -- arr* ) ,&fn STR2 DUP2 LDAk #00 SWP ADD2k NIP2 SWP2 &l INC2 [ LIT2 &fn $2 ] JSR2 GTH2k ,&l JCN POP2 POP2 JMP2r @incr ( addr* -- addr* ) STH2k LDA INC STH2kr STA STH2r JMP2r @send ( addr* -- addr* ) LDAk #18 DEO JMP2r @array 06 &body "abcdef