Special Forms
??
(?? null "fallback")
==> "fallback"
(??)
==> null
(?? 1)
==> 1
(?? null)
==> null
The ??
operator returns the first of its parameters that is not null. It evaluates the parameters on demand.
cond
(let (a 1) (cond (< a 0) "less than zero" (< a 2) "less than two" true "greater than or equal to two"))
==> "less than two"
(let (a 3) (cond (< a 0) "less than zero" (< a 2) "less than two" true "greater than or equal to two"))
==> "greater than or equal to two"
(cond false "this is not going to match")
==> null
(cond)
==> null
The cond
form allows you to express a conditional with multiple branches. It uses condition-branch pairs,
returning the value of the first branch that matches the preceding conditional.
If no branches match, it returns null.
cond
requires an even number of arguments.
define
(define name "value")
==> null
The define
form binds a name to a value in the current namespace. name
is visible to the definition of
value
, which means you can define recursive functions: (define myfun (fn () (myfun)))
dynfn
(let (my-dynamic-function (dynfn [] (* 10 dynamic-value))) (let (dynamic-value 5) (my-dynamic-function)))
==> 50.0
The dynfn
form defines a dynamically scoped function. Unlike fn which operates in its lexical scope —
seeing the names available where it’s defined in the source file — a function defined with dynfn
operates
in a dynamic scope, seeing the values in its caller’s namespace.
eq
(let (a 10 b (+ 5 5) c (- 12 2)) (eq a b c))
==> true
The eq
forms compares its parameters to each other and returns a boolean indicating if they’re identical.
fn
((fn [a] (* a a)) 3)
==> 9.0
(((fn [a] (fn [b] (* a b))) 3) 4)
==> 12.0
The fn
form defines a function. Its first parameter is an array of parameters, and it evaluates the rest
of the expressions one by one, returning the value from the last one. The functions defined with fn
capture their lexical scope: you can refer to values in the containing source location when you return
values from functions or pass functions as parameters.
If you want to skip naming the parameters of your function, use the fna form which assigns automatic
numbered names.
fna
((fna (* $0 $0)) 3)
==> 9.0
The fna
form defines a function with anonymous parameters. It evaluates the expressions it is given as parameters
one by one, returning the value from the last one. The functions defined with fna
capture their lexical scope: you can refer to values in the containing source location when you return
values from functions or pass functions as parameters.
The parameters passed in to functions defined with fna
have access to their parameters with the automatic
names $0
, $1
, etc.
If you want to give names to the function parameters, use the fn form.
if
(define f (fn [a] (if (not (eq a 0)) (/ 1 a) 0)))
==> null
(f 10.0)
==> 0.1
The if
form evaluates takes three parameters: an expression evaluating to a boolean, a "then" expression
and an "else" expression.
let
(let (a 2 b (* a 3) c (* b a)) c)
==> 12.0
The let
form creates a new namespace with value bindings from the first expression and evaluates the
rest of the expressions one by one, returning the value from the last one. The first expression consists
of pairs of values, alternating between variable names and values. Each definition sees the ones created
before it. The names defined in let are not visible when you leave the let.
Functions
%
(% 20 12 3)
==> 2.0
%
is the modulo (remainder) operator. It operates on integers or doubles. It converts integers to doubles
if it receives both as arguments.
*
(* 12 -13 14)
==> -2184.0
*
is the multiplication operator. It operates on integers or doubles. It converts integers to doubles
if it receives both as arguments.
+
(+ 12 -13 14)
==> 13
+
is the addition operator. It operates on integers or doubles. It converts integers to doubles
if it receives both as arguments.
-
(- 12 -13 14)
==> 11
-
is the subtraction operator. It operates on integers or doubles. It converts integers to doubles
if it receives both as arguments.
/
(/ 12.0 -13.0 14.0)
==> -0.06593407
(/ 25 2)
==> 12
/
is the division operator. It operates on integers or doubles. It converts integers to doubles
if it receives both as arguments. It performs integer division when operating on integers, discarding
the fraction part.
> >= < <=
(> 3 2 1)
==> true
(> 3 3 2)
==> false
(>= 3 3 2)
==> true
(< 1 2 3)
==> true
(<= 1 2 1)
==> false
The basic numeric comparison operators are less than (<
), less than or equal (<=
),
greater than (>
), and greater than or equal (>=
). They support any number of arguments.
apply
(apply concat ["abc", "def", "ghi"])
==> "abcdefghi"
(apply (fn [a, b, c] (+ a b c)) [10, 20, 30])
==> 60
The apply
function calls a function with parameters from the array. The function can be a built-in one
or one defined in SexpyJSON.
as-dict
(as-dict { "hello": "world" })
The as-dict
function converts an object to a dictionary.
as-object
(as-object (merge { "k1": "v1" } { "k2": "v2" }))
The as-object
function converts a dictionary to an object.
ceil
(ceil 16.4)
==> 17.0
(ceil 16.5)
==> 17.0
(ceil -16.5)
==> -16.0
The ceil
function rounds its parameter to the nearest larger integer. It does not change
the number’s type.
concat
(concat "ab" "cd" "ef")
==> "abcdef"
(concat [1, 2] [3, 4] [5, 6])
==> [1, 2, 3, 4, 5, 6]
The concat
function concatenates strings or arrays.
dict
(dict "foo" "bar" "zap" "bang")
==> { "foo": "bar", "zap": "bang" }
The dict
function constructs a dictionary, using the first parameter as the first key,
the second parameter as the value for the first key, the third parameter as the second key, etc.
double
(double 12)
==> 12.0
(double -12)
==> -12.0
The double
function converts its number parameter to double.
filter
(filter (fn (a) (> a 2)) [0, 1, 2, 3, 2, 4, 3, 1])
==> [3, 4, 3]
The filter
function filters an array with a predicate function. The return value is an array
with the elements for which the function returns true.
flatmap
(flatmap (fn (a) [a, a]) [1, 2])
==> [1, 1, 2, 2]
The flatmap
function maps over an array with a function that returns arrays and joins the returned
arrays.
floor
(floor 18.4)
==> 18.0
(floor 18.5)
==> 18.0
(floor -18.5)
==> -19.0
The floor
function rounds its parameter to the nearest smaller integer. It does not change
the number’s type.
has-name
(let (a 10) (has-name "a"))
==> true
(let (a 10) (has-name "b"))
==> false
int
(int 12.4)
==> 12
(int 12.5)
==> 12
(int -12.5)
==> -12.0
The int
function truncates its parameter to the nearest integer that’s closer to zero.
Its return value is an integer.
is-null
(is-null null)
==> true
(is-null "asdf")
==> false
The is-null
function returns true if its sole parameter is null.
join-string
(join-string ", " ["hello", "world"])
==> "hello, world"
The join-string
function joins an array of strings into a single string using a separator. The first
parameter is the separator string, the second parameter the array.
len
(len [1, 2, 3, 4])
==> 4
(len "foo")
==> 3
The len
function returns the lenght of an array or a string.
map
(map len ["a", "bb", "ccc"])
==> [1, 2, 3]
The map
function maps a function over an array.
merge
(merge {"a": "b"} {"c": "d"} {"e": "f"})
==> {"a": "b", "c": "d", "e": "f"}
The merge
function merges the fields of two or more objects or dictionaries, returning a dictionary
with the key-value pairs from all the parameters. Objects later in the parameter list take precendence
in collisions.
name
(let (a 10) (name "a"))
==> 10
name?
(let (a 10) (name? "a"))
==> 10
(let (a 10) (name? "b"))
==> null
not
(not true)
==> false
(not false)
==> true
The not
function is the boolean not operation, returning the inverse of the boolean it received as
a parameter.
object
(object "foo" "bar" "zap" "bang")
==> { "foo": "bar", "zap": "bang" }
The object
function constructs an object, using the first parameter as the first key,
the second parameter as the value for the first key, the third parameter as the second key, etc.
round
(round 12.4)
==> 12.0
(round 12.5)
==> 13.0
(round -12.5)
==> -13.0
The round
function rounds its parameter number away from zero. It does not change
the number’s type.
sub
(sub ["foo", "bar", "zap", "bang"] 2)
==> "zap"
(sub {"key1": "value1", "key2": "value2"} "key2")
==> "value2"
(sub {"key1": {"nestedKey1": "nestedValue1"}} "key1" "nestedKey1")
==> "nestedValue1"
The sub
function is the subscription operator. It allows you to retrieve a member of an array (with an index)
or an object (with a string). See also sub?.
sub?
(sub? {"key1": {"nestedKey1": "nestedValue1"}} "key1" "nestedKey1")
==> "nestedValue1"
(sub? {"key1": {"nestedKey1": "nestedValue1"}} "key2" "nestedKey1")
==> null
The sub?
function is the subscription operator with support for conditional container. It allows you
to retrieve a member of an array (with an index) or an object (with a string), and returns null if the
container is null. See also sub.
trunc
(trunc 14.4)
==> 14.0
(trunc 14.5)
==> 14.0
(trunc -14.5)
==> -14.0
The trunc
function truncates its parameter number to the nearest integer that’s
closer to zero. It does not change the number’s type.