基于字符串调用函数

时间:2010-05-30 20:54:36

标签: string lisp common-lisp

我将命令行参数传递给我的Lisp程序,当它们点击我的主函数时,它们的格式如下:

("1 1 1" "dot" "2 2 2") 

我有一个点函数(它将两个向量作为参数)并且想直接从参数中调用它,但是这是不可能的,因为像(funcall(second args)...)这样的东西会收到“dot”而不是点作为函数名称。

我尝试过这个功能的变体:
(defun remove-quotes (s)
(setf (aref s 0) '""))

无济于事,才意识到引号不是字符串的一部分。有没有一种简单的方法可以做到这一点,或者我应该检查每个字符串然后调用适当的函数?

3 个答案:

答案 0 :(得分:8)

“1 1 1”是一个由五个字符组成的字符串:1,空格,1,空格和1.双引号不是字符串的一部分。

(“1 1 1”“dot”“2 2 2”)是三个字符串的列表。

上面没有“字符。”用于分隔s表达式中的字符串。

如果你有一个点函数,你需要告诉我们它期望什么样的输入数据。 它有两个数字列表吗?然后,您必须将字符串“1 1 1”转换为数字列表。

(with-input-from-string (in "1 1 1")
  (loop for data = (read in nil in)
   until (eq data in)
   collect data)))

要从字符串“dot”获取函数DOT,首先找到符号DOT,然后获取其符号函数。

(symbol-function (find-symbol (string-upcase "dot")))

对于find-symbol,如果符号所在的特殊包中,可能还需要指定包。

将列表转换为向量然后是下一个构建块。

所以你需要将函数的参数转换为向量(可能首先将它们转换为列表,如上所示)。然后你需要找到这个功能(见上文)。如果你有函数和参数,那么你可以使用FUNCALL或APPLY调用函数(无论什么更方便)。

答案 1 :(得分:2)

问题有点不清楚,但据我所知,当你将列表("1 1 1" "dot" "2 2 2")作为输入来评估表达式(dot "1 1 1" "2 2 2")时,你想要它。在这种情况下,您可以这样做:

(defun apply-infix (arg1 f arg2)
  (apply (intern (string-upcase f)) (list arg1 arg2)))
(defun apply-list-infix (lst)
  (apply 'apply-infix lst))

(apply-list-infix '("1 1 1" "dot" "2 2 2"))

答案 2 :(得分:2)

funcall不接受字符串作为函数指示符。你需要给它一个符号。你可能想做的是:

  1. 将字符串转换为大写(Lisp符号通常是大写的,即使它看起来像Lisp是不区分大小写的,这只是因为读者在默认情况下提升了它所读取的所有符号)(string-upcase
  2. 创建或查找具有给定名称(intern)的符号。请注意,如果未根据函数名称所在的包设置*package*,则需要提供包名称作为intern的第二个参数。
  3. 例如(对于包dot中名为cl-user的函数:

    (funcall (intern (string-upcase "dot") 'cl-user) ...)