980 lines
33 KiB
Org Mode
980 lines
33 KiB
Org Mode
#+title: The Slime 1.0 Manual
|
|
|
|
#+macro: example_start (eval (concat "{{{slime_header}}}" "\n" "#+begin_src slime"))
|
|
#+macro: example_end (eval (concat "#+end_src"))
|
|
|
|
#+begin_abstract
|
|
abstract
|
|
#+end_abstract
|
|
|
|
\tableofcontents
|
|
|
|
* Lisp languages
|
|
Lisp is not one language but rather a family of programming languages. The family is devided by some
|
|
characteristics. There are Lisp-1 and Lisp-2 dialects and there is a difference between a Lisp with
|
|
lexical scoping as opposed to dynamic scoping. These differences will be explained in later
|
|
sections.
|
|
|
|
Like most Lisps, Slime is dynamically typed. That means that like in statically typed Languages
|
|
Slime has different data types, but they are associated not with variables but with the Lisp objects
|
|
themselves. Variables can be assigend Lisp objects of any internal type.
|
|
|
|
The Lisp language family is known to be highly flexible and applicable in all areas by creating
|
|
domain specific languages in Lisp itself through a powerful macro system. The central data structure
|
|
in Lisp is the list. The reason why lisp is so powerful is because the program source code itself is
|
|
represented as lists. The nested lists make up the syntax tree of the lisp program. It is therfore
|
|
computationally easy to parse lisp programs as the source code itself is already structured in the
|
|
form of the syntax tree; allowing for parsing in linear time.
|
|
|
|
The macro system in Slime works by recognizing macros at parse-time and running them, and replacing
|
|
the macro call in the program code with the return value of the macro and then checking if further
|
|
macros have to be expanded in the replaced code. Therefore the macros can be used to pre-compute
|
|
values or rewrite expressions (creating syntactic sugar) or themselves define macros.
|
|
|
|
* Lists
|
|
As mentioned in [[Lisp languages]], the central data structure in all Lisps is the list. Lists are
|
|
implemented as singly linked lists, made up of pairs (historically called =cons-cells=), each pair
|
|
has two slots, the =first= and the =rest= (historically =car= and =cdr=). A linked lsit ist then
|
|
constructed by the convention that the =first= field of a pair points to the first element of the
|
|
list and the =rest= field points to the rest of the list. Following this description, the list is a
|
|
recursive data structure. For the end of the list a special value =nil= is used in the =rest= field.
|
|
|
|
A helpful way to visualize lists made up of pairs is using box diagrams. A simple box diagram can be
|
|
seen in [[simpleBoxDiagram]]. Each rectangle is divided in two. The left part represents the =first=
|
|
field, the right part represents the =rest=. The arrows point to the values in these fields.
|
|
|
|
The diagram in [[simpleBoxDiagram]] shows a simple list containing the values 1, 2 and 3. The first pair
|
|
stores the number 1 its =first= field and the =rest= points to the rest of the list. The last pair
|
|
points to the special value =nil= in its =rest= to denote the end of the list.
|
|
|
|
{{{ditaa_header}}}
|
|
#+begin_src ditaa :file diagrams/list123.eps
|
|
+-----+-----+ +-----+-----+ +-----+-----+
|
|
| | | | | | | | |
|
|
| | |--->| | |--->| | / |
|
|
| | | | | | | | |
|
|
+-----+-----+ +-----+-----+ +-----+-----+
|
|
| | |
|
|
| | |
|
|
V V V
|
|
1 2 3
|
|
#+end_src
|
|
|
|
#+name: simpleBoxDiagram
|
|
#+caption: Box diagram showing the internal structure of a list containing the values 1, 2 and 3
|
|
#+RESULTS:
|
|
[[file:diagrams/list123.esp]]
|
|
|
|
|
|
However the =rest= of a pair needs not to be a pair or nil, it could also point to any other value.
|
|
By doing this the list is no longer "well formed" but rather "ill formed". Ill formed lsits can be
|
|
used as an optimization when using the list for storing data. In [[illFormedList]] an ill formed list
|
|
can be seen, that also contains the values 1, 2 and 3 but stores them using only two pairs instead
|
|
of 3.
|
|
|
|
{{{ditaa_header}}}
|
|
#+begin_src ditaa :file diagrams/list12.3.eps
|
|
+-----+-----+ +-----+-----+
|
|
| | | | | |
|
|
| | |--->| | |--->3
|
|
| | | | | |
|
|
+-----+-----+ +-----+-----+
|
|
| |
|
|
| |
|
|
V V
|
|
1 2
|
|
#+end_src
|
|
|
|
#+name: illFormedList
|
|
#+caption: The internal structure of an ill formed list where the last pair points to the value 3
|
|
#+RESULTS:
|
|
[[file:diagrams/list12.3.eps]]
|
|
|
|
** representing lists in Lisp
|
|
|
|
In Slime and in most Lisps, lists are represented using round parenthesis where =(= denotes the
|
|
start of the list and =)= denotes the end. Eeach element inside these parenthesis separated by one
|
|
or more spaces will be interpreted as an element of that list. For example the list from
|
|
[[simpleBoxDiagram]] would be represented as =(1 2 3)=. During parse time, the Lisp parser transforms
|
|
the parenthesised list into the pairs that are in the end stored in memory.
|
|
|
|
To also be able to represent ill formed lists in Lisp there is a special syntax using the =.= (dot
|
|
symbol). If the parser encounters a =.= inside of a list, it will treat the next element as the
|
|
=rest=. If there is no or more than one element after the =.= an parsing error will be thrown. Using
|
|
this syntax we can represent the ill formed list from [[illFormedList]] as =(1 2 . 3)=. We can also
|
|
write well formed lists using the dot notation if we point the rest to another list. So the well
|
|
formed list from [[simpleBoxDiagram]] can also be written as \[\texttt{(1 . (2 . (3)))}\]
|
|
|
|
** representing function calls in Lisp
|
|
|
|
If we tried to enter the Lisp representation of the lists like =(1 2 3)= discussed in [[representing
|
|
lists in Lisp]] directly into an Lisp interpreter we would get an error. That doesn't mean that the
|
|
explanation given in the section is wrong, it is in fact correct: the lisp parser will transform the
|
|
lisp syntax into the pairs in memory. The reason we would get an error is, that when reading Lisp
|
|
code, the Lisp interpreter first parses the code and then tries to evaluate it and return the result
|
|
back to the user.
|
|
|
|
In Lisp by default, a list corresponds to a function call. As mentioned in [[Lisp languages]] Lisp
|
|
represents lists and Lisp programms as lists. If a list is treated as a function call, the first
|
|
element will be treated as the function and the rest of the elements will be the arguments to that
|
|
function. If we would wnter =(1 2 3)= directly into the Lisp interpreter we would get an error
|
|
saying it cannot find the function =1=.
|
|
|
|
If we would want to compute the sum of the numbers 5 and 3 we could do this by invoking the =+=
|
|
function with 5 and 3 as its arguments. =(+ 5 3)= will evaluate to 8. We can also nest functions
|
|
calls and use the return values as parameters to other functions: =(+ (- 12 4) (/ 24 4))= will
|
|
evaluate to 14. The box diagramm showing the internal structure of that computation can be seen in
|
|
[[moreComplexBoxDiagram]].
|
|
|
|
{{{ditaa_header}}}
|
|
#+begin_src ditaa :file diagrams/simpleMath.eps
|
|
+-----+-----+ +-----+-----+ +-----+-----+
|
|
| | | | | | | | |
|
|
| | |--->| | |--------------------------------------->| | / |
|
|
| | | | | | | | |
|
|
+-----+-----+ +-----+-----+ +-----+-----+
|
|
| | |
|
|
| | |
|
|
V V V
|
|
+ +-----+-----+ +-----+-----+ +-----+-----+ +-----+-----+ +-----+-----+ +-----+-----+
|
|
| | | | | | | | | | | | | | | | | |
|
|
| | |--->| | |--->| | / | | | |--->| | |--->| | / |
|
|
| | | | | | | | | | | | | | | | | |
|
|
+-----+-----+ +-----+-----+ +-----+-----+ +-----+-----+ +-----+-----+ +-----+-----+
|
|
| | | | | |
|
|
| | | | | |
|
|
V V V V V V
|
|
- 12 4 / 24 4
|
|
|
|
|
|
|
|
#+end_src
|
|
|
|
#+name: moreComplexBoxDiagram
|
|
#+caption: The internal structure of the expression =(+ (- 12 4) (/ 24 4))=
|
|
#+RESULTS:
|
|
[[file:diagrams/simpleMath.eps]]
|
|
|
|
* Evaluation order
|
|
As a first step of evaluation of a regular function, all its arguments are getting evaluated, and
|
|
then the function is applied to the evaluated arguments. For example when evaluating the nested
|
|
expression in [[code:complex-math]] the outermost function is the =+= function with three arguments: =(*
|
|
3 4)=, =(- 100 (+ 12 13 14 15))= and =2=. So before the outhermost =+= gets invoked, the three
|
|
arguments are getting evaluated recursively.
|
|
|
|
{{{slime_header}}}
|
|
#+name: code:complex-math
|
|
#+caption: A more complex nested arithmetic expression. Nested expressions can be written more
|
|
#+caption: readable by aligning subsequent arguments vertically underneeth each other
|
|
#+begin_src slime
|
|
(print (+ (* 3 4)
|
|
(- 100 (+ 12 13 14 15))
|
|
2))
|
|
#+end_src
|
|
|
|
#+RESULTS: code:complex-math
|
|
: evaluates to =>
|
|
: 60
|
|
|
|
** Special forms
|
|
The given evaluation rule -- to evaluate all the arguments first and then allpying them to the
|
|
funciton -- as described in [[Evaluation order]] is only valid for regular functions. There is a class
|
|
of functions that do not follow this evaluation rule called *special forms*. Special forms are
|
|
needed when you do not wish to evaluate all arguments. For example the built-in =if= function should
|
|
only evaluate the "then-expression" if the condition evaluates to a truthy value and not otherwise.
|
|
Consider the example in [[code:special-forms]]. The if expression only evaluates the then-expression. If
|
|
the =if= function would follow the evaluation order of regular functions, first all three arguments
|
|
=(< 1 2)=, =(print "I knew it!!\n")= but also =(print "Oh, it is not?!\n")= could get evaluated and
|
|
so both messages would be printed. In the given =if= expression, the condition evaluates to a truthy
|
|
value and only =I knew it!!= will be printed.
|
|
|
|
{{{slime_header}}}
|
|
#+name: code:special-forms
|
|
#+caption: The =if= function is a special form because it does not evaluate all of its arguments
|
|
#+begin_src slime
|
|
(if (< 1 2)
|
|
(print "I knew it!!\n")
|
|
(print "Oh, it is not?!\n"))
|
|
#+end_src
|
|
|
|
#+RESULTS: code:special-forms
|
|
: evaluates to =>
|
|
: I knew it!!
|
|
|
|
The programmer can also define their own special forms using =special-lambda= and macros, which will
|
|
be explained in [[Special lambdas]] and [[Macros]].
|
|
|
|
* Symbols and keywords
|
|
* Truthyness
|
|
* Lambdas
|
|
Slime allows for creating anonymous functions called *lambdas*. We did not talk about binding
|
|
variables, we will do this in [[Define]], but we can still use lambdas now. Remember that Lisp
|
|
interpretes the first argument of a list in the source code as a function and the rest as the
|
|
arguments. The =lambda= special form evaluates to a *regular function object* that can then stand in
|
|
the first position of the function call list. The basic syntax for the lambda special form is:
|
|
\[\texttt{(lambda (arg1 arg2 ...) (body1) ...)}\] the first arguemnt to =lambda= is a list of the
|
|
arguments. All the following arguments will be the body of the lambda. They will be executed when
|
|
the lambda is invoked. The return value of a lambda is the value of the last evaluated expression in
|
|
the body.
|
|
|
|
Probably the simplest function to write as a lambda is the identity function. It takes one argument
|
|
and returns it. The identity lambda and a few other simple examples of lambdas can be seen in
|
|
[[code:simple-lambdas]].
|
|
|
|
{{{slime_header}}}
|
|
#+name: code:simple-lambdas
|
|
#+caption: Some simle lambdas
|
|
#+begin_src slime
|
|
(printf ((lambda (x) x) 1))
|
|
(printf ((lambda (x y) (+ x y)) 3 5))
|
|
(printf ((lambda (x y z) (list x y z)) 1 2 3))
|
|
#+end_src
|
|
|
|
#+RESULTS: code:simple-lambdas
|
|
: evaluates to =>
|
|
: 1
|
|
: 8
|
|
: (1 2 3)
|
|
|
|
Additionally Slime lambdas have the possibility to take *optional arguments* in the form of *keyword
|
|
arguemnts* as well as a *rest argument* which allows for accepting any number of arguments. Since
|
|
these concepts are most useful when the function is actually bound to a variable, they will be
|
|
introduced when we learned how to do that in [[Define]].
|
|
|
|
** Special lambdas
|
|
The =lambda= special form creates a function object that represents a regular function. So the basic
|
|
evaluation rules count: when the lambda is invoked all it's arguments are evaluated and then the
|
|
lambda is applied to the evaluated arguments. If this is not wanted in some rare cases, the
|
|
programmer also has the possibility to define a special form using =special-lambda=, which, when
|
|
invoked does not evaluare any argument. The programmer has to evaluate the arguments in the body
|
|
themselves using =eval=. The rest of the syntax between =lambda= and =special-lambda= are the same.
|
|
|
|
{{{slime_header}}}
|
|
#+name: code:special-lambdas
|
|
#+caption: Special lambdas do not evaluate their arguments
|
|
#+begin_src slime
|
|
((lambda (x) (printf x)) (+ 1 2))
|
|
((special-lambda (x) (printf x)) (+ 1 2))
|
|
|
|
;; Special lambdas make it possible to write
|
|
;; code that inspects code
|
|
((special-lambda (expr)
|
|
(printf "The function to be called is"
|
|
(first expr)
|
|
"and the result is"
|
|
(eval expr)))
|
|
(+ 1 2))
|
|
#+end_src
|
|
|
|
#+RESULTS: code:special-lambdas
|
|
: evaluates to =>
|
|
: 3
|
|
: (+ 1 2)
|
|
: The function to be called is + and the result is 3.
|
|
|
|
* Define
|
|
To assign a value to a symbol you can use the =define= built-in special form. The syntax for
|
|
=define= is: \[\texttt{(define symbol value)}\] and some usages can be seen in
|
|
[[code:variable-defines]].
|
|
|
|
{{{slime_header}}}
|
|
#+name: code:variable-defines
|
|
#+caption: Simple definition of variables
|
|
#+begin_src slime
|
|
(define var1 1)
|
|
(define var2 "Hello World")
|
|
(define var3 (+ 1 2))
|
|
|
|
(printf var1 var2 var3)
|
|
#+end_src
|
|
|
|
#+RESULTS: code:variable-defines
|
|
: evaluates to =>
|
|
: 1 Hello World 3
|
|
|
|
** Defining functions
|
|
In [[Lambdas]] we learned how to create function objects using the =lambda= built-in form. Using
|
|
=define= every Lisp Object can be assigned to a symbol making no exception for the function objects.
|
|
In [[code:lambda-defines]] you can see what that would look like.
|
|
|
|
{{{slime_header}}}
|
|
#+name: code:lambda-defines
|
|
#+caption: Definition of functions using lambdas
|
|
#+begin_src slime
|
|
(define hypothenuse
|
|
(lambda (a b)
|
|
(** (+ (* a a) (* b b)) 0.5)))
|
|
|
|
(printf (hypothenuse 3 4))
|
|
#+end_src
|
|
|
|
#+RESULTS: code:lambda-defines
|
|
: evaluates to =>
|
|
: 5
|
|
|
|
Since defining functions is so common, there is a syntactic shorthand that does not require to write
|
|
out the whole =lambda= definition. In this case the first argument to the call to =define= is a
|
|
list. The frist element of the list is the name of the function to define and the other elemens are
|
|
the arguments to that function. An example can be seen in [[code:function-defines]]. Note that the
|
|
definition looks like a call to the function we are constructing, making it easier to see what a
|
|
call to that function will look like.
|
|
|
|
{{{slime_header}}}
|
|
#+name: code:function-defines
|
|
#+caption: Definition of functions using the shorthand syntax of define
|
|
#+begin_src slime
|
|
(define (hypothenuse a b)
|
|
(** (+ (* a a) (* b b)) 0.5))
|
|
|
|
(printf (hypothenuse 3 4))
|
|
#+end_src
|
|
|
|
#+RESULTS: code:function-defines
|
|
: evaluates to =>
|
|
: 5
|
|
|
|
** Functions with keyword arguments
|
|
A sometimes more convenient way of passing arguments to a function is using keyword arguments. Using
|
|
keyword arguments a function call could look like this: \[\texttt{(function :arg1 value1 :arg2
|
|
value2)}\] here the function accepts two arguments named =arg1= and =arg2=. The user of this
|
|
function can see more clearly excatly which argument will be assigned wich value. This notation also
|
|
allows for switching the argument order. The following function call is equivalent to the call
|
|
above. \[\texttt{(function :arg2 value2 :arg1 value1)}\].
|
|
|
|
For this to work however, the function must be defined to accept these keyword arguments. To do this
|
|
the special marker =:keys= has to be inserted into the argument list of a =lambda= or a function
|
|
=define=. All following arguments *must* be supplied as keyword arguments, /unless/ they are also
|
|
supplied with a default value, in which case they do not need to be supplied. To attach a default
|
|
value to a keyword argument, insert =:defaults-to <value>= after the keyword argument name. An
|
|
example of all of this can be seen in [[code:keyword-args]]. Important note: keyword arguments must be
|
|
defined and supplied after all the regular arguments.
|
|
|
|
{{{slime_header}}}
|
|
#+name: code:keyword-args
|
|
#+caption: A more complex functoin definition using keyword arguments
|
|
#+begin_src slime
|
|
(define (complex required1 required2 :keys
|
|
key1
|
|
key2 :defaults-to 3
|
|
key3)
|
|
(* (+ required1 required2)
|
|
key1
|
|
key2
|
|
key3))
|
|
|
|
(printf (complex 1 2 :key1 2 :key2 2 :key3 3))
|
|
(printf (complex 1 2 :key1 2 :key3 3))
|
|
(printf (complex 1 2 :key3 3 :key1 2))
|
|
#+end_src
|
|
|
|
#+RESULTS: code:keyword-args
|
|
: evaluates to =>
|
|
: 36
|
|
: 54
|
|
: 54
|
|
|
|
** Functions with rest arguments
|
|
If the programmer wants to create a function that can accept any number of arguments, they can use
|
|
the =rest= argument. It is defined after the special marker =:rest= and after the rest argument, no
|
|
other arguments can be defined. In the execution of the fuction, the rest arguent will be assigned
|
|
to a list containing all the supplied values. The rest argument can be used in conjunction with the
|
|
other argument types, regular arguments and keyword arguments.
|
|
|
|
{{{slime_header}}}
|
|
#+name: code:rest-args
|
|
#+caption: A more complex functoin definition using keyword arguments
|
|
#+begin_src slime
|
|
(define (execute-operation operation
|
|
:keys
|
|
do-logging :defaults-to ()
|
|
:rest values)
|
|
(define result (apply operation values))
|
|
(when do-logging
|
|
(printf "Executing operation"
|
|
operation
|
|
"agains the values"
|
|
values
|
|
"yielded:"
|
|
result))
|
|
result)
|
|
|
|
(printf (execute-operation '+ 1 2 3))
|
|
(printf (execute-operation '*
|
|
:do-logging t
|
|
10 11))
|
|
#+end_src
|
|
|
|
#+RESULTS: code:rest-args
|
|
: evaluates to =>
|
|
: 6
|
|
: Executing operation * agains values (10 11) yielded: 110
|
|
: 110
|
|
|
|
* Environments
|
|
* Macros
|
|
* Built-in functions
|
|
:PROPERTIES:
|
|
:UNNUMBERED: t
|
|
:END:
|
|
#+include: "./built-in-docs.org"
|
|
* COMMENT Built-in functions
|
|
This section provides a comprehensive list of the built in functions for Slime. Some of them are
|
|
defined in =C++= source code, some are themselves written in Slime. The cool thing about Slime is
|
|
that it is really easy to extend and adapt it for many purposes by writing new functions in =C++=
|
|
that for example communicate with an already existing software system, so Slime can be used as an
|
|
embedded scripting language.
|
|
|
|
** Arithmetic functions
|
|
- =+= :: (=regular function [C++]=) Takes 0 or more numbers as arguments and returns the sum of all
|
|
the numbers.
|
|
|
|
{{{slime_header}}}
|
|
#+name: code:built-in-=
|
|
#+begin_src slime
|
|
(printf (+))
|
|
(printf (+ 3))
|
|
(printf (+ 1 3 2))
|
|
(printf (+ 1 (+ 3 4)))
|
|
#+end_src
|
|
|
|
#+results: code:built-in-=
|
|
: evaluates to =>
|
|
: 0
|
|
: 3
|
|
: 6
|
|
: 8
|
|
|
|
|
|
- =-= :: (=regular function [C++]=) Takes 0 or more numbers as arguments. If only one number is
|
|
supplied, its negation is returned, otherwise the difference of the first argument and the
|
|
sum of the remaining arguments is returned:
|
|
\[\texttt{(- 10 2 1)} \Rightarrow 10 - 2 - 1 = 10 - (2 + 1) = 7\]
|
|
|
|
{{{slime_header}}}
|
|
#+name: code:built-in--
|
|
#+begin_src slime
|
|
(printf (-))
|
|
(printf (- 3))
|
|
(printf (- 5 3 1))
|
|
(printf (- 5 (+ 3 1)))
|
|
#+end_src
|
|
|
|
#+RESULTS: code:built-in--
|
|
: evaluates to =>
|
|
: 0
|
|
: -3
|
|
: 1
|
|
: 1
|
|
|
|
- =*= :: (=regular function [C++]=) Takes 0 or more numbers as arguments and returns the product of
|
|
all the numbers.
|
|
|
|
{{{slime_header}}}
|
|
#+name: code:built-in-*
|
|
#+begin_src slime
|
|
(printf (*))
|
|
(printf (* 2))
|
|
(printf (* 5 3 2))
|
|
(printf (* 2 (+ 3 1)))
|
|
#+end_src
|
|
|
|
#+RESULTS: code:built-in-*
|
|
: evaluates to =>
|
|
: 1
|
|
: 2
|
|
: 30
|
|
: 8
|
|
|
|
- =/= :: (=regular function [C++]=) Takes 0 or more numbers as arguments. If only one number is
|
|
supplied, it is returned, otherwise the quotient of the first argument and the product of
|
|
the remaining arguments is returned:
|
|
\[\texttt{(/ 100 2 5)} \Rightarrow \frac{100}{\frac{2}{5}} = \frac{100}{2 \cdot 5} = 10\]
|
|
|
|
{{{slime_header}}}
|
|
#+name: code:built-in-/
|
|
#+begin_src slime
|
|
(printf (/))
|
|
(printf (/ 3))
|
|
(printf (/ 1 2))
|
|
(printf (/ 2 (+ 3 2 1)))
|
|
#+end_src
|
|
|
|
#+RESULTS: code:built-in-/
|
|
: evaluates to =>
|
|
: 1
|
|
: 3
|
|
: 0.500000
|
|
: 0.333333
|
|
|
|
- =**= :: (=regular function [C++]=) Takes 2 number arguments and returns the the first argument
|
|
taken to the power of the second argument.
|
|
|
|
{{{slime_header}}}
|
|
#+name: code:built-in-**
|
|
#+begin_src slime
|
|
(printf (** 1 200))
|
|
(printf (** 2 6))
|
|
(printf (** 25 0.5))
|
|
(printf (** 27 (/ 1 3)))
|
|
#+end_src
|
|
|
|
#+RESULTS: code:built-in-**
|
|
: evaluates to =>
|
|
: 1
|
|
: 64
|
|
: 5
|
|
: 3
|
|
|
|
- =%= :: (=regular function [C++]=) Takes 2 number arguments and rounds them down to integer values
|
|
and then returns the remainder of the division of the first argument by the second.
|
|
|
|
{{{slime_header}}}
|
|
#+name: code:built-in-mod
|
|
#+begin_src slime
|
|
(printf (% 10 3))
|
|
(printf (% (+ 3 (* 12 15)) 15))
|
|
#+end_src
|
|
|
|
#+RESULTS: code:built-in-%
|
|
: evaluates to =>
|
|
: 1
|
|
: 3
|
|
|
|
- =not= :: (=regular function [C++]=)
|
|
|
|
{{{slime_header}}}
|
|
#+name: code:built-in-not
|
|
#+begin_src slime
|
|
(printf (not 10))
|
|
(printf (not ()))
|
|
(printf (not (> 10 1)))
|
|
(printf (not (< 10 1)))
|
|
#+end_src
|
|
|
|
#+RESULTS: code:built-in-not
|
|
: evaluates to =>
|
|
: ()
|
|
: t
|
|
: ()
|
|
: t
|
|
|
|
- =and= :: (=regular function [C++]=)
|
|
|
|
{{{slime_header}}}
|
|
#+name: code:built-in-and
|
|
#+begin_src slime
|
|
(printf (and))
|
|
(printf (and 1 2 3 4))
|
|
(printf (and 1 2 () 4))
|
|
(printf (and (> 3 1) (< 3 10)))
|
|
#+end_src
|
|
|
|
#+RESULTS: code:built-in-and
|
|
: evaluates to =>
|
|
: t
|
|
: t
|
|
: ()
|
|
: t
|
|
|
|
- =or= :: (=regular function [C++]=)
|
|
|
|
{{{slime_header}}}
|
|
#+name: code:built-in-org
|
|
#+begin_src slime
|
|
(printf (or))
|
|
(printf (or 1 2 3 4))
|
|
(printf (or 1 2 () 4))
|
|
(printf (or (> 1 3) (< 3 10)))
|
|
#+end_src
|
|
|
|
#+RESULTS: code:built-in-org
|
|
: evaluates to =>
|
|
: ()
|
|
: t
|
|
: t
|
|
: t
|
|
|
|
- =increment= :: (=regular function [Slime]=)
|
|
{{{slime_header}}}
|
|
#+name: code:built-in-increment
|
|
#+begin_src slime
|
|
(printf (increment 11))
|
|
#+end_src
|
|
|
|
#+RESULTS: code:built-in-increment
|
|
: evaluates to =>
|
|
: 12
|
|
|
|
|
|
- =decrement= :: (=regular function [Slime]=)
|
|
{{{slime_header}}}
|
|
#+name: code:built-in-decrement
|
|
#+begin_src slime
|
|
(printf (decrement 12))
|
|
#+end_src
|
|
|
|
#+RESULTS: code:built-in-decrement
|
|
: evaluates to =>
|
|
: 11
|
|
|
|
** Comparison functions
|
|
- === :: (=regular function [C++]=) Takes 0 or more arguments and returns =t= iff
|
|
\[\forall\ \text{arg}_i \in \text{arguments}: \text{arg}_i = \text{arg}_{i+1}\]
|
|
\indent and =()= otherwise.
|
|
|
|
{{{slime_header}}}
|
|
#+begin_src slime
|
|
;; numbers
|
|
(pe (= 1 (+ -1 2)))
|
|
(pe (= 0 (** 3 0)))
|
|
;; strings
|
|
(pe (= "abc" "abc"))
|
|
(pe (= "abc" "abs"))
|
|
;; symbols & keywords
|
|
(pe (= 'sym1 'sym2))
|
|
(pe (= :key1 :key1))
|
|
#+end_src
|
|
|
|
#+RESULTS:
|
|
: evaluates to =>
|
|
: (= 1 (+ -1 2)) evaluates to t
|
|
: (= 0 (** 3 0)) evaluates to ()
|
|
: (= abc abc) evaluates to t
|
|
: (= abc abs) evaluates to ()
|
|
: (= 'sym1 'sym2) evaluates to ()
|
|
: (= :key1 :key1) evaluates to t
|
|
|
|
|
|
- =>= :: (=regular function [C++]=) Takes 0 or more arguments and returns =t= iff
|
|
\[\forall\ \text{arg}_i \in \text{arguments}: \text{arg}_i > \text{arg}_{i+1}\]
|
|
\indent and =()= otherwise.
|
|
- =>== :: (=regular function [C++]=) Takes 0 or more arguments and returns =t= iff
|
|
\[\forall\ \text{arg}_i \in \text{arguments}: \text{arg}_i \ge \text{arg}_{i+1}\]
|
|
\indent and =()= otherwise.
|
|
- =<= :: (=regular function [C++]=) Takes 0 or more arguments and returns =t= iff
|
|
\[\forall\ \text{arg}_i \in \text{arguments}: \text{arg}_i < \text{arg}_{i+1}\]
|
|
\indent and =()= otherwise.
|
|
- =<== :: (=regular function [C++]=) Takes 0 or more arguments and returns =t= iff
|
|
\[\forall\ \text{arg}_i \in \text{arguments}: \text{arg}_i \le \text{arg}_{i+1}\]
|
|
\indent and =()= otherwise.
|
|
|
|
** Controlflow
|
|
- =if= :: (=special form [C++]=) Takes 2 or more arguments. If the first argument (the
|
|
condition) evaluates to a truthy value, the second argument is evaluated and returned.
|
|
Else if more arguemnts are supplied, they will be evaluated and the last result will
|
|
be returned, if the condition was falsy and no further arguments were supplied, then
|
|
nil will be returned.
|
|
|
|
|
|
{{{slime_header}}}
|
|
#+name: built-in-if
|
|
#+begin_src slime
|
|
(printf (if 1 1 2))
|
|
(printf (if () 1 2))
|
|
(printf (if () 1 ))
|
|
#+end_src
|
|
|
|
#+RESULTS: built-in-if
|
|
: evaluates to =>
|
|
: 1
|
|
: 2
|
|
: ()
|
|
|
|
- =cond= :: (=special form [Slime]=)
|
|
|
|
{{{slime_header}}}
|
|
#+name: built-in-cond
|
|
#+begin_src slime
|
|
(define (fib n)
|
|
(cond ((<= n 0) 0)
|
|
((= n 1) 1)
|
|
(else (+ (fib (- n 1))
|
|
(fib (- n 2))))))
|
|
|
|
(printf (fib 6))
|
|
#+end_src
|
|
|
|
#+RESULTS: built-in-cond
|
|
: evaluates to =>
|
|
: 8
|
|
|
|
- =while= :: (=special form [C++]=)
|
|
|
|
{{{slime_header}}}
|
|
#+name: built-in-while
|
|
#+begin_src slime
|
|
(define animals '("Bird" "Dolphin" "Giraffe"))
|
|
|
|
(while animals
|
|
(printf (first animals) "is an animal")
|
|
(define animals (rest animals))
|
|
)
|
|
#+end_src
|
|
|
|
#+RESULTS: built-in-while
|
|
: evaluates to =>
|
|
: Bird is an animal
|
|
: Dolphin is an animal
|
|
: Giraffe is an animal
|
|
|
|
|
|
- =n-times= :: (=special form [Slime]=)
|
|
|
|
{{{slime_header}}}
|
|
#+name: built-in-n-times
|
|
#+begin_src slime
|
|
(n-times 3 (printf "Three time's a charm"))
|
|
#+end_src
|
|
|
|
#+RESULTS: built-in-n-times
|
|
: evaluates to =>
|
|
: Three time's a charm
|
|
: Three time's a charm
|
|
: Three time's a charm
|
|
|
|
|
|
- =when= :: (=special form [Slime]=)
|
|
|
|
{{{slime_header}}}
|
|
#+name: built-in-when
|
|
#+begin_src slime
|
|
(printf (when 1 2 3))
|
|
(printf (when () 2 3))
|
|
#+end_src
|
|
|
|
#+RESULTS: built-in-when
|
|
: evaluates to =>
|
|
: 3
|
|
: ()
|
|
|
|
- =unless= :: (=special form [Slime]=)
|
|
|
|
{{{slime_header}}}
|
|
#+name: built-in-unless
|
|
#+begin_src slime
|
|
(printf (unless 1 2 3))
|
|
(printf (unless () 2 3))
|
|
#+end_src
|
|
|
|
#+RESULTS: built-in-unless
|
|
: evaluates to =>
|
|
: ()
|
|
: 3
|
|
|
|
** Functions for lists
|
|
- =pair= :: (=regular function [C++]=) Takes 2 arguments of any type and return a pair which
|
|
=first= field points to the first argument and the =rest= field points to the second
|
|
argument.
|
|
|
|
{{{slime_header}}}
|
|
#+name: built-in-pair
|
|
#+begin_src slime
|
|
(printf (pair 1 "yes"))
|
|
(printf (pair '+ ()))
|
|
(printf (pair '+ (pair 1 (pair 3 ()))))
|
|
(printf (eval (pair '+ '(1 3))))
|
|
#+end_src
|
|
|
|
#+RESULTS: built-in-pair
|
|
: evaluates to =>
|
|
: (1 . yes)
|
|
: (+)
|
|
: (+ 1 3)
|
|
: 4
|
|
|
|
- =first= :: (=regular function [C++]=) Takes a list as argument and returns the contents of its
|
|
=first= field.
|
|
|
|
{{{slime_header}}}
|
|
#+name: built-in-first
|
|
#+begin_src slime
|
|
(printf (first (pair 1 3)))
|
|
(printf (first (list 2 3)))
|
|
(printf (first '("hello" "world")))
|
|
#+end_src
|
|
|
|
#+RESULTS: built-in-first
|
|
: evaluates to =>
|
|
: 1
|
|
: 2
|
|
: hello
|
|
|
|
|
|
- =rest= :: (=regular function [C++]=) Takes a list as argument and returns the contents of its
|
|
=rest= field.
|
|
{{{slime_header}}}
|
|
#+name: built-in-rest
|
|
#+begin_src slime
|
|
(printf (rest (pair 1 3)))
|
|
(printf (rest (list 2 3)))
|
|
(printf (rest '("hello" "world")))
|
|
#+end_src
|
|
|
|
|
|
- =list= :: (=regular function [C++]=) Takes any number of arguments, evaluates each and returns a
|
|
list containing the results.
|
|
|
|
{{{slime_header}}}
|
|
#+name: built-in-list
|
|
#+begin_src slime
|
|
(printf (list))
|
|
(printf (list 1 2 3))
|
|
(printf (list (pair 1 2)
|
|
'(3 4)
|
|
(list 5 6)))
|
|
#+end_src
|
|
|
|
#+RESULTS: built-in-list
|
|
: evaluates to =>
|
|
: ()
|
|
: (1 2 3)
|
|
: ((1 . 2) (3 4) (5 6))
|
|
|
|
|
|
- =length= :: (=regular function [Slime]=) Takes a list as argument and returns the number of
|
|
elements in that list.
|
|
|
|
{{{slime_header}}}
|
|
#+name: built-in-length
|
|
#+begin_src slime
|
|
(printf (length ()))
|
|
(printf (length '(1 2 3)))
|
|
(printf (length '(+ 1 4 (+ 2 3))))
|
|
#+end_src
|
|
|
|
#+RESULTS: built-in-length
|
|
: evaluates to =>
|
|
: 0
|
|
: 3
|
|
: 4
|
|
|
|
- =end= :: (=regular function [Slime]=) Takes a list as argument. Returns the last pair in the
|
|
list.
|
|
{{{slime_header}}}
|
|
#+name: built-in-end
|
|
#+begin_src slime
|
|
(printf (end ()))
|
|
(printf (end '(1 2 3)))
|
|
(printf (end '(+ 1 4 (+ 2 3))))
|
|
#+end_src
|
|
|
|
#+RESULTS: built-in-end
|
|
: evaluates to =>
|
|
: ()
|
|
: (3)
|
|
: ((+ 2 3))
|
|
|
|
- =last= :: (=regular function [Slime]=) Takes a list as argument. Returns the last element in the
|
|
list.
|
|
|
|
{{{slime_header}}}
|
|
#+name: built-in-last
|
|
#+begin_src slime
|
|
(printf (last ()))
|
|
(printf (last '(1 2 3)))
|
|
(printf (last '(+ 1 4 (+ 2 3))))
|
|
#+end_src
|
|
|
|
#+RESULTS: built-in-last
|
|
: evaluates to =>
|
|
: ()
|
|
: 3
|
|
: (+ 2 3)
|
|
|
|
- =extend= :: (=regular function [Slime]=) Takes a list and any
|
|
|
|
|
|
- =append= :: (=regular function [Slime]=)
|
|
|
|
- =range= :: (=regular function [Slime]=)
|
|
- =range-while= :: (=regular function [Slime]=)
|
|
- =zip= :: (=regular function [Slime]=)
|
|
- =enumerate= :: (=regular function [Slime]=)
|
|
|
|
|
|
- =map= :: (=regular function [Slime]=)
|
|
- =filter= :: (=regular function [Slime]=)
|
|
- =reduce= :: (=regular function [Slime]=)
|
|
- =reduce-binary= :: (=regular function [Slime]=)
|
|
|
|
** Functions on types
|
|
- =type= :: (=regular function [C++]=)
|
|
- =set-type= :: (=regular function [C++]=)
|
|
- =delete-type= :: (=regular function [C++]=)
|
|
- =symbol->keyword= :: (=regular function [C++]=)
|
|
- =string->symbol= :: (=regular function [C++]=)
|
|
- =symbol->string= :: (=regular function [C++]=)
|
|
|
|
** Help and debugging
|
|
- =break= :: (=regular function [C++]=)
|
|
- =memstat= :: (=regular function [C++]=)
|
|
- =info= :: (=regular function [C++]=)
|
|
- =show= :: (=regular function [C++]=)
|
|
- =pe= :: (=special form [Slime]=)
|
|
|
|
** I/O
|
|
- =print= :: (=regular function [C++]=)
|
|
- =read= :: (=regular function [C++]=)
|
|
- =printf= :: (=regular function [Slime]=)
|
|
|
|
** Errors
|
|
- =try= :: (=regular function [C++]=)
|
|
- =error= :: (=regular function [C++]=)
|
|
|
|
** no category
|
|
- =eval= :: (=regular function [C++]=)
|
|
- =apply= :: (=regular function [C++]=)
|
|
- =lambda= :: (=special form [C++]=) See the section about =Lambdas= in [[Lambdas]].
|
|
- =special-lambda= :: (=special form [C++]=) See the section about =Lambdas= in [[Lambdas]].
|
|
|
|
- =copy= :: (=regular function [C++]=)
|
|
- =import= :: (=regular function [C++]=)
|
|
- =load= :: (=regular function [C++]=)
|
|
- =exit= :: (=regular function [C++]=)
|
|
- =let= :: (=regular function [C++]=)
|
|
- =quote= :: (=regular function [C++]=)
|
|
- =quasiquote= :: (=regular function [C++]=)
|
|
- =unquote= :: (=regular function [C++]=)
|
|
- =mutate= :: (=regular function [C++]=)
|
|
- =define= :: (=special form [C++]=) See the section about =define= in [[Define]].
|
|
- =assert= :: (=regular function [C++]=)
|
|
* COMMENT testbox
|
|
* meta :noexport:
|
|
# local variables:
|
|
# org-confirm-babel-evaluate: nil
|
|
# end:
|
|
|
|
#+author: Felix Brendel
|
|
#+mail: felixbrendel@airmail.cc
|
|
#+options: H:2 toc:nil
|
|
|
|
#+macro: slime_header (eval (concat "#+header: :cache yes :exports both" "\n" "#+attr_latex: :options keywordstyle=\\color{slimeKeyword}, commentstyle=\\color{slimeComment}, stringstyle=\\color{slimeString}"))
|
|
#+macro: ditaa_header (eval (concat "#+header: :cache yes :exports results :cmdline --no-separation --no-shadows"))
|
|
|
|
#+latex_class:article
|
|
|
|
#+latex_header: \usepackage[german]{babel}
|
|
#+latex_header: \usepackage{xcolor}
|
|
#+latex_header: \usepackage{listings}
|
|
#+latex_header: \usepackage[pageanchor=false]{hyperref}
|
|
|
|
#+latex_header: \definecolor{slimeKeyword}{HTML}{B58900}
|
|
#+latex_header: \definecolor{slimeString}{HTML}{2AA198}
|
|
#+latex_header: \definecolor{slimeComment}{HTML}{839496}
|
|
|
|
|
|
#+latex_header: \lstdefinelanguage{slime}
|
|
#+latex_header: {
|
|
#+latex_header: % list of keywords
|
|
#+latex_header: otherkeywords = {+,=,>,>=,<,<=,-,*,/,**},
|
|
#+latex_header: morekeywords={+,=,>,>=,<,<=,-,*,/,**,assert,define,define-syntax,mutate,if,quote,quasiquote,and,or,not,while,let,lambda,special,eval,begin,list,pair,first,rest,set-type,delete-type,type,info,show,print,read,exit,break,memstat,try,load,copy,error,symbol->keyword,string->symbol,symbol->string,concat-strings},
|
|
#+latex_header: basicstyle=\ttfamily\small,
|
|
#+latex_header: showstringspaces=false,
|
|
#+latex_header: sensitive=true, % keywords are not case-sensitive
|
|
#+latex_header: morecomment=[l]{;}, % l is for line comment
|
|
#+latex_header: morestring=[b]" % defines that strings are enclosed in double quotes
|
|
#+latex_header: }
|
|
|
|
#+latex_header:\AtBeginDocument{\renewcommand{\lstlistingname}{Code}}
|
|
#+latex_header:\AtBeginDocument{\renewcommand{\ref}[1]{\autoref{#1}}}
|