【问题标题】:Common Lisp Programmatic KeywordCommon Lisp 程序化关键字
【发布时间】:2008-10-17 10:54:37
【问题描述】:

Common Lisp 中是否有一个函数可以将字符串作为参数并返回关键字?

示例:(keyword "foo") -> :foo

【问题讨论】:

    标签: common-lisp


    【解决方案1】:

    给出的答案虽然大致正确,但并不能产生问题示例的正确解决方案。

    考虑:

    CL-USER(4): (intern "foo" :keyword)
    
    :|foo|
    NIL
    CL-USER(5): (eq * :foo)
    
    NIL
    

    通常你想在实习之前将 STRING-UPCASE 应用于字符串,因此:

    (defun make-keyword (name) (values (intern (string-upcase name) "KEYWORD")))
    

    【讨论】:

    • 当然,可能是 OP 刚刚将 print-case 设置为 :downcase...
    【解决方案2】:

    这是一个 make-keyword 函数,它将关键字创建过程打包(interning 将名称放入 KEYWORD 包中)。 :-)

    (defun make-keyword (name) (values (intern name "KEYWORD")))
    

    【讨论】:

    • 差不多,但不完全。创建关键字时,还必须确保将其值绑定设置为自身。
    • @Vatine 我只有 SBCL 来测试,而在 SBCL 中,(symbol-value (intern "FOO" "KEYWORD")) 已经有了正确的值。此外,Alexandria 也使用相同的方法实现它。
    • @Vatine 11.1.2.3.1 Interning a Symbol in the KEYWORD Package 说(添加了重点),“KEYWORD 包的处理方式与其他包不同,因为在其中包含符号时​​会执行特殊操作。特别是,当一个符号被嵌入到 KEYWORD 包中,它会自动成为一个外部符号,并且会自动成为一个常量变量,并以自身为值。"
    【解决方案3】:

    Alexandria 库中有一个 make-keyword 函数,尽管它确实保留了大小写,因此要准确获得您想要的内容,您必须先将字符串大写。

    【讨论】:

    • 或将print-case 设置为:downcaseintern 不做任何大小写修改,所以这里的解决方案可能也不应该。 (虽然问题中的示例确实说(keyword "foo") => :foo,但最好使用(... "foo") => :|foo|(... "FOO") => :FOO。)
    【解决方案4】:

    在此示例中,它还处理带有空格的字符串(用点替换它们):

    (defun make-keyword (name) (values (intern (substitute #\. #\space (string-upcase name)) :keyword)))
    

    【讨论】:

    • 您是否有理由想用点替换空格?如果你实习 "foo bar" 你会得到一个名为 "foo bar" 的符号,这没有问题。 intern 也不用点替换空格。
    【解决方案5】:

    如果您可以将字符串更改为以冒号开头:

    直接使用read-from-string

    这里是另一个版本的make-keyword

    (defun make-keyword (name)
               (read-from-string (concatenate 'string ":" name)))
    

    【讨论】:

    • 你就不能(read-from-string (concatenate 'string ":" name))吗?
    【解决方案6】:
    (intern "foo" "KEYWORD") -> :foo
    

    请参阅Common Lisp CookbookStrings section 了解其他字符串/符号转换以及符号和包的详细讨论。

    【讨论】:

    • 该名称需要在“KEYWORD”包中作为关键字。例如,(实习生“FOO”“KEYWORD”)
    • 啊是的。 (intern "foo" "KEYWORD") 工作得很好。谢谢。
    • 在我的回答中,我已经将它打包成一个简洁的小功能,您可能会喜欢。 :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-14
    • 2012-12-11
    • 1970-01-01
    • 2015-03-14
    • 2012-06-04
    • 2021-05-09
    • 1970-01-01
    相关资源
    最近更新 更多