【问题标题】:Why does single quote in Lisp always return upper case?为什么 Lisp 中的单引号总是返回大写?
【发布时间】:2015-08-11 13:49:23
【问题描述】:

我希望能够从单引号中设置大小写,但这似乎不可能。

(format nil "The value is: ~a" 'foo)
"The value is: FOO"

(format nil "The value is: ~a" 'FOO)
"The value is: FOO"

(format nil "The value is: ~a" "Foo")
"The value is: Foo"

【问题讨论】:

    标签: format common-lisp single-quotes


    【解决方案1】:

    引用

    报价与大小写无关。 quote 阻止评估。

    引用一个符号:

    CL-USER 1 > 'foo
    FOO
    

    引用列表:

    CL-USER 2 > '(1 2 3 foo)
    (1 2 3 FOO)
    

    你可以在很多东西前面加上引号。比如前面一个字符串:

    CL-USER 3 > '"a b c"
    "a b c"
    

    由于字符串对自身进行评估,因此是否引用它们没有区别:

    CL-USER 4 > "a b c"
    "a b c"
    

    符号默认为大写:

    CL-USER 5 > 'FooBar
    FOOBAR
    
    CL-USER 6 > (symbol-name 'FooBar)
    "FOOBAR"
    

    但这与引用无关,是阅读器的一个功能

    CL-USER 7 > (read-from-string "foo")
    FOO
    3
    

    小写

    如果你想要小写的字符串,你需要将字符串转换为小写:

    CL-USER 8 > (string-downcase (symbol-name 'FooBar))
    "foobar"
    

    混合大小写的符号

    但是您可以创建具有小写名称或混合大小写的符号。你需要逃避它们:

    CL-USER 9 > '|This is a symbol With spaces and mixed case|
    |This is a symbol With spaces and mixed case|
    
    CL-USER 10 > 'F\o\oB\a\r
    |FooBar|
    

    使用FORMAT 缩小输出

    您也可以告诉FORMAT 以小写形式打印:

    CL-USER 11 > (format nil "The value is: ~(~a~)" 'foo) 
    "The value is: foo"
    

    【讨论】:

    • 感谢您的回答!很有帮助。
    • 所以代码使用'value是一个字符串是不好的?我想我在几个地方遇到了这种情况。
    • @Jiminion:你能解释一下你的问题是什么意思吗?我不确定我是否明白你在问什么。
    • 'int 是一个符号。它占用的空间更少,因为它是实习的,而字符串不一定如此。比较符号和比较指针一样快;而比较字符串在最坏的情况下涉及 O(n)。符号大多是内部的:在其他语言中使用幻数或常量的地方使用它们;通常,它们不应该被打印出来。有什么理由更喜欢字符串而不是符号?您希望获得什么?
    • 最后一部分也适用于所有数据类型。在Practical Common Lisp :: A few format recipes 中,还有另外 3 个关于外壳固定的其他变体。 (在页面上搜索“狐狸”)
    【解决方案2】:

    'foo 表示“禁止对符号 FOO 的评估,只留下符号 FOO”。 Common Lisp 默认情况下倾向于向上转换符号名称(因此表示为'foo'Foo'FOO 的符号都是同一个符号,符号名称为"FOO")。

    要确切了解您的实现将做什么,您可以通过调用(readtabe-case *readtable*) 检查当前可读表see CLHS, ch 23.1.2, effect of readtable case 的可读情况。

    一些 lisp 实现将以 :preserve 的 readtable-case 开头。

    至于是否应该使用符号或字符串,这是“取决于”的其中之一。如果您不担心 cse 保存,使用 interned 符号可以减少存储空间并加快比较速度,并且以(可能的)大小写处理的代价。但是,如果大小写很重要,那么平衡可能会更接近“使用字符串”的范围。

    【讨论】:

    • 这听起来像是预优化,但 Stack Overflow 中的许多人似乎对此不以为然。
    • 把它想象成语义胜于表现。符号是一个“值”,例如常量或enum 字段。字符串(更常见)是一种表示形式。该符号恰好具有比#xff4023b5 等程序员更容易理解的清晰表示,但它本身是一个可以快速比较的唯一值,但没有(有用的)算术值。
    【解决方案3】:

    要了解发生了什么,请参阅 Rainer Joswigs 的回答。只需添加一件事:您可以使用*print-case* 控制打印符号的大小写(没有竖线语法):

    CL-USER 1 > (let ((*print-case* :downcase))
                  (format nil "The value is: ~a" 'foo))
    "The value is: foo"
    
    CL-USER 2 > (let ((*print-case* :capitalize))
                  (format nil "The value is: ~a" 'foo))
    "The value is: Foo"
    
    CL-USER 3 > (let ((*print-case* :upcase)) ; default
                  (format nil "The value is: ~a" 'foo))
    "The value is: FOO"
    

    【讨论】:

    • 在这些调用之后,print-case 的值是否恢复到原来的值?
    • 是的,*print-case* 是通过用LET 重新绑定来临时重新定义的。如果要永久更改,可以通过(setf *print-case* :downcase)设置全局变量的值。
    【解决方案4】:

    Lisp 符号,如'a,不区分大小写。您可以通过以下方式检查...

    (eq 'a 'A)
    

    它们是同一个符号。

    如果需要区分大小写,应酌情使用字符串或字符。

    为了使format在特定情况下打印符号,您可以根据需要将set the *print-case* global variable:upcase:downcase:capitalize

    【讨论】:

    • clhs.lisp.se/Body/v_pr_cas.htm 您可以将*print-case* 全局设置为:downcase
    • -1 符号区分大小写;例如,考虑|a|A'a 等于 'A 的原因是因为 reader 默认情况下会大写符号名称。
    【解决方案5】:

    好的,这可行:

    (format nil "The value is: ~a" (string-downcase 'foo))
    "The value is: foo"
    

    更好(来自 Rainer)

     (format nil "The value is: ~(~a~)" 'foo)
    

    我仍然认为如果意图是表示一个字符串,不应该使用 'foo 而不是“foo”。

    【讨论】:

    • 我正在使用 lispworks。我猜小写在其他 lisps 中很常见。
    • 如果你要做一个自我回答,这完全没问题,甚至在这个网站上受到鼓励,试着让它更有信息,而不仅仅是“哦,这就是我的解决方案只为我工作”。你从中学到什么?
    猜你喜欢
    • 2012-11-20
    • 2015-07-20
    • 1970-01-01
    • 2021-01-24
    • 1970-01-01
    • 1970-01-01
    • 2014-09-12
    • 2016-09-16
    • 1970-01-01
    相关资源
    最近更新 更多