A lisp reader is an invisible wrapper around a TextReader and a combination of a scanner and parser. The scanner recognizes tokens such as parentheses, numbers, strings and other character combinations that have a special meaning.

The parser creates S-expressions from the stream of tokens. Sometimes tokens are converted to multiple tokens.


The reader handles line comments and block comments

123 ; line comment
123 #! line comment
(+ 123 #| block comment |# 456)

Abbreviated lambda expressions

user > #(+ 2 %)
it: #<Lambda Name="anonymous">
user > #(* %3 %3)
it: #<Lambda Name="anonymous">
user > (it 1 2 3)
it: 9

Accessor functions

user > .
it: #<Function Name="Kiezel.Runtime.MemberAccessor">
user > (. "to-upper")
it: #<AccessorLambda Name="to-upper" Nullable="False">
user > .to-upper
it: #<AccessorLambda Name="to-upper" Nullable="False">
user > (.to-upper "hello")
it: "HELLO"


user > #9r13
it: 12
user > #b111
it: 7
user > #o77
it: 63
user > #x20
it: 32


user > #q{a b c}
it: "a b c"
user > #q(a b c)
it: "a b c"
user > #q[a b c]
it: "a b c"
user > #q<a b c>
it: "a b c"
user > #q anything really
       drieanything really
it: "een                          \ntwee                         \ndrie"

Regular expression literals

user > #/a(a)p/i
it: #/a(a)p/i
user > :d
#s( :members #s( :match-timeout -00:00:00.0010000
                 :options IgnoreCase
                 :right-to-left false )
    :type "Kiezel.RegexPlus"
    :value #/a(a)p/i )

Backquote expressions

A backquote expression is a template for a piece of lisp code that must execute to produce output. The names bq:list, bq:force, bq:quote and bq:append are used to clarify the translation of the backquote expression. They behave as their counterparts in the lisp package.

user > (quote `(a b c))
it: (bq:list (bq:quote a) (bq:quote b) (bq:quote c))
user > `(a b c)
it: (a b c)
user > (var b '(1 2 3))
it: b
user > (quote `(a ,b c))
it: (bq:list (bq:quote a) (bq:force b) (bq:quote c))
user > `(a ,b c)
it: (a (1 2 3) c)
user > (quote `(a ,@b c))
it: (bq:append (bq:list (bq:quote a)) (bq:force b) (bq:list (bq:quote c)))
user > `(a ,@b c)
it: (a 1 2 3 c)

Immediate execution expressions

user > '(1 (+ 2 3) 4)
it: (1 (+ 2 3) 4)
user > (setq $read-eval true)
it: true
user > '(1 #.(+ 2 3) 4)
it: (1 5 4)

(Un)conditional inclusion or exclusion of forms

The following examples show how to include or exclude a single form. The first argument after #+ and #- is a logical expression that refers to symbols in the $features list. The second argument is the form to include or exclude.

user > $features
it: (:kiezellisp :kiezellisp-con :linux :mono :repl :unix :x64)
user > '(a #; b c)
it: (a c)
user > '(a #ignore b c)
it: (a c)
user > '(a #+x32 b c)
it: (a c)
user > '(a #-x32 b c)
it: (a b c)
user > '(a #+bla b c)
it: (a c)
user > '(a #-bla b c)
it: (a b c)
user > '(a #+(and x32 (not bla)) b c)
it: (a c)

We can also include/exclude more than one (usually top-level) form:

user > '(#if unix 1 2 #elif windows 3 #else 4 5 #endif)
it: ((compile-time-branch 1 2))

Please note that this feature is form-aware and not line-aware and that the forms in the choosen branch are executed as a single top-level form.

Infix notation

user > '#i(1+x)
it: (+ 1 x)
user > '#i(sin(x)**(1+1)+cos(x)**2)
it: (+ (math:pow (sin x) (+ 1 1)) (math:pow (cos x) 2))


The #s(...) reader macro produces a prototype object as a literal. When the number of items in the list is odd, the first item must be the type name of a prototype which will become the parent of the constructed prototype.

user > #s(aap 1 noot 2)
it: #s( :aap 1
        :noot 2 )
user > (defstruct mies aap (noot 4) (teun 5))
it: mies
user > #s(mies aap 1 noot 2)
it: #s(mies :aap 1
            :noot 2
            :teun 5 )
user > (type? it 'mies)
it: true
user > #s(mies2 aap 1 noot 2)
Undefined type name: user::mies2

Read tables


See also

$features $read-eval $readtable peek-char read read-all read-all-from-string read-char read-delimited-list read-from-string set-dispatch-macro-character set-macro-character unread-char with-input-from-string