Builtin Functions
Throws an exception containing MSG if CONDITION evaluates to false
.
(assert false "My Exception")
; ERROR: My Exception
Creates a new Lisp-Pair with the two elements FIRST and REST
(cons 123 456)
;-> (123 . 456)
Retreives first element of Pair
(car (1 . 2))
;-> 1
Retreives last element of Pair
(cdr (1 . 2))
;-> 2
Just returns the first argument, without evaluating it.
(quote Foo)
;-> Foo
Returns the current binding (= LISP.Environment)
(get-bindings)
;-> <Environment>
(eval 'n ((lambda (n) (get-bindings)) 2))
;-> 2
Evals the given LIST. If the optional parameter ENV is given, this environment is used to eval LIST.
(define my_env ((lambda (foo) (get-bindings)) 4))
(eval '(+ foo 1) my_env)
;-> 5
There are a bunch of mathematical operators. All of them can be used with a variable
number of arguments (i.e. (+ 1 2 3 4 5 6)
is supported).
Again there are a few logical operators, which can be used to work on logical
expressions like (not (and true false))
One may note, that the current implementation evaluates both arguments all the
time. When using (and (expr1) (expr2))
both expressions are evaluated before
comparison.
All Comparators, except eq?
are built to work with Numbers.
Evaluates both arguments and compares them afterwards. At first the types are checked for equality. Then the values of both arguments are compared. Lists are compared recursive.
(eq? 4 4)
;-> true
(eq? "Foo" "Foo")
;-> true
(eq? '(1 2 3) '(1 2 3))
;-> true
(eq? '(1 2) '(1 2 3))
;-> false
Greater than. (>)
(gt? 5 4)
;-> true
(gt? 5 5)
;-> false
Greater than, or equal. (>=)
(ge? 5 4)
;-> true
(ge? 5 5)
;-> true
Less than. (<)
Less than, or equal. (<=)
Defines KEY (which has to be a symbol) as VALUE in the current environment.
(define foo 1)
foo
;-> 1
Shorthand for (define SYMBOL (lambda (args) body))
. As with lambda
, let
and
begin
define can take multiple bodies, which are evaluated one after another on
execution.
(define (say_hello name)
(print "Hello!")
(print name))
(say_hello "Mister")
; "Hello"
; "Mister"
;-> nil
Returns true
if KEY is defined in the current environment - otherwise false
is
returned.
(define foo 4)
(defined? foo)
;-> true
(defined? bar)
;-> false
Changes the defined value of KEY to VALUE. (KEY has to be already defined somewhere in the environment chain!!)
(define foo 4)
(set! foo 7)
foo
;-> 7
(set! bar 8)
; ERROR: bar is not defined, and cannot be set to 8
A new temporary environment is created and for each key-value pair VALUE is bound to the KEY. Afterwards all bodies are evaluated in this environment and the last return-value is returned.
(let ( (Foo 3)
(Bar 2) )
(+ Foo Bar))
;-> 5
Clears the global environment and resets it. Afterwards only the builtins are defined.
(define Foo 5)
(reset)
(defined? Foo)
;-> false
(defined? +)
;-> true
To make it possible to work with string and convert them from / to symbols the following methods are available
Converts a symbol (or anything, that's got a value) to a string
Converts a string (or anything, that's got a value) to a symbol.
Splits a string into a list of characters:
(split "Hello World")
;-> '("H" "e" "l" "l" "o" " " "W" "o" "r" "l" "d")
Joins a list back to a string
(join '("H" "e" "l" "l" "o" " " "W" "o" "r" "l" "d"))
;-> "Hello World"
Returns a symbol, which describes the type of the ELEMENT.
(typeof 123)
;-> 'Number
(typeof 'Foo)
;-> 'Symbol
Evals TRUE-EXP if COND evaled to true
. Otherwise evals FALSE-EXP
Lambdas can contain multiple bodies.
((lambda (a b)
(+ a b)) 2 3)
;-> 5
Using varargs can look like
(lambda (first_arg . all_other_args)
(... body ...))
all_other_args
is a list, containing all other applied arguments. If only varargs are wished one can write:
(lambda varargs
(... body ...))
begin evals all given expressions one after another and returns the return-value of the last one.
(begin
(print "Hello")
(print "World")
(+ 4 3)
)
; "Hello"
; "World"
;-> 7
Defines a macro and stores it in the current environment
(defmacro defun (name args body) '(define ,(cons name args) ,body))
When the macro is being called, the macro is evaluated the first time, then expanded (all backquotes are resolved) and afterwards evaluated a second time. So in this example calling the macro like:
(defun Foo (n) (+ n 1))
is fully equivalent to
(define (Foo n) (+ n 1))
When building macros, sometimes unforeseen problems can occur. To get a better understanding of what your macro is doing you can expand it using macroexpand
. In this case the macro is only evaluated the first time and afterwards expanded, without evaluating it a second time. This enables you to see the expanded version of the macro.
Using the example above the macro expands to:
(macroexpand defun Foo (n) (+ n 1))
;-> (define (Foo n) (+ n 1))
call/cc expects a lambda with one argument. This lambda will be called with the current continuation. This continuation can be stored somewhere else and called later on (even multiple times) to gain another way of program flow control.
This little exception-handling sample, shows the use of call/cc:
(define try-catch (lambda (try-block catch-block)
(let ( (exception nil) )
(set! exception (call/cc try-block))
(if (eq? exception nil)
(print "Nothing") ; do nothing
; else
(catch-block exception)
)
)
))
(try-catch
(lambda (throw)
(print "inside lambda")
(throw "My Exception")
(print "after exception"))
(lambda (e)
(print (+ "caught exception: " e))))
; "inside lambda"
; "caught exception: My Exception"
A more advanced example for exception-handling can be found here
Because lisp.js is built to be run in a browser, there are some debugging and configuration functions, that made developing more easy. All output methods are in this section, too.
Prints MSG to the std-out (your browser console, or jsconsole)
Throws an error, containing MSG as message
Evals ELEMENT and outputs the result to your browser console (i.e. console.log())
Prints some System information about the use of Webworkers and the builtin cooperative multitasking.
(system)
; Using browser's webworkers: true
; Using continuations for cooperative multitasking: false
Turns on the continuation-based cooperative multitasking. This feature can be used, if your browser does not support web workers and you want your GUI to be more responsive. But be careful, this option slows down the interpreter!
(set-coop true)
; Using browser's webworkers: false
; Using continuations for cooperative multitasking: true