See inside

Recommended you run in turbo mode.

Code and data use the same syntax for lists: (stuff...) where stuff is a list of things separated by whitespace such as symbols (alphanumerical characters and most other non-whitespace characters on your keyboard besides (, ), ', #, and ;), numbers (integers only for now), booleans (#t for true and #f for false), or other lists with the same recursive syntax.

When a list is evaluated, the function goes at the start of the list, and the arguments follow it: for example, (+ 1 3) or (* 7 6) or (cons 1 (cons (* 6 5) 4)).

Symbols evaluate to variables, which you set for the first time with the define special form, then use either set! or define after that, like this:
(define my-variable 4)
(set! my-variable 4)

The alternative syntax for define has not been implemented yet.

The ' character before anything expands into (quote <that thing>), which evaluates as literally <that thing> rather than it's value. For example: (cons 'a '(b c 1)) does not treat a b or c as variables because they were quoted.

Numbers and booleans (#t for true and #f for false) are self-evaluating, that is they evaluate as themselves.

The begin special form lets you do stuff in sequence and only returns the value of the last one, for example
(set! x 3)

The if special form is like if/else in scratch: if the first thing is true (anything which isn't #f is considered true btw), the second will be evaluated, otherwise the third will, or it will return void if there is no 3rd thing. Example:
(if (< x 3)

Lambdas are hard to explain. They are custom procedures, a bit like custom blocks in scratch, but they are first class, and are like rings in Snap!. This means a variable can be one, or you can pass one to a function. I can't really explain it fully here, so read SICP (linked below).

You can define functions like this:
(define square (lambda (x) (* x x)))
(square 3) ; is 9

There's an alternative syntax for define to define functions, but it's not yet implemented.

You can make loops using recursion. If you write it tail recursively, it won't consume too much stack space.

(define write-all-nums (lambda (num)
(if (= num 0)
(write num)
(write-all-nums (- num 1))))))

(define factorial (lambda (num)
(if (= num 0)
(* num (factorial (- num 1))))))

(factorial 4) ;should be 24

You can even make higher order functions:

(define map (lambda (f lst)
(if (eq? lst '())
(cons (f (car lst)) (map f (cdr lst))))))

(map (lambda (x) (+ x 1)) '(1 2 3)) ; should be (2 3 4)

Lambda alone even makes scheme turing complete!

If you haven't read it yet, I'd highly recomend reading SICP:

Notes and Credits


This is a test for an interpreter for the programming language "Scheme" which I'm making in scratch. It's is now powerful enough to be considered a small subset of scheme. It has lists, quoting, numbers, symbols, variables, if, begin, lambda and the primitives +, -, *, /, mod (integer division only), <, >, =, eq?, cons, car, cdr, read, eval, display, write, and apply.

Inspired by the textbook SICP:
Recent changes:
Fixed a bug involving defining a variable as the value of an expression that called a custom procedure
Added apply

Known bugs:
(Anyone who finds a bug will get credit here)

Fixed bugs:
- Doesn't work at all, discovered by hardmath123
- Mathematical operators don't work, discovered by me
- If doesn't work, discovered by Jonathan50
- Variables don't work, discovered by Jonathan50
- If doesn't work properly, discovered by me
- Variable not bound error when attempting to define cadr, discovered by Jonathan50
- Set-car doesn't work, discovered by Johnathan50

Shared: 2 Mar 2013 Modified: 23 May 2016
Favorite this project 12
Love this project 19
Total views 395
View the remix tree  1
More projects by joefarebrother