【问题标题】:Implementing own sequencing in racket在球拍中实现自己的排序
【发布时间】:2013-10-17 05:58:26
【问题描述】:

我需要实现一个函数,它接受一个或多个表达式并按顺序执行这些表达式。

这是我目前所拥有的:

(define (foo exp0 exp1 ) exp0 exp1)

【问题讨论】:

  • 你能重现教科书中出现的问题吗?你描述的不是一个函数,而是一个macto。到目前为止,您所拥有的是一个函数,它接受两个 值 作为参数,然后返回其中的第二个。
  • 好的,所以它是在谈论实现一个操作符/操作,而不是一个函数。我只是想确定这一点。我看到这是您在 StackOverflow 上的第一个问题。您应该能够编辑您的问题,并且添加这种澄清是说明为什么存在哪些功能的一个很好的例子。我现在将对其进行编辑,但将来,请随时更新您的问题并进行澄清;它更容易找到,而且不是每个人都会阅读 cmets。
  • 你为什么删除我编辑的问题(你之前在评论中发布的)?它增加了必要的澄清。例如,如前所述,这是不可能的;你不能定义一个 function 来做到这一点。然而,引用的问题清楚地表明,您正在寻找一个可以用define-syntax-rule 定义的运算符,正如uselpa's answer 所解释的那样。

标签: lambda scheme racket sequencing


【解决方案1】:

假设你有以下表达式

(sequence form1 form2 form3)

并且您希望按顺序评估表单,然后您不能将它们传递给 Josuha 解释的函数。最简单的转换是将上述更改为

((lambda () form1 form2 form3))

因为 lambda 表达式中的表单是按顺序执行的,结果是最后一个表单的值。由于这种转换必须在源代码级别完成,因此您必须使用宏,例如:

(define-syntax-rule (sequence form1 form2 ...)
  ((lambda () form1 form2 ...)))

这将转换一个表达式,例如

(sequence (display "a") (display "b") (display "c"))

进入

((lambda () (display "a") (display "b") (display "c")))

它将按顺序执行表单。

【讨论】:

  • 这不起作用,因为表单的评估顺序未定义。例如。 ikarus 会首先显示“c”,根据规范可以。
  • @Sylwester 如果表单是随机评估的,您如何编写程序?
  • @Sylwester 我同意 uselpa。我在回答中有点过度设计了这个问题,因为我正在考虑按从左到右的顺序评估 function arguments。但是,函数的主体必须按从上到下的顺序进行评估。否则,像(lambda (x) (display x) (set! x 10)) 这样的东西可以或者打印10 或x 的原始值。
  • 我的错误。我虽然 display 形式是参数,但由于它在 lambda 主体中,它具有明确的开始和最有效的方式。
【解决方案2】:

方案没有指定任何特定的参数评估顺序。这意味着如果你有一个display-and-return 函数:

(define (display-and-return x)
  (display x)
  x)

然后你调用,例如,

(list (display-and-return 1) (display-and-return 2))

您一定会得到(1 2) 的结果,但您可以看到由显示生成的输出为12 或21。但是,Scheme 确实指定函数的参数将在函数体被计算之前被计算。因此,您可以通过将两个表达式作为函数的参数来对它们进行排序:

((lambda (val1)
   ((lambda (val2)
      (list val1 val2))
    (display-and-return 2)))
 (display-and-return 1))

一般来说,您可以使用这样的转换将(seq exp1 exp2 ... expm expn) 变成

((lambda (val1)
   ((lambda (val2)
      ...
        ((lambda (valm)
           expn)        ; or ((lambda (valn) valn) expn)
         expm) ... )
    exp2))
 exp1)

您可以使用define-syntax-rule 定义这种转换。

【讨论】:

  • @user1025948 uselpa's answer 比这个好。因为我首先指出函数参数可以按任何顺序求值,所以我继续展示如何使函数的参数以从左到右的方式求值(所以最里面的主体将是对带有变量的函数的调用)。不过,这不仅仅是测序所必需的。正如 uselpa 指出的那样,您可以将表单作为 lambda 表达式的主体。
  • 这适用于其中一种 HtDP 语言,它只需要 lambda 正文中的一种形式。
  • @Sylwester 实际上,这将是一种实现 lambda 函数的方式,该函数可以在其主体中接受多种形式(只需在未出现在主体中的 lambda 参数列表中使用一次性变量)。 (事实上​​,这就是我不久前实现 λ-演算解释器时采用的方法……)
【解决方案3】:

您需要接受“一个或多个表达式”然后评估它们并返回最后一个的东西。这可以定义为:

(define (sequence exp1 . exps)
  (car (reverse (cons exp1 exps))))       ; (if (null? exps) exp1 ...)

然后你会调用它:

> (sequence (+ 1 2) (* 1 2) 17)
17

不需要使用定义语法的东西,因为标准函数应用程序将“按顺序执行这些表达式”

如果您需要保证从左到右的顺序,那么您需要:

(define-syntax sequence
  (syntax-rules ()
    ((sequence exp exps ...)
     (begin exp expos ...))))

但是如果你不能使用begin,但是可以使用lambda,那么:

(define-syntax sequence
  (syntax-rules ()
    ((sequence exp exps ...)
     ((lambda () exp exps ...)))))

【讨论】:

    猜你喜欢
    • 2022-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-20
    • 1970-01-01
    相关资源
    最近更新 更多