Gerbil Scheme quick Guide for Beginners
1. What is it?
Scheme
is a classic programming language in the Lisp family. It emphasizes functional programming and domain-specific languages but adapts to other styles. Known for its clean and minimalist design, Scheme is one of the longest-lived and best-studied dynamic languages, and has many fast and portable implementations.
Gerbil
is a programming language that acts as an extension or dialect of the Scheme language, designed to enhance productivity and improve performance. It is built on top of Gambit Scheme, which is another highly efficient Scheme implementation.
2. Installation
sudo apt install libssl-dev zlib1g-dev libsqlite3-dev
git clone https://github.com/mighty-gerbils/gerbil.git
cd gerbil
./configure
make -j4
sudo make install
/opt/gerbil/bin
should be added to the PATH environment variables.
3. Introduction to Gerbil
3.1 Core Gerbil
- Primitive forms
def
: same as define
(def (say-hello who)
(displayln "hello " who))
(say-hello "world")
defvalues
: same as define-values
(defvalues (a b)
(values 1 2))
lambda
: optional argument
(def (an-opt-lambda a (b 1))
(+ a b))
(an-opt-lambda 1)
lambda
: keyword argument
(def (a-keyword-lambda a b: (b 1))
(+ a b))
(a-keyword-lambda 1)
(a-keyword-lambda 1 b: 2)
lambda
: optional and keyword argument
(def (a-keyword-lambda-with-options a b: (b 1) (c 3) . rest)
(+ a (* b c)))
(a-keyword-lambda-with-options 1)
(a-keyword-lambda-with-options 1 b: 2)
(a-keyword-lambda-with-options 1 b: 2 4)
case-lambda
:
(def my-case-lambda
(case-lambda
((a b) (+ a b))
((a) (+ a 1))))
; or the short definition form
(def* my-case-lambda
((a b) (+ a b))
((a) (+ a 1)))
argument bindings
:
(let ((x 1) ((values y z) (values 2 3)))
(+ x y z))
_ identifier
:
(def (a-function x . _) ; accepts 1 or more ignored args
(+ x 1))
pair
:
[1 . 2]
list
:
[1 2 3*]
list splicing
:
[1 2 [3 4 5] ... 6]
set!
: bindings can be mutated with set!
(def a #f)
(set! a 'a)
set!
: binding mutation with s-expression
(def a-pair (cons 'a 'b))
(set! (car a-pair) 'c)
(car a-pair)
- Pattern Matching
example:
(def (my-destructurer obj)
(match obj
([a . b]
(printf "a pair (~a . ~a)~n" a b)
'pair)
((point-3d x y z)
(printf "a 3d-point (~a ~a ~a)~n" x y z)
'point-3d)
((point x y)
(printf "a 2d point (~a ~a)~n" x y)
'point-2d)
(else 'something-else)))
<>
: shorthand syntax
(def car+cdr (match <> ([a . b] (values a b))))
> (car+cdr [1 2 3])
values 1 '(2 3)
with
:
(def (car+cdr obj)
(with ([a . b] obj)
(values a b)))
(def (car+cdrx2 lsta lstb)
(with (([a-car . a-cdr] lsta)
([b-car . b-cdr] lstb))
(values a-car a-cdr b-car b-cdr)))
- Macros
defrules
: defining syntax-rules macros
(defrules macro-id (id ...)
(head [guard] body) ...)
defsyntax
: more complicated macros with syntax-case
(defsyntax (with-magic stx)
(syntax-case stx ()
((macro expr body ...)
(with-syntax ((magic-id (datum->syntax #'macro 'magic)))
#'(let (magic-id expr) body ...)))))
> (with-magic 3 (+ magic 1))
4
defsyntax-for-match
: match expander
(defsyntax-for-match id match-macro [macro])
begin-syntax
:
(begin-syntax
(def (identifier-or-keyword? stx)
(or (identifier? stx)
(stx-keyword? stx)))
(def (identifiers-or-keywords? lst)
(andmap identifier-or-keyword? lst)))
3.2 Objective Gerbil
- Defining Class
defclass
:
(defclass Point (x y))
(defclass (Point3D Point) (z))
Initialize the Point/Point3D:
(make-Point x: 1 y: 2)
(make-instance Point::t x: 1 y: 2)
Slots:
(Point-x a)
@
: dynamic slot operator
(@ a x)