Janet 1.19.0-a0ddfcb Documentation
(Other Versions:
1.18.1
1.17.1
1.16.1
1.15.0
1.13.1
1.12.2
1.11.1
1.10.1
1.9.1
1.8.1
1.7.0
1.6.0
1.5.1
1.5.0
1.4.0
1.3.1
)
Bindings (def and var)
Values can be bound to symbols for later use using the keyword def
. Using
undefined symbols will raise an error.
(def a 100)
(def b (+ 1 a))
(def c (+ b b))
(def d (- c 100))
Bindings created with def
have lexical scoping. Additionally, bindings
created with def
are immutable; they cannot be changed after definition.
For mutable bindings, like variables in other programming languages, use the
var
keyword. The assignment special form set
can then be used to
update a var.
(def a 100)
(var myvar 1)
(print myvar)
(set myvar 10)
(print myvar)
In the global scope, you can use the :private
option on a def or var to
prevent it from being exported to code that imports your current module. You can
also add documentation to a function by passing a string to the def
or
var
command.
(def mydef :private "This will have private scope. My doc here." 123)
(var myvar "docstring here" 321)
Scopes
Defs and vars (collectively known as bindings) live inside what is called a scope. A scope is simply where the bindings are valid. If a binding is referenced outside of its scope, the compiler will throw an error. Scopes are useful for organizing your bindings and they can expand your programs. There are two main ways to create a scope in Janet.
The first is to use the do
special form. do
executes a series of
statements in a scope and evaluates to the last statement. Bindings created
inside the form do not escape outside of its scope.
(def a :outera)
(do
(def a 1)
(def b 2)
(def c 3)
(+ a b c)) # -> 6
a # -> :outera
b # -> compile error: "unknown symbol \"b\""
c # -> compile error: "unknown symbol \"c\""
Any attempt to reference the bindings from the do
form after it has
finished executing will fail. Also notice that defining a
inside the
do
form did not overwrite the original definition of a
for the
global scope.
The second way to create a scope is to create a closure. The fn
special
form also introduces a scope just like the do
special form.
There is another built in macro, let
, that does multiple def
s at
once, and then introduces a scope. let
is a wrapper around a combination
of def
s and do
s, and is the most "functional" way of creating
bindings.
(let [a 1
b 2
c 3]
(+ a b c)) # -> 6
The above is equivalent to the example using do
and def
. This is
the preferable form in most cases. That said, using do
with multiple
def
s is fine as well.