2017-01-21 65 views
6

Common Lisp i Clojure zrobićDlaczego niektórzy sepleniści umieszczają nazwę funkcji poza listą argumentów w definicji funkcji?

(defn function-name (arg1 arg2) (body)) 

rakieta/program robi

(defn (function-name arg1 arg2) (body)) 

Ten ostatni ma większy sens dla mnie, bo składnia definicji funkcji i wywołania jest podobny. Jakie jest uzasadnienie tego pierwszego?

+0

myślę prawdziwa odpowiedź brzmi „Historia” : Schemat i jego warianty stanowiły jeden wybór, MACLISP i jego potomkowie byli kolejnymi. Jestem całkiem pewien, że inne wczesne Lispy, które nie mają żywych potomków, miały jeszcze inne składnie: zapomniałem, co zrobił InterLisp, ale prawdopodobnie było to coś dziwnego i innego. – tfb

Odpowiedz

11
Ten ostatni ma dla mnie więcej sensu, ponieważ składnia definicji funkcji i wywołania jest podobna.

W Common Lisp definicja funkcji na ogół nie jest podobna do inwokacji, więc nie ma sensu udawać, że to robią.

Jest to ważna funkcja defintion:

(defun foo (arg1 arg2 
      &optional (ovar 10) 
      &rest args 
      &key (ak 11 a-p) 
      &allow-other-keys 
      &aux (aux1 12)) 
    (list arg1 arg2 ovar args ak a-p aux1)) 

te obowiązują domaga się powyżej:

(foo 1 2) 
(foo 1 2 3) 
(foo 1 2 3 :ak 4) 
(foo 1 2 3 :foo 10 :ak 4) 

Zatem argumenty wywołania wyglądać inaczej niż na liście argumentów definicja.

W przypadku DEFMETHOD definicja może wyglądać następująco:

(defmethod (setf foobar) :around ((value integer) (object foo)) 
    (setf (slot-value object 'a) value)) 

i rozmowa będzie

(setf (foobar object) 10) 

Podsumowanie

W definicji funkcji Common Lisp nie będzie wyglądać podobnie jak i połączenia

Excursion

To proste do zdefiniowania składni Schemat podobną do prostych funkcji CL:

(defmacro define ((name &rest args) &body body) 
    `(defun ,name ,args ,@body)) 

CL-USER 36 > (macroexpand-1 `(define (foo a b c) (baz) (bar))) 
(DEFUN FOO (A B C) (BAZ) (BAR)) 
T 

Niektóre programy nawet użyć coś podobnego ...

1

Definicja funkcji to tylko operacja w rodzinie Lisp. Nie ma większego sensu w tworzeniu definicji funkcji podobnej do zastosowania funkcji.

13

TL; DR To nie jest tak proste, jak to ujęłeś. Składnia jest nieco bardziej odmienna i za każdym razem, gdy ktoś tworzy język, decyduje się na nową składnię, zwykle w celu uczynienia go bardziej zwięzłym, że poprzednie języki lub język ma projekt, który tego wymaga. Oczywiście to, co jest "lepsze", jest kwestią opinii.

W Schemacie (i Renie potomka) masz jedną przestrzeń nazw dla zmiennych i funkcji. W ten sposób używasz define do wszystkiego.

(define variable 10) 
(define function (lambda (arg1 arg2) body ...)) 

Teraz define ma skrót dla tego ostatniego, który jest:

(define (function arg1 arg2) body ...) 

więc regułą jest, jeśli pierwsza część jest pair? to ma być rozszerzona do dłuższej formy z lambda. To, jak przypuszczam, przypomina aplikację. Ta dodatkowa funkcja służy tylko do zapisywania niektórych klawiszy i jest często pomijana w takich książkach jak "Mały Schemat", ponieważ jest myląca, ponieważ ma dwie drogi, a osoba ucząca się i mogą myśleć, że zdefiniowanie wiązania dla funkcji jest bardziej wyjątkowe niż zdefiniowanie 10, co jest niedorzeczne. Reszta argumentów zwykle się myli. na przykład. Są to te same:

(define (test . x) x) 
(define test (lambda x x)) 

W Common Lisp masz dwie przestrzenie nazw, a więc defun służy tylko do zasięgu globalnym i istnieją odpowiedniki funkcji zmiennych form sprawia, że ​​funkcje. w defun masz listę pierwszy argument w Common Lisp też, ale robi coś zupełnie innego:

(defun (setf name) (new-value) 
    body ...) 

ten zapewnia sposób, aby uzyskać taką samą symetrię jak innych akcesorów w CL. na przykład. jeśli (car x) otrzyma wartość samochodu od kantu (setf (car x) 10) zmieni go. W moim przykładzie name można używać w taki sam sposób, jak car. Jest bardzo przydatny.

Clojure robi to z def i fn i wykorzystuje tablicę dla parametrów:

(def function (fn [arg1 agr2] body ...)) 

defn jest tylko skróconą wersję podobnie jak define zaczynającej się parą. To, że nie jest bardziej podobny do Schematu, jest być może faktem, że dane parametru są tablicą lub że składnia zachowała składnię jak najbliżej oryginału. Jeśli dobrze pamiętam, możesz mieć nazwę funkcji jako drugi argument z wartością fn, co powoduje, że wyglądanie jest prawie identyczne.