开发者

Call function based on a string

开发者 https://www.devze.com 2023-01-01 08:25 出处:网络
I am passing in command line arguments to my Lisp program and they are formatted like this when they hit my main function:

I am passing in command line arguments to my Lisp program and they are formatted like this when they hit my main function:

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

I have a dot function (which takes two vectors as arguments) and would like to call it directly from the argument, but this isn't possible because something like (funcall (second args)...) receives "dot" and not dot as the function name.

I tried variations of this function:

(defun remove-quotes (s)

(setf (aref s 0) '""))

to no avail, before realizing that the quotes were not really a part of the string. Is there 开发者_开发问答a simple way to do this, or should I just check each string and then call the appropriate function?


"1 1 1" is a string of five characters: 1, space, 1, space and 1. The double quotes are not part of the string.

("1 1 1" "dot" "2 2 2") is a list of three strings.

There are no " characters above. The " are used to delimit strings in s-expressions.

If you have a dot function you need to tell us what kind of input data it expects. Does it expect two lists of numbers? Then you have to convert the string "1 1 1" into a list of numbers.

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

To get the function DOT from the string "dot" first find the symbol DOT and then get its symbol function.

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

For find-symbol one might need to specify also the package, if there is a special package where the symbol is in.

Converting a list to a vector then is the next building block.

So you need to convert the arguments for your function to vectors (probably first converting them to lists as I showed above). Then you need to find the function (see above). If you have then the function and the arguments, then you can call the function using FUNCALL or APPLY (whatever is more convenient).


The question is a bit unclear, but as far as I understand it you want, when given the list ("1 1 1" "dot" "2 2 2") as input to evaluate the expression (dot "1 1 1" "2 2 2"). In that case you can do this:

(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"))


funcall does not accept a string as a function designator. You need to give it a symbol instead. What you probably want to do is:

  1. Convert the string to upper case (Lisp symbols are usually upper case, and even though it may look like Lisp is case-insensitive, that's just because the reader upcases all symbols it reads by default) (string-upcase).
  2. Create or find a symbol with the given name (intern). Note that, if *package* is not set according to the package your function's name lives in, you need to supply the package name as the second argument to intern.

For instance (for a function named dot in package cl-user:

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

精彩评论

暂无评论...
验证码 换一张
取 消