2006 small scheme
DESCRIPTION
Building a Scheme interpreter in Smalltalk. Lectured given at the Engineering school of Annecy (France) in 2006TRANSCRIPT
![Page 1: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/1.jpg)
Functional Languages Interpretation
in Smalltalk
Alexandre BergelLero & DSG, Trinity College Dublin,Ireland
[email protected]/Alexandre.Bergel
November 2006
![Page 2: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/2.jpg)
Alexandre Bergel
Goal
• Studying the implementation of Scheme-like languages in an object-oriented environment.
• Dynamic versus static scoping
2
![Page 3: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/3.jpg)
Alexandre Bergel
Outline
1. Essence of Scheme2. SmallScheme overview3. Modeling environment4. Reading and parsing Scheme5. Primitive expression types6. Dynamic and static scoping7. Further notes...
3
![Page 4: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/4.jpg)
Alexandre Bergel
Essence of Scheme
4
1. Idea behind Scheme2. Examples3. Evaluation
![Page 5: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/5.jpg)
Alexandre Bergel
Essence of Scheme
“Scheme demonstrates that a very small number of rules for forming expression, with no restriction on how they are composed, suffice to form a practical and efficient programming language that is flexible enough to support most of the major programming paradigms in use today.”
R5RS, page 2
The first description of Scheme was written in 1975
5
![Page 6: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/6.jpg)
Alexandre Bergel
Manipulate parenthesized expressions
Example of Scheme expression:10 => 10‘aSymbol => aSymbol(+ 1 2) => 3(if cond else then)(let ((a 10) (b 15) (+ a (* 2 b))) => 40(define (fac n) (if (= n 0) 1 (* n (fac (- n 1)))))(fac 10) => 3628800
6
![Page 7: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/7.jpg)
Alexandre Bergel
Closure application
In such expression:(expr expr1 expr2 ... exprN)
1 - expr is first evaluated into f
2 - expr1 ... exprN are evaluated (most of the time sequentially). Let’s assume results are v1 ... vN
3 - v1 ... vN are applied to f
7
![Page 8: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/8.jpg)
Alexandre Bergel
Special form (1/3)
Exceptions to the previous rule are special forms.
Condition of a if statement needs to be evaluated before other arguments.
(if (= x 0)‘error(/ 1 x))
(= x 0) is evaluated first, then, according to this value, ‘error or (/ 1 x) is evaluated.
8
![Page 9: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/9.jpg)
Alexandre Bergel
Special form (2/3)
The body of a function is evaluated only when the function is applied
(define (foo x) (+ x (* 2 x)))
It binds (lambda (x) (+ x (* 2 x))) to foo
9
![Page 10: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/10.jpg)
Alexandre Bergel
Special form (3/3)
The body of an anonymous function is evaluated only when applied
((lambda (x) (* x x)) 2)
10
![Page 11: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/11.jpg)
Alexandre Bergel
Manipulate parenthesized expressions
Sequence of evaluation(fac 2)
11
![Page 12: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/12.jpg)
Alexandre Bergel
Manipulate parenthesized expressions
Sequence of evaluation(fac 2)((lambda (n) (if (= n 0)
1 (* n (fac (- n 1))))) 2)
12
![Page 13: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/13.jpg)
Alexandre Bergel
Manipulate parenthesized expressions
Sequence of evaluation(fac 2)((lambda (n) (if (= n 0)
1 (* n (fac (- n 1))))) 2)(if (= 2 0) 1 (* 2 (fac (- 2 1))))
13
![Page 14: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/14.jpg)
Alexandre Bergel
Manipulate parenthesized expressions
Sequence of evaluation(fac 2)((lambda (n) (if (= n 0)
1 (* n (fac (- n 1))))) 2)(if (= 2 0) 1 (* 2 (fac (- 2 1))))
(* 2 (fac (- 2 1)))(* 2 (fac (- 2 1)))(* 2 (fac (- 2 1)))(* 2 ((lambda (n) (if (= n 0) ...)) (- 2 1)))...
14
![Page 15: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/15.jpg)
Alexandre Bergel
SmallScheme overview
15
![Page 16: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/16.jpg)
Alexandre Bergel
What is SmallScheme
• SmallScheme is an interpreter of a subset of Scheme in Squeak.
16
![Page 17: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/17.jpg)
Alexandre Bergel
How to use SmallScheme
In a programmatic way, Scheme expression can be evaluated:
Scheme evalString: ‘(+ 2 3)’=> 5
Scheme evalString: ‘(define (fac n)
(if (= n 0) 1 (* n (fac (- n 1)))))(fac 10)’
=> 3628800
17
![Page 18: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/18.jpg)
Alexandre Bergel
Writing Scheme in Smalltalk with SmallScheme
Available on www.squeaksource.com
MCHttpRepositorylocation: 'http://www.squeaksource.com/Scheme'
user: '' password: ''
18
![Page 19: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/19.jpg)
Alexandre Bergel
shouldArgsBeEvaluated
Class Hierarchy
19
SchemeObject
Boolean Number Pair String Symbol
Primitive
Add Begin Car If Closure
Cons MakeClosure ...
eval: anEnv
apply: args withEnv: anEnv
![Page 20: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/20.jpg)
Alexandre Bergel
Modeling environment
20
1. Set of bindings2. Hierarchy of environments3. Primitive definitions
![Page 21: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/21.jpg)
Alexandre Bergel
Environment
21
a -> 1b -> 2
x -> 5y -> 7
+ -> ...- -> ...if -> ......
currentenvironment
(let ((x 5) (y 7)) (let ((a 1) (b 2)) ...))
An environment has a parent and a set of bindings
![Page 22: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/22.jpg)
Alexandre Bergel
Modeling Environments (1/3)
22
Each environment has a set of bindings and a parent:
Object subclass: #SchemeEnvironmentinstanceVariableNames: 'dictionary parent'
SchemeEnvironment>>get: aSymbol^ dictionary
at: aSymbol asSmalltalkObject ifAbsent: [parent get: aSymbol]
SchemeEnvironment>>at: aSymbol put: aValuedictionary
at: aSymbol asSmalltalkObject put: aValue
![Page 23: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/23.jpg)
Alexandre Bergel
Modeling Environment (2/3)
Creating a new environment:
SchemeEnvironment class>>createFromEnv: anEnv^ self new withEnvironment: anEnv.
SchemeEnvironment>>withEnvironment: anEnvparent := anEnv.dictionary := Dictionary new.parent isNil
ifTrue: [self initializePrimitives].
The environment root should be aware of different primitives.
23
![Page 24: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/24.jpg)
Alexandre Bergel
Modeling Environment (3/3)
The root of the environment contains the primitives:SchemeEnvironment>>initializePrimitives
{{'if' . SchemePrimitiveIf} . {'begin' . SchemePrimitiveBegin} .{'loadfile' . SchemePrimitiveLoadfile} .{'display' . SchemePrimitiveDisplay} .{'newline' . SchemePrimitiveNewline} .{'set!' . SchemePrimitiveSet} .{'let' . SchemePrimitiveLet} .{'>' . SchemePrimitiveGreater} .{'<' . SchemePrimitiveLesser} .{'+' . SchemePrimitiveAdd} .{'/' . SchemePrimitiveDiv} .{'*' . SchemePrimitiveMul} .{'-' . SchemePrimitiveSub} .{'=' . SchemePrimitiveEqual} .{'define' . SchemePrimitiveDefine} .{'quote' . SchemePrimitiveQuote} .{'lambda' . SchemePrimitiveMakeClosure} .{'null?' . SchemePrimitiveNull} .{'car' . SchemePrimitiveCar} .{'cdr' . SchemePrimitiveCdr} .{'cons' . SchemePrimitiveCons}} do: [:pair| self at: pair first asSymbol put: pair second new]
24
![Page 25: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/25.jpg)
Alexandre Bergel
Reading Scheme (R5RS, Section 1.2, 2, 7)
1. Lexical analysis2. Parsing Scheme3. SmallScheme uses a minimal grammar
25
![Page 26: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/26.jpg)
Alexandre Bergel
Lexical Analysis
Defined by the class SchemeLexer
Public methods are: SchemeLexer class>>analyseString: aStringSchemeLexer >>nextSchemeLexer >>getTokenSchemeLexer >>getType
The type of a token could either be a boolean, (, ), ‘(), an integer, a string, or a symbol.
26
![Page 27: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/27.jpg)
Alexandre Bergel
Parsing Scheme
Defined by the class SchemeParser
Public methods are: SchemeParser class>>lexer: aLexerSchemeParser >>next
The next method returns a scheme object
27
![Page 28: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/28.jpg)
Alexandre Bergel
Grammar of SmallScheme
Very minimal grammarexpr =
<number> |<symbol> |<string> |<nil> |( expr+ ) |‘ expr
Primitive types are not part of the grammar. This gives more flexibility regarding the definition of those types.
This is a major difference between SmallScheme and R5RS.
28
![Page 29: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/29.jpg)
Alexandre Bergel
Example: the quote case
SchemeParser>>next| l |l := lexer next....lexer getType == SchemeLexer quoteID
ifTrue: [ ^ SchemePair
car: (‘quote’ asSchemeSymbol)cdr: (SchemePair
car: self next cdr: nil)]
29
‘x = (quote x) = quote x
![Page 30: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/30.jpg)
Alexandre Bergel
Primitive expression types (R5RS, Section 4.1)
1. Variable reference2. Literal expression (quote)3. Procedure calls4. Procedures (lambda)5. Conditionals
30
![Page 31: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/31.jpg)
Alexandre Bergel
Variable Reference
Class SchemeSymbol:
SchemeObject subclass: #SchemeSymbolinstanceVariableNames: 'value'
SchemeSymbol>>eval: anEnvironment^anEnvironment get: value
Scheme evalString: ‘(define x 5) x’=> 5
31
![Page 32: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/32.jpg)
Alexandre Bergel
Literal expression (quote)
Class SchemePrimitiveQuote:
SchemePrimitive subclass: #SchemePrimitiveQuote
SchemePrimitiveQuote>>apply: listOfArguments withEnv: anEnvironment“arguments are not evaluated”^listOfArguments car
SchemePrimitiveQuote>>initializeself doNotEvaluateArguments
Scheme evalString: '(quote (+ 1 2)'=> (+ 1 2)
32
![Page 33: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/33.jpg)
Alexandre Bergel
Procedure calls
Associated with the lambda keywordSchemePrimitive subclass: #SchemePrimitiveMakeClosure
SchemePrimitiveMakeClosure>>apply: listOfArguments withEnv: anEnvironment
|args body|args := listOfArguments car.body := listOfArguments cdr.
^ SchemePrimitiveClosure createWithArgs: args body: body env: anEnvironment
33
![Page 34: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/34.jpg)
Alexandre Bergel
Procedure calls
SchemePrimitive subclass: #SchemePrimitiveClosureinstanceVariableNames: 'arguments body env'
When we execute the following:Scheme evalString: ‘((lambda (x y) (+ x y)) 2 3)’
SchemePrimitiveClosure>>apply: listOfArguments withEnv: anEnvironment ...
listOfArguments is a collection containing 2 and 3
34
![Page 35: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/35.jpg)
Alexandre Bergel
Procedure calls
SchemePrimitiveClosure>>apply: listOfArguments withEnv: anEnvironment | env b valuesProvided argNames |valuesProvided := listOfArguments.argNames := arguments.env := SchemeEnvironment createFromEnvironment: environment.
[valuesProvided isNil] whileFalse: [env at: argNames car put: valuesProvided car.argNames := argNames cdr.valuesProvided := valuesProvided cdr.].
b := body.
[b cdr isNil] whileFalse: [b car eval: env. b := b cdr].
^ b car eval: env
35
![Page 36: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/36.jpg)
Alexandre Bergel
Creation of a new environment
SchemePrimitiveClosure>>apply: listOfArguments withEnv: anEnvironment | env b valuesProvided argNames |valuesProvided := listOfArguments.argNames := arguments.env := SchemeEnvironment createFromEnvironment: environment.
[valuesProvided isNil] whileFalse: [env at: argNames car put: valuesProvided car.argNames := argNames cdr.valuesProvided := valuesProvided cdr.].
b := body.
[b cdr isNil] whileFalse: [b car eval: env. b := b cdr].
^ b car eval: env
36
![Page 37: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/37.jpg)
Alexandre Bergel
Binding variables in the new environment
SchemePrimitiveClosure>>apply: listOfArguments withEnv: anEnvironment | env b valuesProvided argNames |valuesProvided := listOfArguments.argNames := arguments.env := SchemeEnvironment createFromEnvironment: environment.
[valuesProvided isNil] whileFalse: [env at: argNames car put: valuesProvided car.argNames := argNames cdr.valuesProvided := valuesProvided cdr.].
b := body.
[b cdr isNil] whileFalse: [b car eval: env. b := b cdr].
^ b car eval: env
37
![Page 38: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/38.jpg)
Alexandre Bergel
SchemePrimitiveClosure>>apply: listOfArguments withEnv: anEnvironment | env b valuesProvided argNames |valuesProvided := listOfArguments.argNames := arguments.env := SchemeEnvironment createFromEnvironment: environment.
[valuesProvided isNil] whileFalse: [env at: argNames car put: valuesProvided car.argNames := argNames cdr.valuesProvided := valuesProvided cdr.].
b := body.
[b cdr isNil] whileFalse: [b car eval: env. b := b cdr].
^ b car eval: env
Evaluating the body of the closure
38
![Page 39: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/39.jpg)
Alexandre Bergel
And returning the last value...
SchemePrimitiveClosure>>apply: listOfArguments withEnv: anEnvironment | env b valuesProvided argNames |valuesProvided := listOfArguments.argNames := arguments.env := SchemeEnvironment createFromEnvironment: environment.
[valuesProvided isNil] whileFalse: [env at: argNames car put: valuesProvided car.argNames := argNames cdr.valuesProvided := valuesProvided cdr.].
b := body.
[b cdr isNil] whileFalse: [b car eval: env. b := b cdr].
^ b car eval: env
39
![Page 40: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/40.jpg)
Alexandre Bergel
Conditionals
(if (= 2 3) ‘hello ‘world)
SchemeObject subclass: #SchemePrimitiveIf
SchemePrimitiveIf>>initializeself doNotEvaluateArguments
SchemeSymbol>>apply: listOfArguments withEnv: anEnvironment | cond then else |cond := listOfArguments car.then := listOfArguments cdr car.
listOfArguments cdr cdrifNotNil: [else := listOfArguments cdr cdr car].
cond := cond eval: anEnvironment.cond isTrue
ifTrue: [^ then eval: anEnvironment].else notNil
ifTrue: [^ else eval: anEnvironment].^ Scheme undefined
40
![Page 41: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/41.jpg)
Alexandre Bergel
Conditionals explained
(if (= 2 3) ‘hello ‘world)
SchemeObject subclass: #SchemePrimitiveIf
SchemePrimitiveIf>>initializeself doNotEvaluateArguments
SchemeSymbol>>apply: listOfArguments withEnv: anEnvironment | cond then else |cond := listOfArguments car.then := listOfArguments cdr car.
listOfArguments cdr cdrifNotNil: [else := listOfArguments cdr cdr car].
cond := cond eval: anEnvironment.cond isTrue
ifTrue: [^ then eval: anEnvironment].else notNil
ifTrue: [^ else eval: anEnvironment].^ Scheme undefined
41
![Page 42: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/42.jpg)
Alexandre Bergel
Dynamic and static scoping
42
![Page 43: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/43.jpg)
Alexandre Bergel
Dynamic vs static scoping
• Static scoping: variable references are bound to the environment in which those variables are defined.
• Dynamic scoping: variables are looked up dynamically, according to the current environment
43
![Page 44: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/44.jpg)
Alexandre Bergel
Static scoping: variable are statically bound
The result is 15
(let ((a 10))(let ((f (lambda (x) (+ a x))))
(let ((a 0))(f 5))))
44
![Page 45: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/45.jpg)
Alexandre Bergel
Dynamic scoping: variable are dynamically bound
The result is 5
(let ((a 10))(let ((f (lambda (x) (+ a x))))
(let ((a 0))(f 5))))
45
![Page 46: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/46.jpg)
Alexandre Bergel
Static scoping with SmallScheme
SchemePrimitiveClosure>>apply: listOfArguments withEnv: anEnvironment | env b valuesProvided argNames |valuesProvided := listOfArguments.argNames := arguments.env := SchemeEnvironment createFromEnvironment: environment....
The variable environment is bound to the environment in which the closure was created. And not to the current environment.
46
![Page 47: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/47.jpg)
Alexandre Bergel
Dynamic scoping with SmallScheme
SchemePrimitiveFunction>>apply: listOfArguments withEnv: anEnvironment | env b valuesProvided argNames |valuesProvided := listOfArguments.argNames := arguments.env := SchemeEnvironment createFromEnvironment: anEnvironment....
The variable anEnvironment is bound to the current environment. Which is not the environment in which the closure was created.
47
![Page 48: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/48.jpg)
Alexandre Bergel
Further notes
1. Symbiosis2. Tail recursion3. Grammar4. Useful links
48
![Page 49: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/49.jpg)
Alexandre Bergel
Symbiosis between Smalltalk and Scheme
Few class extensions:
Object>>asSmalltalkObject^ self
SchemeObject>>asSmalltalkObjectself subclassResponsibility
SchemeSymbol>>asSmalltalkObject^ self value
...
49
![Page 50: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/50.jpg)
Alexandre Bergel
Tail Recursion (R5RS, Section 3.5)
• But... We did not talk about tail recursion...
• “Tail-recursion allows the execution of an iterative computation in constant space, even if the iterative computation is described by a syntactically recursive procedure.”
• Easy to implement in SmallScheme
50
![Page 51: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/51.jpg)
Alexandre Bergel
Tail Recursion
Intuitively there is a stack consumption in:(define (fac n)
(if (= n 0) 1 (* n (fac (- n 1)))))
But there is no stack consumption in:(define (fac n) (fac2 n 1)) (define (fac2 n acc)
(if (= n 0)acc(fac2 (- n 1) (* acc n))))
51
![Page 52: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/52.jpg)
Alexandre Bergel
Minimal or large grammar?
• SmallScheme uses a very minimal grammar.
• The fact that we use a small grammar:– new primitives can be added without having to modify the
grammar– primitive names can be easily changed
• However we need:– evaluation of arguments need to be controlled
(evaluateArguments var in primitive)– need to have a MakeClosure primitive
52
![Page 53: 2006 Small Scheme](https://reader034.vdocuments.us/reader034/viewer/2022051313/549c6d10b47959bd318b4734/html5/thumbnails/53.jpg)
Alexandre Bergel
Useful links
SmallScheme: http://www.squeaksource.com/Scheme
Smacc (also available on SqueakMap):http://www.refactory.com/Software/SmaCC
Squeak:http://www.squeak.org
Everything you wish to know about Scheme:http://www.schemers.org
Especially the R5RS:http://www.schemers.org/Documents/Standards/R5RS/
53