基于字符串调用函数

问题描述 投票:0回答:3

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

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

我有一个点函数(它接受两个向量作为参数)并想直接从参数调用它,但这是不可能的,因为像 (funcall (第二个参数)...) 这样的东西接收

"dot"
而不是
dot
作为函数名称。

我尝试了此功能的变体:

(defun remove-quotes (s)
  (setf (aref s 0) '""))

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

string lisp common-lisp
3个回答
10
投票

"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
(以更方便的方式)调用该函数。


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
投票

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

  1. 将字符串转换为大写(Lisp 符号通常都是大写,尽管看起来 Lisp 不区分大小写,但这只是因为阅读器默认将其读取的所有符号都大写)(
    string-upcase
    )。
  2. 创建或查找具有给定名称的符号 (
    intern
    )。请注意,如果未根据函数名称所在的包设置
    *package*
    ,则需要将包名称作为第二个参数提供给
    intern

例如(对于包

dot
中名为
cl-user
的函数:

(funcall (intern (string-upcase "dot") 'cl-user) ...)
© www.soinside.com 2019 - 2024. All rights reserved.