如何使用字符串在包中查找变量并进行更改?

时间:2017-04-22 13:04:58

标签: package lisp common-lisp

我有一些变量包:

(in-package #:pack)

(defparameter *a* "foo")
(defparameter *b* "bar")

导出变量*a**b*

我的目标是使用字符串("*a*""*b*"

更改此变量

我可以使用intern函数

找到这些变量
(symbol-value (intern (string-upcase "*a*") :pack)) ;; return *a* symbol
(symbol-name (intern (string-upcase "*a*") :pack))  ;; return "foo"

但如果我尝试用

更改符号
(setf (symbol-name (intern (string-upcase "*a*") :pack)) "baz")

我有一个错误:

The function (COMMON-LISP:SETF COMMON-LISP:SYMBOL-NAME) is undefined.
[Condition of type UNDEFINED-FUNCTION]

如何更改这些变量?

1 个答案:

答案 0 :(得分:2)

正如评论@jkiiski所指出的那样,共同的lisp函数用于在包中查找符号:

find_symbol:

功能FIND-SYMBOL

语法:

find-symbol string& optional package =>符号,状态

然后另一个重要的事情是看看understanding the difference between variables and symbols in common lisp的答案。

函数set,setq和setf来自common lisp hypersec

  

设置将符号的值单元格的内容更改为给定   值。

     

setq(setq var1 form1 var2 form2 ...)是简单的变量赋值   Lisp的陈述。评估第一个form1并存储结果   在变量var1中,然后评估form2并将结果存储在   var2,等等。 setq可用于分配词汇   和动态变量。

     

(setf place newvalue)扩展为存储的更新表单   将newvalue评估到地点引用的位置的结果。   一些地方形式涉及使用可选的访问者   参数。是否允许这些可选参数由setf或   他们的用途是什么,取决于setf扩展器功能而不是   在setf的控制下。任何功能的文档   接受& optional,& rest,或..... key参数和声称的   可用于setf必须指定如何处理这些参数。

所以加入所有这些东西我们可以得到这个代码:

(defpackage :pack
  (:use :cl) ;; You must import this line in order to use functions from cl package like setf
  (:export :*a*
           :*b*))

(in-package :pack)

(defparameter *a* "foo")
(defparameter *b* "bar")

现在让我们探讨变量

CL-USER> pack:*a*
"foo"
CL-USER> pack:*b*
"bar"

然后我们可以找到符号 a (请注意,如果不使用||来命名符号,则常见的lisp不区分大小写)

CL-USER> (find-symbol "*A*" :pack)
PACK:*A*
:EXTERNAL

所以在这里,没有任何意外存在的符号 a 并且它在包装的外部

然后让我们更改值设置我们可以直接更改值但是使用setf我们需要一个地方,在常见的lisp情况下指针有一个不同的指针,在这种情况下,对我们来说重要的是符号值。所以为了改变我们可以按照以下步骤进行:

CL-USER> (set (find-symbol "*A*" :pack) "baz")
"baz"
CL-USER> pack:*a*
"baz"
CL-USER> (setf (symbol-value (find-symbol "*A*" :pack)) "buzz" )
"buzz"
CL-USER> pack:*a*
"buzz" 

希望这有帮助。