Problem 5 (200pts): define@1

The define special form (spec) in Scheme can be used either to assign a name to the value of a given expression or to create a procedure and bind it to a name:

scm> (define a (+ 2 3))  ; Binds the name a to the value of (+ 2 3)
a
scm> (define (foo x) x)  ; Creates a procedure and binds it to the name foo
foo

The type of the first operand tells us what is being defined:

  • If it is a symbol, e.g. a, then the expression is defining a name
  • If it is a list, e.g. (foo x), then the expression is defining a procedure.

The do_define_form function in scheme_forms.py evaluates (define ...) expressions. There are two missing parts in this function. For this problem, implement just the first part, which evaluates the second operand to obtain a value and binds the first operand, a symbol, to that value. Then, do_define_form returns the symbol that was bound.

Use Ok to unlock and test your code:

python ok -q 04 -u
python ok -q 04

You should now be able to give names to values and evaluate the resulting symbols.

scm> (define x 15)
x
scm> (define y (* 2 x))
y
scm> y
30
scm> (+ y (* y 2) 1)
91
scm> (define x 20)
x
scm> x
20

Consider the following test:

(define x 0)
; expect x
((define x (+ x 1)) 2)
; expect Error
x
; expect 1

Here, an Error is raised because the operator does not evaluate to a procedure. However, if the operator is evaluated multiple times before raising an error, x will be bound to 2 instead of 1, causing the test to fail. Therefore, if your interpreter fails this test, you'll want to make sure you only evaluate the operator once in scheme_eval.