Scheme is one of the three major dialects of the programming language Lisp. It has many similar syntax as Lisp but features minimalism. In this post, I'll summarize basic Scheme syntax after I read this book to get started with Scheme. That should be helpful to get started since I already have some programming experience.
Everything Meaningful Is in a List Form
The basic syntax is in the form (obj1 obj2 ...)
or(expression1 expression2 ...)
. For example, (1 2 3)
is a list that contains 1, 2, and 3. Each element can be of different types. So it can contain strings too. For example, (1 2 'hello')
. If it is a procedure call, the first expression is the procedure name. For example (+ 1 2)
. The first element is +
. It's the sum operator. It adds the numbers from the remaining of the list.
We can nest expressions. Each expression itself can be in the list form. That being said, the first one can be in the list form which returns a procedure. And then apply the remaining elements to the returned procedure.
You can have a single symbol or value too. For example "Hello"
will generate "Hello". And 2
will generate 2. But if you want to have a meaningful operation, you should use the list form.
Basic Operations
These are the basic operations
(quote expression)
As I said before, the data and procedure call are in the same form.
quote
will force to treat the remaining as data. For example,(+ 1 2)
is to calculate the sum of 1 and 2, which it generates 3.(quote (+ 1 2))
will always treat(+ 1 2)
as data.+
becomes the symbol instead of the operation. So it generates(+ 1 2)
instead of doing the calculation. We can use'
to replacequote
for abbreviation. So'(+ 1 2)
is the same as(quote (+ 1 2))
.(car list-expression)
returns the first element in the list(car '(1 2 3)) => 1
(cdr list-expression)
returns the list that contains the elements except the first one.(cdr '(1 2 3)) => (2 3)
(cons obj1 obj2)
generates a new pair in whichobj1
is the first element and the remaining are fromobj2
.It can generate a proper list or an improper list. For example,
(cons 'a 'b) => (a . b) ; an improper list
(cons 'a '(b c)) => (a b c) ; a proper list
Variable, Expression and Procedure
The syntax to define a lambda expression is
(lambda (var ...) body1 body2 ...)
The syntax to define a top level variable or procedure is
(define var expression)
The syntax to create a variable at the local scope is
(let ((var expression) ...) body1 body2 ...)
We can use both define
and let
to create a variable or a procedure.
For example, (define count 0)
creates a variable count
with the value 0. (let count 0)
also creates a variable count
with the value 0.
To define a procedure, it's in the form
(define sum
(lambda (x y)
(+ x y)))
This creates a procedure sum
at the top level. It sums up the two given arguments.
The difference between define
and let
is that define
creates the variable or procedure at the top level. Any other code can reference to it. let
creates it inside the let
scope. That means, the variable or the procedure isn't available outside of let
code.
We can nest let
statements. In this case, the variable or procedure with the same name will shadow the one from outer scope. Here is the code to demonstrate it.
(define var 1)
(let ((var 2))
(let ((var 3))
(display var)
(newline))
(display var)
(newline))
(display var)
(newline)
(display)
is used to show the argument on the output. (newline)
shows a new line. The output of this code is
3 2 1
The variable var
in the inner scope shadows the one from outer scope.
Conditional Expression
We can do a if
check in Scheme. The syntax is
(if test consequent alternative)
The test
can be and
, or
, and not
. The syntax is
(and expression ...)
(or expression ...)
(not expression)
Similarly to if
, we can also do switch
(cond (test expression) ... (else expression))
There are special symbol. #t
means true and #f
means false.
Report errors
(assertion-violation symbol-of-scope message what-violates)
Set Assignment
(set! symbol value)
Improper List
The definition of a proper list uses recursion. A proper list is the list of which the (cdr)
is a proper list. And an empty list is a proper list. If a list isn't a proper list, it's an improper list. An improper list is denoted by a '.'. For example (a . b) is an improper list and (a b) is a proper list. Below is an example in the code
(cons 'a 'b) => (a . b)
(cdr (a . b)) => b ; b is not a list
(cons 'a '(b)) => (a b)
(cdr (a b)) => (b); (b) is a list
These are the basic syntax and building block of Scheme. With that we can go on to the advanced Scheme and start writing programs.