In this exercise, we are given the following function:-
It is noted that the order in which the exps are evaluated is the same as the order of the underlying language because we use cons to evaluate the list. We can use the let construct to evaluate the operands in the order w choose.
To evaluate the list-of-values from left to right regardless of the underlying implementation, we use the following code:-
Likewise, we can evaluate from right to left using:-
Exercise 4.2
In this exercise, Louis Reasoner whanters to reorder the cond clauses in eval code so that procedure applications clause appears before assignments’. This is a bad idea mainly because the code as it is right now would causeall calls to go into application. Let us take the example code of '(define x 3).
The given code is an assignment. However, by reordering, we first check if its an application by calling (define (application? exp) (pair? exp)). This would return true for the definition statement and execute an application which is false.
Now, Louis proposes another syntax for evaluation known as call. For example, we perform addition by using (call + 1 2). This can be handled using the new syntax:-
Exercise 4.3
In this exercise, we are tasked with rewriting eval so that the dispatch is done in a data-directed style. Based on the code from section 2, we set up an initial dispatch table as follows along with functions for tagged expressions.
Based on the above set-up, let us rewrite the eval function by replacing the tagged expressions with the data-direction:-
Exercise 4.4
In this exercise, we are tasked with implementing the functionality to evaluate and and or functions and install them to the eval function. The code can be written using make-if and following the same pattern as cond:-
Exercise 4.5
In this exercise, we need to add a way to evaulate an additional syntax for cond of type (test => recipient). To do that, we define the following tester functions:-
Next, we modify the cond clause generator to include the syntax:-
We use the lambda expression to make sure that the test is only run once in case it has side-effects.
Exercise 4.6
In this exercise, we need to rewrite let expressions as derived expressions composed of lambda expressions. This can be done using the following code:-
Now we can handle let by modifying eval as follows:-
Exercise 4.7
In this exercise, we need to write a converter for let* expression which is like let but allows for binding the variables one by one such that later bindings have access to the earlier bindings. Thus, let* can be expressed in terms of recursive let. The code to do that is as follows:-
It is sufficient to add a clause (eval (let*->nested-lets exp) env) to eval. The eval function can recursively transform the expression until the primitive value.