2023-02-27

scheme syntax overview

"..." means zero or more repetitions of the preceding expression. it is only actually written in syntax patterns

self-evaluating

boolean: #t #f

characters

  • character: #\a #(
  • code point hexadecimal: #\x1ff #\x200
  • named characters: #\nul #\alarm #\backspace #\tab #\linefeed #\vtab #\page #\return #\esc #\space #\delete

strings

  • string: "abc" "ab\nc"
  • escape sequences: \\ \" \| \a \f \n \r \t \v \b \0
  • string with code point hexadecimal escape sequence: "ab\x0ac" "\x41;bc"

numbers

  • binary: #b1111011
  • complex: 1+2i 3.4+5i
  • e-notation: 1e22 1.0e22 -1e22
  • hexadecimal: #x7b
  • infinity: +inf.0 -inf.0
  • integer: 123
  • negative: -123 -123.4
  • octal: #o173
  • real or rational: 123.4 1/3

identifiers

most ascii characters that are not control characters or whitespace are allowed. for example

test-identifier?
! $ % & * + - . / : < = > ? @ ^ _ ~

comments

until end of line

; ab c

range

#;(ab c)

#;(abc
    (efg #;(nested even)))

level 1

literals, quoting, content as data (for example lists or symbols)

(quote a)
(quote (a b))

branching

(if test consequent alternate)
(if test consequent)

sub-routines, procedures, content executed only when called

creation

(lambda (formals ...) expression other-expressions ...)

(lambda (a b c) (+ a b c))

(lambda (a b c . rest) expression other-expressions ...)

(lambda a expression other-expressions ...)

body must contain at least one expression

usage, application, call

( (lambda (a b) (display (+ a b)))
  1 2)

(apply (lambda (a b) (display (+ a b)))
  (list 1 2))

(define test (lambda (a b) (+ 1 a b)))
(test 2 3)

binding

top-level

(define a 1)
(define b (+ 2 3))

explicit scope

( (lambda (a b)
    (+ a b))
  1 2)

syntax transformers

(syntax-case syntax-object-name ()
  (pattern expansion ...)
  ...)
(syntax-case s () ((_ a b) (syntax (+ a b))))
(syntax-case s ()
  ( (_ a (b ...) ... c)
    (syntax (+ a (+ 1 b ...) ... c)))
  ((_ a) (syntax a)))

syntax binding

top-level

(define-syntax test (lambda (s) syntax-transformer))
(define-syntax test
  (lambda (s)
    (syntax-case s () ((_ a b) (syntax (+ a b))))))

usage

(test 1 2)

explicit scope

(let-syntax ((test-1 syntax-transformer) (test-2 syntax-transformer)) (test 1 2))
(let-syntax
  ( (test
      (lambda (s)
        (syntax-case s () ((_ a b) (syntax (+ a b)))))))
  (test 1 2))

serialisation

(begin any-expression ...)

the last expression is the result, unless the "begin" form is specified at the top-level. on the top-level the contents are merged with the series of other top-level expressions as if the enclosing "begin" where not there. this is to make it possible to create macros that create top-level restricted code like defines

; top-level
(begin
  (define a 1)
  (define b 2))

same as

; top-level
(define a 1)
(define b 2)

level 2

based on forms of level 1

quasiquote. unquote evaluates and inserts the result

(quasiquote (+ 1 (unquote (+ 2 3)) (unquote (+ 4 5))))

binding

explicit scope

bound in unspecified order (possibly at once)

(let ((a 1) (b 2))
  a)

bound one after another

(let* ((a 1) (b (+ 2 a)))
  b)

bound one after another, with binding usable in definition

(letrec
  ((a
     (lambda (b)
       (if (< b 10)
         (a (+ 1 b))
         b)))
   (b (a 1)))
  b)

sub-routines, procedures

(define (a b c) (+ b c))

definition looks similar to application

usage, application

(a 1 2)
(apply a (list 1 2))

scoped, recursively applicable, named-let

(let loop ((a 10) (b 2))
  (if (> a 0)
    (loop (- a 1) b)))

(let a () #t)

syntax transformers

(syntax-case syntax-object ()
  ((_ a b) (quasisyntax (+ 1 (unsyntax a) (unsyntax b)))))

(syntax-case s ()
  (syntax-case s ()
    ((_ a b) (syntax (+ a b)))))

(syntax-rules ()
  ((_ b c) (+ b c))
  ((_ b ...) (+ c b ...)))

(syntax-rules (literal-keyword-to-match ...)
  ((_ b literal-keyword-to-match c) (+ b c)))

syntax binding

(define-syntax-rules (a b ... c d)
  (+ b ... c d))

(define-syntax a
  (syntax-rules ()
    ((_ b c) (+ b c))))

links