Janet
Janet is a functional (and imperative) cross-platform interpreted (and compiled) lisp-inspired language with batteries-included api that makes a good system scripting language, or a language to embed in other programs.
The entire language (core library, interpreter, compiler, assembler, PEG) is less than 1MB.
Resources
Notes
Very Basics
Starting off with minimum required to do anything
Data Types:
Comments start with a
#
nil- booleans:
true,false - symbols (conventionally
small-letterswith hypens) - keywords:
:symbolsstarting with colon - numbers: like javascript number
1-1.11e10(unlike js,4r100= 16:rn= basen)
Data Structures:
- strings:
"strings are in double quotes"or in n`s like lua’s[[ ... ]] - buffer: mutable
@strings - tuples:
[1 2 3]list of values - arrays: mutable
@tuples - structs: like elixir’s
{:keyword "value"}pairs (or js objects, or clisp plists) - tables: mutable
@structs
Bindings:
anything with paren tuple
(...)is “called” (conventionally called “forms”)
-
Variable definition:
([def | var] <name> <expr>)- immutable
defor mutablevar - bind any value retured by
<expr>to a symbol<name> - works as variable assignment but can also destructure (pattern match) on lists and dicts
- use
(let [<name> <expr> <name2> <expr2>] ...)for multipledefbindings sugar
- immutable
-
Variable reassignment:
(set <name> <expr>)- only works on
var namemust exists and be an initialized value or a declared datastructure
- only works on
-
Function definition:
([defn | fn] [<name>] <args> <body>)- yes,
nameis optional in case offn. functions form closure. - arguments are literal tuples
[...]but can be destructured fromstructs - use
&for variadic arguments:[a b c & rest] - body is zero or more forms
(...) - last form is returned implicitly
defnis short for bindingfnto<name>usingdef
- yes,
Conditionals:
-
If conditional:
(if <expr> <true-form> [<false-form>])- lazy eval (does not evaluate forms until needed)
- if no
false-formbutcondisfalse, then returnsnil
-
Cond conditional:
(cond <expr> (body) <expr2> (body2) <expr3> (body3))- Can be used instead of multiple if-else-if-else nesting
-
Case conditional:
- think
switchstatements elsewhere
- think
-
When conditional:
- like
ifwithoutfalse-form; returnsnilonfalseimplicitly
- like
Loops:
OPINION: Avoiding mutable loops and stick to functional paradigm
-
While loop:
(while <cond> <body>)- Usually works with mutable
varswith side effects in body
- Usually works with mutable
-
For loop:
(for <var> <start-expr> <end-expr> <body>) -
loop loop:
(loop [<var> <verb> <values> <modifiers> <cond>] <body>)-
Ex1:
(loop [i :range [0 10] :when (even? i)] (print i))iis a var,:rangeis a verb,:whenis a modifier
-
Ex2:
(loop [name :in names] (print name))nameis a var,:inis a verb andnamesis a list
-
Ex2 can be written using
eachandmapresp as:-
(each name names (print name)) -
(map print names)
-
-
Ex3:
(loop [[k v] :pairs some_struct] (print k " -> " v))- Above for looping across a dict
-
Arithmetic (<op> <expr> <expr2>) and Comparisons (<cmp> <expr> <expr2>) work as usual:
- Use
(not= <expr> <expr2>)for checking unequality - Use
(deep= <mutable> <mutable>)for checking contents of mutable structures