1
votes

I am trying an example on Chapter 4 of SICP (part of writing the LISP interpreter)

(define (definition-value exp)
    (if (symbol? (cadr exp))
        (caddr exp)
        (make-lambda 
                    (cdadr exp) ; formal parameters
                    (cddr exp)  ; body
        )              
    )
) 


(define (make-lambda parameters body)
    (cons 'lambda (cons parameters body))
)

I Tested it, definition-value on '(define (double x) (+ x x))) should return a lambda function

( (definition-value '(define (double x) (+ x x))) 10)

Racket outputs

procedure application: expected procedure, given: (lambda (x) (+ x x)); arguments were: 10

Isn't "(lambda (x) (+ x x))" a procedure? Or it is a reference? If it is a reference, any way to "dereference" it?

2

2 Answers

2
votes

definition-value returns the value in the definition expression given to it as an argument:

(definition-value '(define x 42))  
=> 42

(definition-value '(define (qq x) (+ x y 42))) 
=> (make-lambda '(x) '((+ x y 42)))
=> '(lambda (x) (+ x y 42))

You can't call the quoted list as a function, as you do: ( '(lambda (x) (+ x y 42)) 10) is invalid. It is not a function, it is just an s-expression.

definition-value is part of an interpreter. This interpreter is the way to "dereference", i.e. interpret function definitions. Different interpreters can have different ways to interpret same function definitions, giving different semantics to the resulting languages.

Evaluation of expressions must be done in context - they appear inside certain lexical scope (area in code where a variable is visible), which gives rise to environments (also, this). In the example above, y is defined in some enclosing scope in the program being interpreted. Trying to interpret that expression in REPL by calling Racket's eval, what value would y have?

0
votes

I figured the answer, if execute a Racket script in file, racket interpreter doesn't know the namespace, however, the REPL knows it. The solution is to add this line at the beginning of the file

(define ns (make-base-namespace))

Then pass ns to eval when using it

(eval <what ever code reference here> ns)

That will make my above mentioned examples work.