Вызов функции на основе строки - PullRequest
6 голосов
/ 31 мая 2010

Я передаю аргументы командной строки моей программе на Лиспе, и они форматируются следующим образом, когда попадают в мою главную функцию:

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

У меня есть функция точки (которая принимает два вектора в качестве аргументов), и я хотел бы вызвать ее непосредственно из аргумента, но это невозможно, потому что что-то вроде (funcall (second args) ...) получает «точку» а не точка в качестве имени функции.

Я пробовал варианты этой функции:
(defun remove-quotes (s)<br> (setf (aref s 0) '""))

безрезультатно, прежде чем понять, что кавычки на самом деле не являются частью строки. Есть ли простой способ сделать это, или я должен просто проверить каждую строку и затем вызвать соответствующую функцию?

Ответы [ 3 ]

8 голосов
/ 31 мая 2010

«1 1 1» - это строка из пяти символов: 1, пробел, 1, пробел и 1. Двойные кавычки не являются частью строки.

("1 1 1" "точка" "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, а затем получите функцию символа.

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

Для символа поиска может потребоваться указать также пакет, если есть специальный пакет, в котором находится символ.

Преобразование списка в вектор является следующим строительным блоком.

Так что вам нужно преобразовать аргументы вашей функции в векторы (возможно, сначала преобразовать их в списки, как я показал выше). Затем вам нужно найти функцию (см. Выше). Если у вас есть функция и аргументы, вы можете вызвать функцию с помощью FUNCALL или APPLY (что удобнее).

2 голосов
/ 31 мая 2010

funcall не принимает строку в качестве обозначения функции. Вы должны дать ему символ вместо этого. Что вы, вероятно, хотите сделать, это:

  1. Преобразование строки в верхний регистр (символы Lisp обычно пишутся в верхнем регистре, и, хотя может показаться, что Lisp не чувствителен к регистру, это просто потому, что читатель преобразует все символы, которые он читает по умолчанию) (string-upcase).
  2. Создать или найти символ с заданным именем (intern). Обратите внимание, что если *package* не установлено в соответствии с пакетом, в котором находится имя вашей функции, вы должны указать имя пакета в качестве второго аргумента для intern.

Например (для функции с именем dot в пакете cl-user:

(funcall (intern (string-upcase "dot") 'cl-user) ...)
2 голосов
/ 31 мая 2010

Вопрос немного неясен, но, насколько я понимаю, вы хотите, когда дан список ("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"))
...