使用eval,R5RS从列表中评估我自己的函数

问题描述 投票:0回答:1

我遇到了这个问题

例如我有

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

我需要从给定列表中评估表达式。 (我正在编写一个模拟器,我在列表中得到一系列命令作为参数)

我已经读过R5RS标准需要包含在函数eval中作为第二个arg(scheme-report-environment 5),但我仍然遇到这个问题。

这适用(带标准功能):

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

但这不是:

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

它说:

../../../../../../usr/share/racket/collects/racket/private/kw.rkt:923:25:mypow:undefined;无法引用未定义的标识符

尽管在提示返回时简单地调用了mypow:

#<procedure:mypow>

请问有什么建议吗? (顺便说一句我需要使用R5RS)

scheme lisp r5rs
1个回答
1
投票

(scheme-report-environment 5)返回R5RS Scheme标准中定义的所有绑定,而不是任何用户定义的绑定。这是设计的。使用它作为eval的第二个参数,你永远无法做你想做的事。

该报告提到(interaction-environment)是可选的。因此,您无法保证实现具有它,但它将具有来自(scheme-report-environment 5)的所有绑定

为了完整性,有(null-environment 5)只有语法绑定。例如。 (eval '(lambda (v) "constan) (null-environment 5))工作,但(eval '(lambda (v) (+ 5 v)) (null-environment 5))将不会因为+不在最终的程序关闭。

完成任务的其他方法

通常你可以在不使用eval的情况下离开。应该几乎不惜一切代价避免使用eval。在过去的16年里,我曾两次在生产代码中故意使用eval

通过使用thunk而不是数据:

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

(todo) ; ==> result from mypow

现在想象一下,你有一个你想做的操作列表:

(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
© www.soinside.com 2019 - 2024. All rights reserved.