Scheme 方案中的控制性评价(guile)

Scheme 方案中的控制性评价(guile),scheme,eval,quote,guile,Scheme,Eval,Quote,Guile,这似乎是一个简单的问题;也许这是如此简单,很难找到一个搜索,将找到答案。在Scheme(特别是Guile实现,如果这有什么不同的话)中,我如何评估引用的内容 这就是我要做的 我基本上需要确保我定义的函数以特定的顺序计算其参数,因为计算一个参数所引起的副作用在计算其他参数时是依赖的。然而,Scheme说参数可以按任何顺序求值,所以我想通过引用参数,然后按需要的顺序手动求值来手动强制求值 “eval”似乎应该做我想做的事情,但它有两个问题: 不鼓励使用它,所以我觉得应该有更好的方法来完成我想在这里做

这似乎是一个简单的问题;也许这是如此简单,很难找到一个搜索,将找到答案。在Scheme(特别是Guile实现,如果这有什么不同的话)中,我如何评估引用的内容

这就是我要做的

我基本上需要确保我定义的函数以特定的顺序计算其参数,因为计算一个参数所引起的副作用在计算其他参数时是依赖的。然而,Scheme说参数可以按任何顺序求值,所以我想通过引用参数,然后按需要的顺序手动求值来手动强制求值

“eval”似乎应该做我想做的事情,但它有两个问题:

  • 不鼓励使用它,所以我觉得应该有更好的方法来完成我想在这里做的事情
  • 在Scheme中,eval似乎采用了第二个参数,即环境。这让我很困惑。我希望它在语句出现的相同环境中求值,那么为什么我需要第二个参数呢?这可能吗?我玩了一下eval,似乎有些实现需要不同的参数(例如,mitscheme甚至不知道什么是交互环境!!!)
  • 我还尝试过其他技巧,比如建立一个lambda:

    (list 'lambda '() '(car (b c)))
    
    但似乎必须对其进行评估才能生成一个过程。 我还尝试:

    (list lambda '() '(car (b c)))
    
    但这将返回一个“基本内置宏”,它也不起作用

    编辑: 看起来宏将用于控制计算顺序:
    (defmacro test1(a b)`(begin,b,a))

    如果需要评估列表结构(带有引号的嵌套列表,表示方案程序文本),则应使用
    eval
    。Scheme要求将环境作为第二个参数传递,即使它是当前环境:

    (eval '(+ x y) (interaction-environment))
    
    如果您只需要按特定顺序进行计算,则可以通过使用
    begin
    let
    ,或仅使用函数体来强制执行副作用的计算顺序。它们定义了一系列评估:

    (let ((x 42))
      ; eval with effects #1
      (display x)
      ; eval with effects #2
      (display (+ x 1)))
    
    编辑:如果您需要一个参数化的代码块,可以在其中传递未计算的表达式,然后按特定顺序强制计算,则可以使用以下技术之一:

    • 宏(正如您已经提到的,只是为了完整性):

    • 延迟计算(Scheme用于延迟计算的特殊语法):

    • 正则lambda抽象及其应用

      > (define (test1 a b) (begin (b) (a)))
      > (test1 (lambda () (display 2)) (lambda () (display 3)))
      32
      

    eval
    对于改变参数的求值顺序来说是完全错误的工具。改为创建宏:

    ;; (my-fun e1 e2)
    ;; Just calls my-real-fun, but evaluates e2 before e1
    (define-syntax my-fun
      (syntax-rules ()
        [(my-fun e1 e2)
         ;; let* has guaranteed order of evaluation
         (let* ([y e2]
                [x e1])
           (my-real-fun x y))]))
    
    (define (my-real-fun x y) ....)
    

    如果必须的话,也可以使用
    defmacro

    你通过lambdas的路线是正确的。如果你有

    (define (f x y z) ...)
    
    。。。那么你可以这样称呼它:

    (f
      (lambda () a)
      (lambda () b)
      (lambda () c))
    
    这将以未计算的形式使用所有参数(
    a
    b
    c
    )调用
    f
    。在
    f
    中,您完全有权选择评估顺序。唯一的区别是,您必须显式调用
    (x)
    (y)
    (z)
    ,并在
    定义
    类语句中捕获它们的值。这样可以确保副作用只发生一次


    这里根本不需要宏。顺便说一句,不要担心在任何地方都使用大量lambda,它们非常便宜。

    如果需要可变数量的参数,宏如何工作<代码>(defmacro test1(a.b)`(begin,b,a))
    不起作用,因为b现在是一个列表。我需要以某种方式将它拼接到开头,但是各种尝试,例如
    `(begin(if(pair?,b)(test1,b)),a))
    都不起作用。此外,我不能使用
    (defmacro test1(a.b)`(begin(apply begin,b),a))
    ,因为我不能应用宏。您错过的是
    (defmacro test1(a.b)`(begin,(cons'begin b),a))
    (define (f x y z) ...)
    
    (f
      (lambda () a)
      (lambda () b)
      (lambda () c))