1
votes

I am having problems with this

e.g. i have

(define (mypow x) (* x x))

and I need to eval expressions from given list. (I am writing a simulator and I get a sequence of commands in a list as an argument)

I have already read that R5RS standard needs to include in function eval as second arg (scheme-report-environment 5), but still I am having issues with this.

This works (with standard function):

(eval '(sqrt 5) (scheme-report-environment 5))

but this does not:

(eval '(mypow 5) (scheme-report-environment 5))

It says:

../../../../../../usr/share/racket/collects/racket/private/kw.rkt:923:25: mypow: undefined; cannot reference undefined identifier

Eventhough simply called mypow in prompt returns:

#<procedure:mypow>

Any advice, please? (btw I need to use R5RS)

1

1 Answers

2
votes

(scheme-report-environment 5) returns all the bindings that are defined in the R5RS Scheme standard and not any of the user defined ones. This is by design. You will never be able to do what you want using this as the second parameter to eval.

The report mentions (interaction-environment) which is optional. Thus you have no guarantee the implementation has it, but it will have all the bindings from (scheme-report-environment 5)

For completeness there is (null-environment 5) which only has the bindings for the syntax. eg. (eval '(lambda (v) "constan) (null-environment 5)) works, but (eval '(lambda (v) (+ 5 v)) (null-environment 5)) won't since + is not in the resulting procedures closure.

Other ways to get things done

Usually you could get away without using eval alltogether. eval should be avoided at almost all costs. The last 16 years I've used eval deliberately in production code twice.

By using a thunk instead of data:

(define todo 
  (lambda () ; a thunk is just a procedure that takes no arguments
    (mypow 5))

(todo) ; ==> result from mypow

Now imagine you have a list of operations you'd like done instead:

(define ops
  `((inc . ,(lambda (v) (+ v 1)))      ; notice I'm unquoting. 
    (dec . ,(lambda (v) (- v 1)))      ; eg. need the result of the
    (square . ,(lambda (v) (* v v))))) ; evaluation

(define todo '(inc square dec))
(define with 5)

;; not standard, but often present as either fold or foldl
;; if not fetch from SRFI-1 https://srfi.schemers.org/srfi-1/srfi-1.html
(fold (lambda (e a)
         ((cdr (assq e ops)) a))
       with
       todo)
; ==> 35 ((5+1)^2)-1