【问题标题】:What is ' (apostrophe) in Lisp / Scheme?Lisp / Scheme中的'(撇号)是什么?
【发布时间】:2010-12-05 01:54:02
【问题描述】:

我在自学 Scheme 的第 1 天第 1 小时。不用说,我什么都不懂。所以我正在阅读 The Little Schemer 并使用这个东西:

http://sisc-scheme.org/sisc-online.php

作为翻译。

例如,我需要使用'

(atom? 'turkey)

以避免“未定义的变量”错误。根据这本书,' 是 Common Lisp 的东西。

我有两个问题:

  1. 我上面提到的那个解释器好不好?你能推荐另一个吗?我需要一个能与 The Little Schemer 配合得很好的人。

  2. 什么是'

【问题讨论】:

  • “我需要 ' 来避免 '未定义变量' 错误”——如果你这样写的话,你的方法存在严重缺陷,尽管我不能说是什么。建议您仔细阅读旧的 R4RS 标准(除了附录;它比 R5RS 或 R6RS 更易于访问)三遍。
  • 这是一个老问题,但我建议您删除问题的第一部分,因为在这里寻求建议是题外话。

标签: scheme lisp quote the-little-schemer


【解决方案1】:

'foo 表单是输入特殊表单的一种更快的方式

(quote foo)

也就是说,“不要评估名称foo 将其替换为它的值;我真正的意思是名称foo 本身”。

我认为 SISC 非常适合探索 TLS 中的练习。

【讨论】:

  • 引用和函数之间没有功能上的区别吗?即:加热/冷却规则。当 foo 被传递给一个函数时,它首先被评估,而引用代码的目的是阻止它的评估。
【解决方案2】:

(quote ...) 的缩写,' 将代码转换为数据。

stuff 是一个符号,这意味着它可以是变量名或函数名等。
'stuff 为您提供符号“东西”本身。

(dostuff "on" those 4 :parameters) 评估时,将运行带有四个参数的函数dostuff:字符串、变量内容、数字和关键字。
'(dostuff "on" those 4 :parameters) 在评估时将返回上面的代码,在评估时将依次使用这四个参数运行函数dostuff..

例如: 运行'''somecode,返回''somecode。运行''somecode,返回'somecode。运行'somecode,它返回somecode。运行somecode,然后......好吧......somecode 将运行。

你可以说'有点像(eval..)的反面。

(eval (eval (eval '''(print "hello")))) 将打印“Hello”。
(eval (eval (eval ''''(print "hello"))) - 注意' 然后eval - 不会打印任何内容,但它会返回代码(print "hello") 本身!!

除了 lispers 倾向于将返回的代码(有时甚至是手写代码)称为“列表”而不是“代码”,原因会随着您深入挖掘而变得明显。祝你好运:)

【讨论】:

  • 不,在方案(与普通的 lisp 相对)中,东西是一个标识符。它通过引用它成为一个符号,就像在'stuff中一样。一个小点,但很高兴把它做好。在 scheme 中,标识符不需要像在 common lisp 中那样实现为符号。有关最新的方案标准,请参阅 r7rs 的 §2.1 和 §6.5。
  • @ChrisVine 感谢您提供的信息,我相信当我尝试在 haskell 中实施方案时,我会发现它很有用,希望在不久的将来 :)
【解决方案3】:

如果您正在为 scheme 寻找最佳 IDE,请选择 Dr Racket。但是当开始Dr Racket 第一行应该是#lang scheme,因为Dr Racket 有很多语言,我们已经明确提到我们将使用哪种语言。

当我们想传递参数本身而不是传递参数的值时,我们使用引号。它主要与使用 C 编程语言中不可用的列表、对和原子期间传递的过程有关(大多数人开始使用 C 编程进行编程,因此我们感到困惑)这是 Scheme 编程语言中的代码,它是 lisp 的一种方言我猜你可以理解这段代码。

(define atom?              ; defining a procedure atom?
(lambda (x)              ; which as one argument x
(and (not (null? x)) (not(pair? x) )))) ; checks if the argument is atom or not
(atom? '(a b c)) ; since it is a list it is false #f

最后一行 (atom?'abc) 将 abc 按原样传递给程序以检查 abc 是否为原子,但是当您通过 (atom?abc) 时,它会检查 abc 的值并通过对它的价值。因为,我们没有为它提供任何价值

【讨论】:

    【解决方案4】:

    你需要了解Scheme的基本求值规则。

    第一

    (atom? 'turkey)
    

    该列表是一个函数应用程序,因此atom? 被评估为一个函数。 'turkey(quote turkey) 的简写符号。评估(quote turkey) 得到符号turkey

    所以接下来将函数应用于符号turkey 并计算返回值。

    第二

    (atom? turkey)
    

    再次,我们有一个函数应用程序,atom? 被评估为一个函数。这次turkey 是一个变量。评估 turkey 会给出绑定到它的值 - 无论它是什么。

    那么函数就会应用到变量turkey的值上。

    总结

    turkey 是一个变量,它被评估为它的值。 'turkey(quote turkey),它被评估为符号 turkey

    Scheme 重用 s 表达式并使用 s 表达式构建其程序。这导致了一个问题,有时turkey 应该是一个变量,有时它应该是符号。这对初学者来说有点混乱。过一段时间你就会看到它背后的力量。

    【讨论】:

    • 这在某种程度上不如 C 指针有意义。就像,我知道这是一种间接形式,即foo5'foofoo,但是......为什么这是必要的?如果你评估'foo,你会得到foo,如果你评估foo,你会得到5,如果你评估5......你仍然应该得到5,那为什么它是非法的?我看不出这会导致错误的原因。常量5 的值将是5,无论它后面是否有变量。例如,为什么我必须在引用函数时键入#'bar,而在大多数其他函数式语言中,函数是一等的?
    • 我也了解函数返回函数和lambda函数,发现它们非常有用。 IE。像let x = () => thing(), a = x(), b = x(); 这样的东西来保证在传递共享语义下的唯一对象。但这:(defvar newlist (map 'list #'myfun oldlist)) 只是令人困惑。为什么不让list 成为字符串?为什么一定要引用myfun?如果是因为myfun 不是变量,那么为什么函数不是一等的呢?为什么我必须引用(1 2 3 4 5) 而不是oldlist(1 2 3 4 5) 是不是不管是token还是value形式的list字面量?
    • 我知道'(1 2 3 4 5) 等同于oldlist,但为什么有必要这样做?这不像(1 2 3 4 5) 的值在被评估后就消失了。然而 lisp 还是选择对它挑剔。 (defvar list (1 2 3 4 5)) 无效但 (defvar list '(1 2 3 4 5)) 有效怎么办?无论哪种方式,lisp 都看不到 (function value value) 吗?还是 lisp 期望 (a b c) 形式的所有表达式都是对函数 a 的调用,从而使 (1 2 3 4 5) 本身作为表达式无效?这完全不直观。
    • @BradenBest:如果您对 Lisp 的使用有疑问,请提出问题。评论不是提问的好地方。
    【解决方案5】:

    单引号字符是 (quote foo) 的简写方式,其中 quote 是只返回 foo 而不对其进行评估的形式。

    在 Scheme 或任何 Lisp 中真正要记住的一件事是默认情况下会评估所有内容。因此,在您不想评估的情况下,您需要一种方法来解决这个问题。

    引用某事就是这样做的,而单引号只是需要更少的输入并导致更少的冗长代码。

    【讨论】:

    • Emm,并非所有内容都默认进行评估。在(if t (one) (two)) 中,永远不会评估(二)。默认情况下,仅在顶层或函数的参数中评估所有内容。如果它在其他任何地方,它可能会或可能不会被评估,具体取决于该特定其他任何地方的确切位置。
    【解决方案6】:
    1. 我建议您转移到更好的环境,例如 PLT Scheme,它有一个 IDE、调试器和许多库。随着您前进并开始编写更大的程序,您将需要它们。

    2. 单引号字符是“引号”表达式的语法糖,因此 'turkey 与 (quote turkey) 相同。基本上,“报价”所做的是关闭方案评估器。换句话说,“quote”逐字返回表达式。如果没有“quote”,Scheme 将尝试在当前环境中评估“turkey”。这不是 Common Lisp 的事情,而是 Lisp 的事情。 Common Lisp 和 Scheme 是 Lisp 的两种方言。所有 Lisp 教程/书籍中都解释了“引用”的用法。另请参阅this question 的答案。

    【讨论】:

      【解决方案7】:

      SISC 不错,但更轻量级的在线 Scheme 执行器是 http://codepad.org。它实际上不是 REPL,因为它不是交互式的,但它非常接近。您提交的代码在服务器 端执行,而不是使用浏览器小程序。并且您可以通过短 URL 共享您正在运行的代码。

      键盘上的about 页面显示它使用“MzScheme v372 [cgc]”。

      我使用键盘进行各种快速的 sn-p 测试(包括测试代码示例以获得 SO 答案!)。

      对于引号语法,可以使用如下代码看出区别:

      (let ((x 5))
        (display x) (newline)
        (display 'x) (newline))
      

      这显示:

      5 X

      在第一种情况下,x 被评估并传递给display,它打印 5。在第二种情况下,符号x(这与一个字符串)被传递给display,它会打印符号的名称。

      【讨论】:

        猜你喜欢
        • 2016-02-20
        • 1970-01-01
        • 2010-11-30
        • 1970-01-01
        • 1970-01-01
        • 2015-07-20
        • 2016-08-25
        • 2011-01-24
        • 2023-04-07
        相关资源
        最近更新 更多