如何自动识别或允许我的程序的用户识别Lisp中的变量



我在Lisp中遇到了一个微妙的(我认为(问题,这与我之前问的一个问题有关:如何在Lisp中将变量命名为字符串?

情况如下:

  1. 我正在创建一种语言,用户在其中输入文本字符串,然后我的解析器根据他们的输入创建唯一标识的实体(和其他东西(
  2. 典型而简单的输入是:my_name:my_contents——其中my_name是实体的名称,my_contents是字符串
  3. 因此,我需要找到一种方法来建立一个lisp程序,该程序接受用户输入,然后创建实体并根据用户输入识别它们

到目前为止,我已经考虑了两种方法:

  • A每个实体一个变量:当用户输入字符串时,Lisp获取my_name并创建一个具有该名称的变量,然后将my_contents放入其中。这里的缺点是,我不知道如何将变量的名称设置为一些用户定义的可变输入,如my_name。

  • B一个表,比如哈希表:当用户输入一个字符串时,Lisp会向哈希表中添加一行,其中my_name是关键字,my_contents是条目。这种方法的缺点是,我在任何给定的时刻都找不到将密钥设置为my_name的方法。

总之,我正在1号找律师。如何以用户定义的字符串或2命名变量。如何将用户定义的字符串设置为哈希表中的键或3。是否有更好的方法。

提前感谢!

如果你感到困惑,我建议你把你的计划分解成更小的部分。或者只是用repl来处理这些想法,这样你就会看到你的许多问题得到了回答。

开始:创建哈希表:

>> (make-hash-table)
;;... some hash table is created ...

注意:在下面,你会看到这种类型的哈希表不能与你的字符串键一起使用,但要继续使用:

等等,您需要引用它,让我们将它设置为一个变量:

>> (setf my-hash *)

或类似:

>> (setf my-hash (make-hash-table))

添加一些值:

>> (setf (gethash "key1" my-hash) "value1")
>> (setf (gethash "key2" my-hash) "value2")

嗯,我想看看价值观。有几个选择。让我们检查CLHS中的一个:http://clhs.lisp.se/Body/f_maphas.htm#maphash

复制粘贴示例的最后一行:

>> (maphash #'(lambda (k v) (print (list k v))) my-hash)
("key1" "value1")
("key2" "value2")
NIL

现在我想知道我是否可以使用getash访问条目:

>> (gethash "key1" my-hash)
NIL

我不能!这是因为我们在上面使用的make hash表默认使用'eql作为测试谓词。我们需要改变这一点。用一个更合适的哈希表重新做所有事情:

>> (setf my-hash (make-hash-table :test 'equal))
>> (setf (gethash "key1" my-hash) "value1")
>> (setf (gethash "key2" my-hash) "value2")
>> (maphash #'(lambda (k v) (print (list k v))) my-hash)
("key1" "value1")
("key2" "value2")
>> (gethash "key1" my-hash)
"value1"

这样更好。

请原谅我在回答你的问题之前先从基础开始。我觉得我们有时会忘记原则/基本原则。如果你这样处理你的答案,我想你会发现找到你想要的答案会更容易。

现在,为了补充Numbra的答案,这里有一些提示:

如果你想使用哈希表:

>> (setf user-entered-string "VARIABLE1")
>> (setf user-entered-value "value1")
>> (setf (gethash user-entered-string) user-entered-value)

或,符号:

>> (intern user-entered-string)
;; now it is a symbol object in current package:
>> (find-symbol user-entered-string)
>> (setf (symbol-value (find-symbol user-entered-string)) user-entered-value)

我不确定是否能理解您的所有问题,但是:

以用户定义的字符串命名变量:

(或多或少(这样做的函数是intern(或read,但更通用(。你可能想在一个"CCD_;用户包";,以便不与实际代码冲突。

哈希表

在这里,我不确定是什么导致了你的麻烦:如果用户输入了一个字符串(你可以用获得,例如read-line或更复杂的东西,如果你愿意的话(,在你的代码中绑定到,比如user-string-name,你可以只做(setf (gethash user-string-variable *user-defined-variables*) user-string-value),假设你已经创建了这样一个哈希表。请注意,默认情况下,哈希表使用eql来比较键,这不是字符串所需要的;您需要创建带有参数:test 'equal的表。

其他选项

使用符号特性列表。


可能还有更多我没有想到的解决方案。决定哪一个是最好的可能取决于很多事情,考虑到你的申请,我会让你决定你更喜欢哪一个。

最新更新