【问题标题】:Scheme: Proper application of the eval function?方案:eval 函数的正确应用?
【发布时间】:2011-04-26 08:33:25
【问题描述】:

在工作中,我在尝试使用 Scheme 实现配置脚本时遇到了一个基本问题。为了避免发明一种人为的和受限制的语言,脚本应该包含实际的代码。稍后将评估此代码。要使配置按需要工作,它必须有权访问某些变量。这些变量仅在评估的上下文中是已知的。因此必须在当前环境中评估配置脚本。这是我所说的一个原始示例:

(let ((a #t))
  (wr "a is ..."
    (eval '(if a "true" "false"))))

运行此代码时,我总是会收到一条错误消息,告诉我变量“a”未知。那么问题来了:你知道如何评估当前环境中的冻结代码吗?

P.S.:我使用的是 bigloo 编译器。

///////////////////////////////////// 编辑: //////////////////////////////////////////////// //////

当使用 Chris 建议的方法时,我遇到了另一个有趣的问题,即 case 关键字的使用。以下两个示例都使用相同的案例结构,应该触发“是!”的输出。线。不幸的是,它们的行为不同。

通常 -> 输出是“是!”正如预期的那样:

  (define testit "test")
  (case testit
    (("test")
     (begin (newline) (write "yes!") (newline)))
    (else
      (begin (newline) (write "no!") (newline)))))

使用 eval -> 输出令人惊讶的是“否”:

  (define env (null-environment 5))
  (eval '(define testit "test") env)
  (eval '(case testit
           (("test")
            (begin (newline) (write "yes!") (newline)))
           (else
            (begin (newline) (write "no!") (newline))))) 

这有意义吗?

【问题讨论】:

  • 重新编辑:不要在 case 匹配子句中使用字符串。我知道一些/许多方案实现在这两种情况下都输出“否”。只有符号、数字、字符、布尔值和空列表 (()) 可以可靠地写入 case 的匹配项。有关详细信息,请参阅stackoverflow.com/questions/5768696/…

标签: scheme eval expression-evaluation bigloo


【解决方案1】:

eval 无法访问词法变量,例如使用let 定义的变量。

相反,您必须创建一个环境,并使用您想要提供的变量填充它。例如:

(define env (null-environment 5))
(eval '(define a #t) env)
(wr "a is ..."
    (eval '(if a "true" "false") env))

【讨论】:

  • 嘿,这确实有效,谢谢!我很好奇是否有更短或更直接的方法来定义变量 a 内部 env,也许是省略了“'(define..”表达式的评估 - 比如:(定义一个#t env)。我是还想知道评估这种 eval 结构需要多长时间。
  • 通过 R5RS 报告(和 R7RS 报告),(null-environment 5) 返回的环境可能是不可变的。所以建议的解决方案是不可移植的。
【解决方案2】:

要回答您的编辑,您没有将 env 作为参数传递给最后一个 eval。如果未给出该参数,则 testit 在 eval 创建的环境中不存在。

这可能是一个错字,但如果不是,那是你的问题。

【讨论】:

    猜你喜欢
    • 2013-03-20
    • 2022-12-19
    • 1970-01-01
    • 2013-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-06
    • 1970-01-01
    相关资源
    最近更新 更多