在Common Lisp中合并符号

4
我想将一个字符插入到列表中。但是,我希望将这个字符与列表中的最后一个符号合并。使用appends和cons,结果始终是两个不同的符号。我希望得到一个合并的符号作为我的结果。
例子:
       (XXXX 'a '5) ====>  (a5)    

我希望有以下内容,而不是:

       (XXXX 'a '5) ====> (a 5)   
3个回答

11

在Lisp中,您无法“合并符号”。

首先,5不是符号,而是数字。如果您想要一个名为"5"的符号,您需要将其输入为|5|(例如)。

如果一个函数接受符号A和符号|5|,并生成符号A5,它并没有合并符号。它创建了一个新的符号,其名称是这些输入符号名称的连接。

正确设计的Lisp程序很少依赖于符号的命名方式。它们依赖于符号作为唯一实体。

如果您正在使用符号来标识某些东西,并且5A都标识某个实体,则最好的答案不一定是创建一个新符号,它在名称上至少是这两个符号的混合物。例如,更好的设计可能是接受名称具有多个方面或复合性质的事实。也许列表(A 5)可以作为一个名称。

通用Lisp函数本身可以具有复合名称。例如,(setf foo)是一个函数名称。像列表这样的集合可以作为名称。

如果您只需要计算机在运行时发明唯一的符号,请考虑使用gensym函数。您可以向其传递自己的前缀:

(gensym "FOO") -> #:FOO0042

当然,前缀可以是某个现有符号的名称,通过symbol-name来获取。符号#:FOO0042 不是因为0042 而独特,而是因为它是地址空间中新分配的对象。#:意味着它没有被保存在任何包中。该符号的名称是FOO0042

如果您仍然真的想要,将一堆输入对象的打印表示形式转换为符号的简单方法如下:

(defun mashup-symbol (&rest objects)
  (intern (format nil "~{~a~}" objects)))

示例:

(mashup-symbol 1 2 3) -> |123|

(mashup-symbol '(a b) 'c 3) -> |(A B)C3|

5

请定义此内容:

(defun symbol-append (&rest symbols) 
  (intern (apply #'concatenate 'string 
                 (mapcar #'symbol-name symbols))))

然后可以将其用作:

* (symbol-append 'a 'b 'c)
ABC

* (apply #'symbol-append '(a b c))
ABC

如果您的参数中除了符号外还包含其他内容,请将symbol-name替换为:

   (lambda (x)
     (typecase x ...)) 

或者一个我已经忘记的预先存在的CL函数,将任何东西转化为字符串。


函数 string 将字符串标识符转换为字符串,但不包括路径名。 - sds

2
你所询问的问题的答案是:
(defun concatenate-objects-to-symbol (&rest objects)
  (intern (apply #'concatenate 'string (mapcar #'princ-to-string objects))))
(concatenate-objects 'a 'b) ==> ab

如果您希望结果以列表的形式呈现:

(defun xxxx (s1 s2) (list (concatenate-objects-to-symbol s1 s2)))

然而,我相当确定这并不是你实际想要问的问题。

编程创建新符号并不是初学者应该做的事情...


一旦您在Lisp监听器中输入一个被解释为符号名称的标记,就创建了一个符号。 - Kaz
不公平!你抄袭了我的答案!!(定义 xxxx (s1 s2)...)<笑脸> - GoZoner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接