1

我正在尝试编写一个函数来检查某些输入是否是语法检查器的引用。

我有以下代码:

(define is-quote-expression?
  (lambda (v)
    (equal? (car v) 'quote)
    (is-quotation? (cdr v)))))

(define is-quotation?
  (lambda (v)
    (or (number? v)
        (boolean? v)
        (char? v)
        (string? v)
        (symbol? v)
        (null? v)
        (and (pair? v)
             (is-quotation? (car v))
             (is-quotation? (cdr v)))))

当我尝试评估时,我得到以下信息:

 (is-quote-expression? '1)
 #f

 (is-quote-expression? (cons 'quote 1))
 #t

我想我的 TA 告诉我,Scheme 环境用“'quote”替换了所有“'”,但是,情况似乎并非如此。我们正在运行 Petite Chez 计划。

我没看到什么?

提前致谢。

4

3 回答 3

2

您的代码存在一些问题,对于初学者来说,其中的(lambda (pair? v)部分is-quote-expression?几乎可以肯定是一个错误(您正在定义一个带有两个参数的 lambdapair?v)。

另外,我相信您打算仅在不是一对时才打电话is-quotation?,因此再次询问 if in是没有意义的。谁说只有当它的和都是引用时,一对才是引用?is-quote-expression?v (pair? v)is-quotation?carcdr

在这里,我相信这就是您的意图:

(define is-quote-expression?
  (lambda (v)
    (if (pair? v)
        (equal? (car v) 'quote)
        (is-quotation? v))))

(define is-quotation?
  (lambda (v)
    (or (number? v)
        (boolean? v)
        (char? v)
        (string? v)
        (symbol? v)
        (null? v))))
于 2012-05-06T17:56:54.460 回答
1

不过,我同意 Óscar 的帖子,它is-quote-expression?接受一个列表而不是一对,并返回它是否是一个引用。

(define is-quote-expression?
  (lambda (v)
    (and (proper-list-of-given-length? v 2)
         (equal? (car v) 'quote)
         (is-quotation? (cadr v)))))

此外,您最初的问题对报价的实际作用有些困惑。这才是真正应该发生的:

> (is-quote-expression? '1)
#f
> (is-quote-expression? (cons 'quote 1))
#f
> (is-quote-expression? (quote 42))
#f
> (is-quote-expression? (quote (quote 42)))
#t

请注意内置的报价过程如何简单地返回它传递的内容。在(quote 42)它只是返回的情况下42。但是(quote (quote 42))返回(quote 42),这是您希望传递给 is-quote-expression? 的内容。

于 2012-05-06T18:18:20.320 回答
1

的行为quoteR6RS附录A.3中指定。对于'1,相关规则是6sqv

(存储 ( sf 1 ...) S 1 [ 'sqv 1 ]) → (存储 ( sf 1 ...) S 1 [ sqv 1 ])

是时候打破这个了。

“S → T”表示法定义了评估术语的一个步骤,其中“S”评估为“T”。

由于store非终结符在左侧和右侧看起来相同,因此您无需了解它们即可了解如何评估。如果您需要某些东西,请将其视为“存储环境”,并将其视为名称和值对;表示标识符与 value 相关联,并且在评估 term 时与之相关联。sf1 '1storesfn(store ((x 1) (y 2)) S)x1y2S

如果你不熟悉这个符号,它指的是一个有一个“洞”(一个里面有 a 的词)填充的术语。有两个相关的语法元素:带有孔的术语 ( ) 和带有由值填充的孔的术语 ( )。孔有点(但只有一点)像未命名的变量。一个重要的区别是一个术语只允许一个洞。孔可能最好用例子来解释。以下是:S[e][]eS[]S[e]S[]

  • (+ [] 1 2)
  • (list [] 'a "foo")
  • (cond ((= x 0) [])
          ((> x 0) 1)
          (else   -1))
    

请注意,只有在子项在语法上有效时才会出现空洞;[] 2)不是一个有洞的术语。S[0]将是一个0代入洞中的术语:

  • (+ 0 1 2)
  • (list 0 'a "foo")
  • (cond ((= x 0) 0)  
          ((> x 0) 1)
          (else   -1))
    

当为孔指定值时,该术语S[]也称为“上下文”。这来自 term-with-holes 的主要用途之一:匹配包含给定值的任何术语。是任何包含有效子术语的术语,因此出现的上下文也是如此。简而言之,它是包含引用的任何术语的替代。S[e]eS[]eS1['sqv1]

  • (+ 'foo 1 2)
  • (list 'bar 'a "foo")
  • (cond ((= x 0) 'baz)
          ((> x 0) 1)
          (else   -1))
    

请注意,第二个术语为引用术语提供了两种不同的上下文:(list [] 'a "foo"), (list 'bar [] "foo"). 这表明您不应该过多地将漏洞视为未命名的变量。

如果您想知道为什么使用上下文术语和孔,它们是递归定义的替代方案。如果没有上下文,→ 必须在术语结构上递归定义(Scheme 的语法定义了结构)。lambda 演算中的替换是结构递归的一个示例,您可能在 Scheme 中定义的任何树处理函数也是如此(尽管 Scheme 语法与用于定义 → 和 lambda 演算替换的语法完全不同)。

(define (tree-depth tree)
  (if (pair? tree) 
          (max (tree-depth (car tree)) 
               (tree-depth (cdr tree)))
          1
) )

接下来,让我们检查一下 的含义sqv,它是“自引用值”的缩写。这是附录 A.2 中给出的Scheme 语法的非终结符。

平方::= n | #t | #f
 n    ::= [数字]

sqv只是一个数字或布尔值。

总之,6sqv评估规则意味着引用的数字或布尔值评估为数字或布尔值;报价被简单地丢弃。

这对您的作业意味着您无法区分普通函数1'1普通函数之间的区别,因为在调用函数之前会评估子项。你需要一个宏。

为什么要经历这一切只是为了说“'1评估为1”?首先,回答“为什么”比回答“什么”更重要。此外,它有望帮助您超越问题,学习一点如何阅读 Scheme 的形式语义,让您体验计算理论概念并引发更多问题。

于 2012-05-06T20:07:28.763 回答