Names can contain every printable character except space and # and @, although operator names consist of different characters than other names.
Usually, operator names consist of funny characters or math operator characters, not alphanumeric letters.
Some operators are preregistered (most important first): . _ ^ ** ⨯ * ⋅ / : ' ++ + - % = /= < <= ≤ > >= ≥ && || , $ else elif | => ; \ let import
Monoms after a name are function arguments: sin k⋅x=sin(k⋅x) and not (sin k)*x.
On the other hand, sin k⋅x+φ=(sin k⋅x)+φ
Likewise, 5⋅f x=(5⋅f) x and not 5⋅(f x)
#!/usr/bin/λ -i let IO := requireModule "IO" in import [write! stdout] from IO in write! stdout "Hello world"
Note that you need to specify (using -i) that you want IO to happen (rather than just be described).
What this does is:
write! \file \text will write text, once a World is given (i.e. by calling the interpreter with -i or chaining actions with ;).
The usual calculator mathematics work (note: no -i):
#!/usr/bin/λ let Arithmetic := requireModule "Arithmetic" in import [(+)] from Arithmetic in (5 + 2) => 7
#!/usr/bin/λ let Arithmetic := requireModule "Arithmetic" in import [(+) (⋅)] from Arithmetic in (5 + 2⋅3) => 11
Operator precedence is as you would expect:
#!/usr/bin/λ let Arithmetic := requireModule "Arithmetic" in import [(+) (⋅)] from Arithmetic in (5 + 2⋅3) => 11
#!/usr/bin/λ let Arithmetic := requireModule "Arithmetic" in import [(+) (⋅)] from Arithmetic in let f := \x x⋅x in (5 + 2⋅(f 3)) => 23
Here, the function f is defined to be a function of x, giving the square of x.
Then the function f is evaluated with the argument 3.
However, there is one strange quirk: 2⋅f x means (2⋅f) x:
#!/usr/bin/λ let Arithmetic := requireModule "Arithmetic" in import [(+) (⋅)] from Arithmetic in let f := \x x⋅x in (5 + 2⋅f 3) => ???
The following works, too (although it has more parens for no reason):
#!/usr/bin/λ let Arithmetic := requireModule "Arithmetic" in import [(+) (⋅)] from Arithmetic in let f := \x x⋅x in (5 + 2⋅(f(3))) => 23
Or if it's the first operand of multiplication:
#!/usr/bin/λ let Arithmetic := requireModule "Arithmetic" in import [(+) (⋅)] from Arithmetic in let f := \x x⋅x in (5 + (f 3)⋅2) => 23
Note that * works for multiplication as well (and is the same thing):
#!/usr/bin/λ let Arithmetic := requireModule "Arithmetic" in import [(+) (*)] from Arithmetic in (5 + (f 3)*2) => 23
#!/usr/bin/λ let Arithmetic := requireModule "Arithmetic" in let Logic := requireModule "Logic" in let Composition := requireModule "Composition" in import [(≥)] from Arithmetic in import [(if) (else)] from Logic in import [($)] from Composition in let abs := \x if (x ≥ 0) x else (-x) in abs (-2) => 2
#!/usr/bin/λ let List := requireModule "List" in let Testers := requireModule "Testers" in let (=>) := Testers.(=>) in List.allTrue? [ #t => #t #f => #t #f && #f => #f #f && #t => #f #t && #f => #f #t && #t => #t #f || #f => #f #f || #t => #t #t || #t => #t #t || #t => #t not #f => #t not #t => #f ]
The simplest form of list is the linked list.
Nodes of a linked list are created by : like this:
#!/usr/bin/λ let List := requireModule "List" in import [(:) nil] from List in 42:24:12:nil
This is a list with 3 elements, linked together through the tail. The last element has nil tail.
There's also a shorthand macro for creating lists used like this:
let List := requireModule "List" in import [(:) nil] from List in [42 24 12]
You can access elements like this:
#!/usr/bin/λ let List := requireModule "List" in import [(:) nil head tail cons? list? allTrue?] from List in allTrue? [ head (1:2:3:nil) => 1 tail (1:2:3:nil) => (2:3:nil) head (tail (1:2:3:nil)) => 2 cons? (1:nil) => #t cons? nil => #f cons? 42 => #f list? (1:nil) => #t list? nil => #t ]
Sometimes you want to not reduce a function or operator to their definition but rather leave the name. To do so, prefix their name by '
let x := 2 in 'x => x
However:
let x := 2 in x => 2
#!/usr/bin/λ -i REPL.import! "IO" fopen @mode:"w" "foo.INI.temp" -- Keyword Arguments need to be before normal arguments.
Conditionals are used for flow control.
If you want to see a short result on screen, use something like the following:
#!/usr/bin/λ let Logic := requireModule "Logic" in let Testers := requireModule "Testers" in let (=>) := Testers.(=>) in if (#t && #t) 'yes else 'no => 'yes
#!/usr/bin/λ -i let IO := requireModule "IO" in import [write! flush! readline! return! stdout] from IO in write! stdout "What's your name? " ;\_ flush! stdout ;\_ readline! stdin ;\name write! stdout "Hello " ;\_ write! stdout name ;\_ flush! stdout ;\_ return! name
What this does is:
write! \file \text will write text, once a World is given (i.e. by interpreter option -i or ;).
; will sequence two operations so the left-hand-side operation will be done first and the result of that operation given to the right-hand-side - which results in an operation, which will be done afterwards.
_ is the traditional variable name for "don't care about the argument".
If you want to spread your program over multiple lines, you can. However, then, indentation rules come into effect.
let Arithmetic := requireModule "Arithmetic" in let Logic := requireModule "Logic" in let Composition := requireModule "Composition" in import [(if) (else) (elif) (=)] from Logic in import [($)] from Composition in import [(=)] from Arithmetic in if (x = 0) 1 elif (x = 1) 2 elif (x = 2) 3 else 4
These work as follows:
If the indentation (number of whitespace characters at the beginning of the line) increased compared to the previous line, then a "(" is inserted.
If the indentation decreased compared to the previous lines, then one or more ")" are inserted until previous blocks up to and excluding the current block are closed.
If you want to abbreviate some formula you use often, you can use the let macro.
let a := b in c expands to (\a c) b, the macro argument order being more common for programmers.
Example:
let pi := 3.141592 in 2⋅pi
Result is:
6.283184
Because:
((\pi 2⋅pi) 3.141592) => 6.283184
If you want to abbreviate a lot of lets, you can use the import macro.
import [a b c d] from F in B expands to:
let a := F.a in let b := F.b in let c := F.c in let d := F.d in B
For example:
let Arithmetic := requireModule "Arithmetic" in import [(+) (-) (*) (/)] from Arithmetic in 5 + 2*3
The interactive interpreter has a few special features, available through the module "REPL" which is automatically imported for you and made available under the name REPL:
If you keep needing the same definitions all the time, you can add them to the environment of the REPL and have them available automatically in the future:
REPL.import! "IO"
Note that this will import everything from the module "IO", possibly overriding your own definitions of things of the same name.
Sometimes you want to know how a function was originally defined (as opposed to how it was actually implemented).
Therefore, the λ REPL has a command to retrieve the original definition of things in its environment:
Note that you need to put parenthesis around operators (in order to prevent them from asserting their own precedence).
REPL.import! "IO" REPL.define! 'f \x x*x REPL.describe! 'f => \x x*x REPL.describe! '(;) => \m \ber \world (\r ber (ioValue r) (ioWorld r)) (m world)
If there are multiple overrides for the definition, try using @backOffset: to reach back. The value is an integer starting at 0 (which is the default) stating how many definitions (of that symbol) back you want to reach.
REPL.describe! @backOffset:1 'g => \x x*x
Usually, the function name is not available within the function:
REPL.define! 'f (\x (f 1)) -- makes no sense
If you want it to do recursion, do it like this:
REPL.import! "Composition" REPL.define! 'f (rec \f \x (f 1)) -- endless recursion, but it works
Or like this, which is exactly the same:
REPL.import! "Composition" REPL.define! 'f (rec \self \x (self 1)) -- endless recursion, but it works
Note that the reason that define! 'f doesn't make f available within the body of f is that you can refer to previous definitions of f within the new definition of f.
An example will make that clearer:
REPL.import! "Logic" REPL.import! "Arithmetic" REPL.define! 'f \x (x**x) REPL.define! 'f \x if (x = 0) 1 else (f x) -- refers to the previous definition.
See the 5D Library Documentation for functions available to you.