←THE LAST ACTION LANGUAGE→

= ←THE_LAST_ACTION_LANGUAGE→ =
== overview ==
* natural-language agnostic (all keywords are 1 special character) so you can program in Toki Pona
* prefix notation
* variadic functions are not allowed
* tacit programming
* variables are mutable
* their types are immutable
* functions are values
* events
==== types ====
there are 8 types
 void [;]
 type [~]
 error [`]
 boolean [?]
 number [0]
 block [_]
 function [#]
 event handler [:]
==== basics ====
the syntax is all prefix notation, so to assign (2+5)*3 to a variable Foo, you would
 $ [Foo] * + 2 5 3
all functions have constant arity, so you always know which argument goes to which parameter. in the example above, we use the function $ which is the assignment. assignment needs 2 arguments, the first is the name of a variable, and the second is a value. let's go step by step.
 ; [ this is a comment ]
 $ ; [ this is our assignment function call ]
 [Foo] ; [ this is the first argument of $ ]
 * + 2 5 3 ; [ this is the second argument of $ ]
again, slower.
 $ ; [ this is our assignment function call ]
 [Foo] ; [ this is the first argument of $ ]
 * ; [ this is the second argument of $ ]
 + ; [ this is the first argument of * ]
 2 ; [ this is the first argument of + ]
 5 ; [ this is the second argument of + ]
 3 ; [ this is the second argument of * ]
notice how Foo is between square brackets. this is because assignment is not a special form, so Foo alone would have been evaluated and 21 would have been assigned not to Foo but to Foo's current value.
btw, using a variable that has not been assigned a value yet, raises an error. you need to initialize them before you use them.
==== immutable types ====
once a variable has a value, its type becomes immutable.
 $ [Foo] 5
 $ [Foo] [bar baz]
this raises an error because 5 is a number while [bar baz] is a block. this would change the type of Foo, which is forbidden.
==== section ====
the source code is made of sections. here is a section named Init.
 § [Init]
the content of a section is accessible by using its name like a variable name. you can read it, and you can also assign a new value to it, which changes directly the source code of the running program.
 $ [Init] [ § [Init] some code here...]
==== conditional ====
if-then-else goes like:
 ? ; [ if ]
 < n 0 ; [ the condition, directly ]
 [ $ [n] 0 ] ; [ then-part code, enclosed in a quoting block ]
 [ ] ; [ else-part is mandatory, even though it's empty ]
then-part and else-part must be enclosed in blocks to prevent their direct execution.
==== loooop ====
who needs loops anyway? ok, let's calculate r = 2^p
 $ [n] p $ [r] 1
 €
 < 0 n ; [ condition ]
 [ $ [n] - n 1 $ [r] * 2 r ] ; [ loop body ]
==== index ====
say you have a list.
 $ [list] [ One A Two B Three C 0 D 1 E 2 F ]
then after
 $ [x] ° list 0
 $ [y] ° list 1
 $ [z] ° list [Two]
x is One, y is A, and z is B.
if the index is a number, then the list is treated as an array. if the index is a block, the list is treated as a key-value object. if the index is something else, an error is raised.
==== template ====
inside of a block, everything between curlies will be evaluated, and the curlies will be replaced by the result of the evaluation. no matter how deep curlies are.
 [ this is a [ test where one plus one equals { + 1 1 } ] ]
will become
 [ this is a [ test where one plus one equals 2 ] ]
==== function assembler ====
the function assembler is not a special form. it is a function which needs 3 arguments: an arity, a return type, and a function code body.
 $ [Double] # 1 [0] [ ^ * 2 @ 1 ]
 $ [Addten] # 1 [0] [ ^ + @ 1 10 ]
step by step
 $ ; [ we asssign ]
 [Double] ; [ to the variable named "Double" ]
 # ; [ a function ]
 1 ; [ which takes 1 argument ]
 [0] ; [ and which returns a number ]
 [
 ^ ; [ return ]
 *
 2 ; [ twice ]
 @ 1 ; [ the first argument ]
 ]
==== function disassembler ====
the function disassembler does the opposite.
 $ [Src] ' [Double]
now Src is a block which contains:
 # 1 [0] [ ^ * 2 @ 1 ]
==== evaluation & composition ====
parens ( ) evaluate their content. say you have
 $ [Doubten] [Double Addten]
then if you do
 $ [Answer] (Doubten) 11
Answer will be 42.
==== exception ====
you can do classical try/catch blocks like this.
 "
 [ + 1 [meh] ] ; [ try block, executed first ]
 [ oooops... ] ; [ catch block, executed if the try block failed ]
you can also raise an error manually. since I don't like backticks much, the raise function is `.
 ` [ my own error ]
==== events, timing & I/O ====
you can attach an event handler, which returns an handle. with this handle, you can detach the event handler.
events are how you communicate with anything outside of the interpreter. output is done by emitting events, input is received as events.
they also have a timing functionality: when you emit events, you can choose to delay their emission.
 $ [keypressedHandle] : [ keypressed ] [
 
 $ [pressedKey] @ 1
 handleInput pressedKey
 ]
 
 ; [ now we have an active event handler ]
 
 . keypressedHandle
 
 ; [ now then handler is deactivated ]
 
 > ; [ emit ]
 0 ; [ after 0 msec ]
 [print] ; [ an event named "print" ]
 [be bop] ; [ with an argument "be bop" ]
==== shadowing ====
when you're inside of a closure, if you read a variable, you're reading locally first, then in the callers.
But when you set a variable's value, you're always working on a local variable, even when a variable with the same name exists in the callers.
==== misc. ====
to get a list of all variable names:
 _
and to get the type of something:
 ~ [datum]
you must put your datum inside of a block.
== keywords ==
==== section ====
syntax:
 § name:block
==== escape ====
syntax:
 \
==== conditional ====
syntax:
 ? condition:boolean then:block else:block
==== while ====
syntax:
 € condition:boolean body:block
==== index ====
syntax:
 ° data:block index:any
==== block ====
syntax:
 [ ]
==== evaluate ====
syntax:
 ( )
==== template ====
syntax:
 [ { } ]
==== set variable value ====
syntax:
 $ varName:block value:any
==== assemble function ====
syntax:
 # arity:number type:type body:block
==== return ====
syntax:
 ^ value:any
==== argument ====
syntax:
 @ index:number
==== disassemble function ====
syntax:
 ' funcExpr:block
==== exception ====
syntax:
 " try:block catch:block
==== raise ====
syntax:
 ` error:block
==== event on ====
syntax:
 : event:block body:block
==== event off ====
syntax:
 . handle:event-handler
==== emit ====
syntax:
 > delay:number event:block argument:any
==== vocabulary ====
syntax:
 _
==== no op ====
syntax:
 ; comment:any
==== type of ====
syntax:
 ~ datumExpr:block
==== math ====
syntax:
 + a:number b:number ; [ add ]
 - a:number b:number ; [ subtract ]
 * a:number b:number ; [ multiply ]
 / a:number b:number ; [ divide ]
 % a:number b:number ; [ modulo ]
 , a:number ; [ trunc ]
 = a:number b:number ; [ equal ]
 < a:number b:number ; [ less than ]
 ! a:boolean ; [ not ]
 & a:boolean b:boolean ; [ and ]
 | a:boolean b:boolean ; [ or ]
== factorial example ==
 $ [factorial] # 1 [0] [
 
 ^ ? < @ 1 2
 1
 *
 @ 1
 factorial - @ 1 1
 ]
== length example ==
 $ [length] # 1 [0] [
 
 $ [len] 0
 € ! = ° @ 1 len [] [ $ [len] + len 1 ]
 ^ len
 ]
Category:Languages
Category:Unimplemented
Category:Self-modifying
Category:Turing complete
Category:Functional paradigm
Category:Golfing language