带有重音符号作为键的通用Lisp哈希表

时间:2019-06-30 19:20:02

标签: unicode lisp common-lisp hashtable

我正在尝试在Common Lisp中创建一个哈希表以将字符存储为键,但是如果使用带重音符号的字符,则哈希表将不起作用。只需一个可能的带有重音符号的键。

在此示例中,我添加了5个键,并看到哈希表显示了5个元素,然后添加了另外5个带有重音符号的表格,表中显示了6个元素,然后添加了另一个“普通” 5个元素,大小变为11(如预期)。

发生了什么事?我该如何解决呢?

(defparameter *h* (make-hash-table))
(setf (gethash #\A *h*) #\A)
(setf (gethash #\E *h*) #\A)
(setf (gethash #\I *h*) #\A)
(setf (gethash #\O *h*) #\A)
(setf (gethash #\U *h*) #\A)
(hash-table-count *h*)
(setf (gethash #\á *h*) #\A)
(setf (gethash #\é *h*) #\A)
(setf (gethash #\í *h*) #\A)
(setf (gethash #\ó *h*) #\A)
(setf (gethash #\ú *h*) #\A)
(hash-table-count *h*)
(setf (gethash #\a *h*) #\A)
(setf (gethash #\e *h*) #\A)
(setf (gethash #\i *h*) #\A)
(setf (gethash #\o *h*) #\A)
(setf (gethash #\u *h*) #\A)
(hash-table-count *h*)

2 个答案:

答案 0 :(得分:4)

来自SBCL manual

On non-Unicode builds, the default external format is :latin-1.

您要使用UTF-8。因此,按照手册中的说明进行操作,并在致电SBCL时设置环境:

$ LANG=C.UTF-8 sbcl --noinform --no-userinit --eval "(print (map 'string #'code-char (list 97 98 246)))" --quit
"abö"
$ LANG=C sbcl --noinform --no-userinit --eval "(print (map 'string #'code-char (list 97 98 246)))" --quit
"ab?"

如果您使用Emacs的SLIME或Sly,则可以在init中进行设置:

(setq sly-lisp-implementations
      '((sbcl ("/opt/sbcl/bin/sbcl") :coding-system utf-8-unix)))

然后使用健全的测试功能,例如char=。我认为您应尽可能使用最具体的谓词。 char-equal是不区分大小写的版本。

Sly manual, though the above snippet works on SLIME too as slime-lisp-implemetations

如@Manuel的注释中所述,如果您的LANG变量和朋友不使用UTF-8,那么您注定要失败。 See this quetsion

答案 1 :(得分:2)

如果出于某种原因无法更改SBCL的默认external fomat,则可以始终使用 #\LATIN_SMALL_LETTER_A_WITH_ACUTE