2013-11-25 2 views
3

Я нашел эту функцию LISP в то время как я был прибегая к помощиWeird синтаксис Common Lisp

(defun filter (lst items-to-filter) 
    (cond ((null lst) nil) 
     ((member (car lst) items-to-filter) #1=(filter (cdr lst) items-to-filter)) 
     (t (cons (car lst) #1#)))) 

Это просто установить разницу, но это первый раз, когда я вижу # 1 = и # 1 #, синтаксис. Я думаю, что понимаю, что это значит, просто взглянув на код, но я не уверен. Я думаю, что # 1 = используется для обозначения выражения, чтобы не повторять его позже, когда это необходимо, можно просто ссылаться на него с помощью # index #, в этом случае index = 1. Мне было интересно, может ли кто-нибудь пролить свет на это. Что называются этими конструкциями, если для них есть ссылка, и если они широко используются в современном коде Lisp. Спасибо

+2

Возможный справочный материал: http://www.lispworks.com/documentation/HyperSpec/Body/02_dh.htm Похоже, что второй '#' вызывает макрос «ссылка на». Я не знаю, является ли использование этой функции распространенной. Является ли использование lisp распространенным? :) – pseudocoder

+7

Это макрос читателя с острым значком, который дает возможность ссылаться на ранее прочитанную форму. Для документации см. Раздел 2.4.8.16 Общего Lisp hyperspec, например. на http://www.lispworks.com/documentation/HyperSpec/Body/02_dhp.htm –

+0

Спасибо, что сделал трюк: D. – turingcomplete

ответ

6

Чтобы увидеть это в письменном виде, очень необычно. Большую часть времени вы видите это в данных. Он используется для создания или печати общих элементов данных в s-выражениях. Таким образом, вы также можете читать или печатать круговые s-выражения.

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

CL-USER 3 > (pprint '(defun filter (lst items-to-filter) 
         (cond ((null lst) nil) 
          ((member (car lst) items-to-filter) 
           #1=(filter (cdr lst) items-to-filter)) 
          (t (cons (car lst) #1#))))) 

(DEFUN FILTER (LST ITEMS-TO-FILTER) 
    (COND ((NULL LST) NIL) 
     ((MEMBER (CAR LST) ITEMS-TO-FILTER) 
     (FILTER (CDR LST) ITEMS-TO-FILTER)) 
     (T 
     (CONS (CAR LST) (FILTER (CDR LST) ITEMS-TO-FILTER))))) 

Как вы видите выше, принтер не печатает его таким образом. Почему это? Существует глобальная переменная *print-circle*, которая контролирует ее. Для примера выше было установлено значение NIL. Давайте изменим, что:

CL-USER 4 > (setf *print-circle* t) 
T 

CL-USER 5 > (pprint '(defun filter (lst items-to-filter) 
         (cond ((null lst) nil) 
          ((member (car lst) items-to-filter) 
           #1=(filter (cdr lst) items-to-filter)) 
          (t (cons (car lst) #1#))))) 

(DEFUN FILTER (LST ITEMS-TO-FILTER) 
    (COND ((NULL LST) NIL) 
     ((MEMBER (CAR LST) ITEMS-TO-FILTER) 
     #1=(FILTER (CDR LST) ITEMS-TO-FILTER)) 
     (T 
     (CONS (CAR LST) #1#)))) 

Таким образом, это показывает, что можно читать и печатать такие S-выражения в Common Lisp

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

CL-USER 22 > (defmacro add-1-2-3 (n) `(,n 1 2 3)) 
ADD-1-2-3 

CL-USER 23 > (walker:walk-form '(+ (add-1-2-3 4) (add-1-2-3 5))) 
(+ (4 . #1=(1 2 3)) (5 . #1#)) 
+1

Одним из дополнительных, но редких применений является обращение к буквальному объекту с целью EQness без создания привязки. например в качестве части определения макроса '(lambda (# 1 = #. (gensym)) (declare (ignore # 1 #) ...) –

+1

Другим редким, но полезным примером является ссылка на строку doc для функции, поэтому мы может распечатывать его по мере необходимости: (defun do-it (cmd & rest args) # 1 = "Это делает". (case cmd (: help (print # 1 #)) ...). –