views:

223

answers:

3

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?

Thanks!

+5  A: 

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

Rainer Joswig
Dot takes two vectors as arguments. I was hoping to get the symbol "dot" out of the string.
powerj1984
I don't quite understand the iteration method above and I get an infinite loop when I attempt to run it.
powerj1984
@powerj1984 : I have replaced UNLESS with UNTIL. Should work now.
Rainer Joswig
+2  A: 

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"))
sepp2k
Sorry my question is unclear, that is very similar to what I want - dot takes two vectors as arguments but you've got me on the right track, thanks!
powerj1984
+1  A: 

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) ...)
Matthias Benkard