【问题标题】:Scheme sequencing方案排序
【发布时间】:2013-05-15 23:27:03
【问题描述】:

我是 Scheme 的新手,我正在尝试通过阅读 Structure and Interpretation of Computer Programs 来熟悉该语言。我对排序有点困惑。

首先,我知道begin 关键字是为了允许排序而引入的,这样可以更轻松地对可变结构进行操作。我不明白的是,有时他们使用如下排序(受 SCIP 第 268 页上的示例启发):

(define (stuff-0)
   (+ 1 2)
   (+ 1 3)
   'ok)

同样可以使用begin

(define (stuff-1)
  (begin
    (+ 1 2)
    (+ 1 3)
    'ok))

这两者之间是否存在语义差异,或者第一个只是第二个的语法糖?

其次,除了实际重要性之外,理论上我们是否需要begin 构造?我想对于我们需要的每个序列,我们可以编写实现该序列的级联程序。这当然是不切实际的,但我只对没有 begin 构造的语言的表现力感兴趣。

【问题讨论】:

    标签: scheme syntactic-sugar sequencing


    【解决方案1】:

    很简单:在一个过程中,总是有一个隐式 begin。所以这个:

    (define (f x)
      (begin
        <expression 1>
        <expression 2>
        <returned value>))
    

    ... 完全等价于这个:

    (define (f x)
      <expression 1>
      <expression 2>
      <returned value>)
    

    不,没有任何语义差异,上面的第二种形式只是第一种形式的语法糖。 begin 形式是必要的,因为必须有一种方法可以按指定的顺序执行一系列表达式只是为了它们的效果。请记住:在begin 中(或者就此而言,在一个过程中 - 它是相同的)所有表达式都按照它们出现的顺序执行,它们的结果值基本上被忽略了,最后只返回最后一个表达式的值.

    【讨论】:

    • 您能否详细说明您所说的begin 是必要的部分?你能给我一个例子,说明使用begin 绝对是唯一的方法。我的印象是,由于 Scheme 在主体之前评估过程的参数,我们可以通过级联过程来模拟排序。
    • 例如:您将如何为此级联程序? (define x 10) (define (f) (set! x (add1 x)) x) (f) 请注意 begin 隐含在 f 过程中,并且过程中的第一行会产生效果,而不是值
    • 首先,您必须定义cascade 来接收可变数量的参数,因为begin 可以有任意数量的表达式。其次,它不起作用,因为过程参数的求值顺序是未定义的 - 并且begin 保证其表达式的求值顺序
    • 您的第一句话:我知道这一点,这就是begin 非常有用的原因。没有它,您总是需要为特定问题编写特定的级联,但我目前将其放在一边。对于您的第二句话,Racket 似乎从右到右评估参数link
    • 第二句话:你不能指望它。它取决于实现。
    【解决方案2】:

    每个 define special from 都包含一个隐含的 begin 子句。

    对于新手来说,第二个例子更清楚,但对于有经验的人来说,这只是噪音。

    您经常需要 begin 构造的一个地方是 if 语句的 then 或 else 子句。您还需要在匿名函数中使用它。

    【讨论】:

      【解决方案3】:

      不需要显式的begin。如果您需要对某些内容进行排序,但没有begin,那么您可以这样做:

      ((lambda () <body1> <body2> ...))
      

      实际上,以上内容正是您将begin 实现为宏的方式。以下是 R7RS 的语法定义:

       (define-syntax begin
          (syntax-rules ()
            ((begin exp ...)
             ((lambda () exp ...)))))
      

      因此,您的陈述“我了解引入 begin 关键字以允许排序”并不真正正确。 begin 作为lambda 的基本排序结构的语法糖引入。

      【讨论】:

      • 但这只是因为begin被隐式添加为过程主体的一部分,所以你需要一个begin才能工作。
      • 一个 lambda 的主体产生一个序列;因为它确实可以使用lambda 来定义beginlambda 更为基础。
      • 就我对 lambda 演算的了解而言,lambda 表达式中没有排序。在 Scheme 中,有排序。我很好奇是否可以通过仅应用函数来模拟排序,同时考虑到 Scheme 严格的按值调用评估策略。
      • 如果lambda 只允许一种body 形式(而begin 不存在),那么您可以使用重复的函数应用来实现排序。例如序列(display 'foo) (display 'bar)变成((lambda x (display 'bar)) (display 'foo))
      猜你喜欢
      • 2014-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-21
      • 2011-05-02
      • 2015-03-18
      • 2019-03-25
      • 2017-06-24
      相关资源
      最近更新 更多