2013-10-15 6 views
2

Я хочу сохранить функцию как print в переменной, так что я могу просто напечатать что-то короткое, как p, например:
В Scheme:Как хранить функцию в переменной в Лиспе и использовать его

(define print display) 
(print "Hello world\n") 
;; alternate way 
(define print 'display) 
((eval print) "Hello world\n") 

Тот же подход, кажется, не работает в Common Lisp:

(defvar p 'print) 
;;(print (type-of p)) 
(p "Hello world") ;; Attempt 1 
((eval p) "Hello world") ;; >> Attempt 2 
((eval (environment) p) "Hello world") ;; Attempt 3 

я получаю эту ошибку с Attempt 1 выше:

*** - EVAL: undefined function P 

И это с Attempt 2 и 3 в Clisp:

*** - EVAL: (EVAL (ENVIRONMENT) P) is not a function name; try using a 
      symbol instead 
*** - EVAL: (EVAL P) is not a function name; try using a symbol instead 

И gcl:

Error: (EVAL P) is invalid as a function. 
Error: (EVAL (ENVIRONMENT) P) is invalid as a function. 

Итак:

  • Что try using a symbol значит? p - это, безусловно, symbol; ложно положительный?
  • Что случилось с eval? Не соответствует ли оценка p процедуре print?
  • Я думал, Lisp процедуры были first class objects. Почему Attempt 1 не работает, как в Scheme?

EDIT
(Перенести из комментариев ниже)

мне было интересно, почему (setf (symbol-function 'p) #'print) не будет работать таким образом
(setf (symbol-function 'p) 'print). Я получаю следующее сообщение (не очень полезно) сообщение об ошибке:

*** - SYSTEM::%PUTD: PRINT is not a function ;; CLisp 
Error: PRINT is not of type LIST. ;; Gcl 

Я знаю, что острый знак (#) предполагается неоднозначность между функцией и переменной
с тем же именем, но в этом случае есть только один print, функция.

Кроме того, почему не будет работать с defvar вместо setf вот так:

(defvar (symbol-function 'p) #'print) 

еще defvar и setf как присвоить значения переменной.
Соответствующая ошибка:

*** - DEFVAR: non-symbol (SYMBOL-FUNCTION 'P) cannot be a variable ;; Clisp 
Error: (SYMBOL-FUNCTION (QUOTE P)) is not of type SYMBOL. ;; Gcl 
+1

Возможный дубликат [Почему нам нужна функция funcall in lisp] (http://stackoverflow.com/questions/9729549/why-do-we-need-funcall-in-lisp) –

ответ

8

Common Lisp является "Lisp-2". Помимо прочего, первая позиция в вызове функции оценивается в «пространстве имен функций». В вашем случае символ p называет переменную, а не функцию.

Это работает лучше:

(defvar p 'print) 

(funcall p "Hello world") 

Или, возможно, но вы, вероятно, не хотят, чтобы сделать это:

(setf (symbol-function 'p) #'print) 

(p "Hello world") 
+1

Учитывая, что это может быть для некоторых Я также хотел бы указать «flet» и «label». –

5

Common Lisp имеет отдельное пространство имен для функций, что делает работу, как это более подробный, чем с помощью Схемы. Если вы хотели бы похожи на верхнего уровень(define p display) в CL вы должны сделать макрос:

(defmacro defun-alias (name original-name) 
    `(setf (symbol-function ',name) #',original-name)) 

который работает как это:

(defun-alias pc princ) 
(pc "Hello") ; prints hello 

В отличии от схемы define это будет только перезапись глобального связывания. Таким образом:

(flet ((test (x) (+ x x))) 
    (defun-alias test +) 
    (test 10)) 

установит глобальное определение #'test к #'+ и вернуться 20. например. он работает как defun.

+0

Мне нравится макрос, он близок к '' Scheme' define' – Segfault

4

В дополнение к другим хорошим ответам с прямыми ответами на вопросы:

What does try using a symbol mean? p is definitely a symbol; false positive?

Прочитайте сообщения об ошибках буквальны: (EVAL (ENVIRONMENT) P) и (EVAL P) (невычисленный) не являются символами, но списки. В Common Lisp автомобиль формы не оценивается.

What's up with eval? Doesn't the evaluation of p yield the procedure print?

eval никогда не вызывается вашим кодом (смотрите предыдущий ответ). Даже если бы это было так, результатом был бы symbol-value символа print, а не /fdefinition.

I thought Lisp procedures were first class objects. Why is Attempt 1 not working like in Scheme?

Это не имеет ничего общего с функциями (я думаю, что Common Lisp стандарт не использует термин «процедуры», поскольку стандарты Scheme делать.), Являющихся объектами первого класса. Это работает в Common Lisp:

(let ((p #'print)) 
    (funcall p "hello world")) 

Edit:

Ответы на дополнительные вопросы:

I was wondering why (setf (symbol-function 'p) #'print) won't work this way (setf (symbol-function 'p) 'print) .

Это не совсем верно, что «острый знак (#) предполагается неоднозначность между функцией и переменной с тем же именем ", как вы напишете позже. 'print расширяется до (quote print), поэтому он вычисляет символ print вместо его значения как переменной. #'print расширяется до (function print), поэтому вместо этого вычисляется значение ячейки функции символа print. Имеет ли значение print значение в качестве переменной, совершенно не имеет значения для оценки #'print.

Установка (symbol-function 'p) к символу print, очевидно, не будет делать p вызовите функцию print, потому что символ print не то же самое, что и функция связана с символом print.

Also, why won't it work with defvar instead of setf like so:

(defvar (symbol-function 'p) #'print) 

yet defvar and setf both assign values to a variable.

setf присваивает значения места. Термин (symbol-function 'p) обозначает место, которое является ячейкой функции символа p.

defvar определяет новые глобальные переменные. Его первый аргумент должен быть символом, который называет переменную и не может быть местом.

+0

И, что ответ на вопрос в комментарии? – Segfault

+0

Почему нет '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '? – Segfault

+0

@Segfault: Вот соответствующий раздел стандарта: http://www.lispworks.com/documentation/HyperSpec/Body/03_abab.htm. Так что на самом деле существуют два допустимых типа для автомобиля формы, символов или лямбда-выражений. Это будет работать: '((lambda (s) (funcall p s))« hello world »)'. –

 Смежные вопросы

  • Нет связанных вопросов^_^