<< Previous exercise (4.13) | Index | Next exercise (4.15) >>


 ;; Parse error: Spurious closing paren found
Eva's map can work, because he implemented it. But when installing map in the eval as a primitive procedure, there is something wrong. for example: when eval expression '(map + (1 2) (3 4)), primitive procedure + is interpreted as '(application + env), so the expression is (apply map (list 'application + env) (list 1 2) (list 3 4))), it doesn't work.


I get the following error with Louis's approach:

    application: not a procedure;
     expected a procedure that can be applied to arguments
      given: #0=(mcons 'procedure (mcons (mcons 'x '()) (mcons (mcons (mcons
      '* (mcons 'x (mcons 'x (mcons 'x '())))) '()) (mcons (mcons (mcons
      '*frame* (mcons (mcons 'cube #0#) (mcons (mcons 'false #f) (mcons
      (mcons 'true #t) (mcons (mcons 'map #<procedure:mm...

I believe the problem is that Louis is 'crossing the streams'.  He is
passing one of 'our' procedures to a primitive procedure.

We have a procedure, cube, that is designed to be applied in the
implementation that we are constructing.  But here we are passing cube (i.e.
the procedure object referenced by the symbol 'cube) to the underlying map. 
So it will be the underlying implementation (e.g. Racket, Guile, Chicken,
...) that will apply map and, in turn, attempt to apply our cube procedure. 
This cannot work if our implementation of procedures, environments, etcetera
is different from the ones used by the underlying implementation.

(If key parts of the underlying implementation were identical to our
implementation I can imagine that it might work, but clearly we should never
rely on that.)


The procedures of metacircular evaluator(which are represented as lists consisting of a function and an environment) are not same as the procedures of scheme, so we need meta-apply(the apply of metacircular) to tackle that problem.

 (define meta-map 
   (lambda (f l) 
     (if (null? l) 
         (cons (meta-apply f `(,(car l))) (meta-map f (cdr l)))))) 


 (define primitive-procedures 
   (list (list 'car car) 
         (list 'cdr cdr) 
         (list 'cons cons) 
         (list 'null? null?) 
         (list 'map map))) 
 ;;; test 
 (map car '((1 a) (2 b) (3 c))) 
 ;;; M-Eval input: 
 ;;; M-Eval value: 
 (primitive #[compiled-procedure 12 (list #x1) #x1a #x10305319a]) 
 ;;; M-Eval input: 
 (map car '((1 a) (2 b) (3 c))) 
 ;The object (primitive #[compiled-procedure 12 ("list" #x1) #x1a #x10305319a]) is not applicable. 

Error message above said (primitive car) is not applicable. The point is that within the Scheme's implementation of map, car will be applied to the list, but the car is interpreted in the form ('primitive car) in our evaluator which is not recognized in Scheme's evaluator.


The point here is, by the definition of <eval>, evaluation of <map> will lead to eval of the first operand, <+>. Interpreter does it by searching the initial env which we setup at very first, and find that <+> is bind with the list ('primitive +). And since map is primitive in the implemented lisp, procedure <apply> will pass the whole list to original "map" as the first operand, but it is a procedure which implemented in our lisp, also not a legal form that can be recognized by underlying lisp system.