2011-10-27 13 views
5
kod

Emacs dla apply-partially to:Jak działa definicja "apply-partial" w Emacs 24?

(defun apply-partially (fun &rest args) 
    "Return a function that is a partial application of FUN to ARGS. 
ARGS is a list of the first N arguments to pass to FUN. 
The result is a new function which does the same as FUN, except that 
the first N arguments are fixed at the values with which this function 
was called." 
    `(closure (t) (&rest args) 
      (apply ',fun ,@(mapcar (lambda (arg) `',arg) args) args))) 

To zwraca listę, która wygląda trochę jak wyrażenia lambda, oprócz tego, że lambda zastępuje closure (t). Na przykład, (apply-partially 'cons 1) powraca w ten sposób:

(closure (t) (&rest args) (apply (quote cons) (quote 1) args)) 

który, o ile wiem, wygląda i działa dokładnie tak:

(lambda (&rest args) (apply (quote cons) (quote 1) args)) 

wyjątkiem tego, że „zamknięcie” wyrażenie nie ma „ja -quoting "właściwość lambda, więc kiedy próbuję to ocenić, Emacs informuje mnie, że closure nie ma definicji funkcji: Lisp error: (void-function closure).

Nie mogę znaleźć żadnych odniesień w podręczniku Elisp do korzystania z symbolu closure w ten sposób. Wydaje się, że jest to jakaś wewnętrzna magia Emacsa. Wyrażenie zamknięcia wyraźnie nie jest oceniane zgodnie z normalnymi regułami (ponieważ ręczne wykonanie powoduje błąd).

Co tu się dzieje? Czy muszę pobrać kod C w celu uzyskania odnośników do "zamknięcia", aby się dowiedzieć?

EDYCJA: Wydaje się, że w Emacs 23 i poniżej, apply-partially po prostu używa lexical-let z pakietu cl, aby dokonać zamknięcia. Powyższa definicja pochodzi z wersji "24.0.90.1".

Odpowiedz

3

Znalazłem odpowiedź w eval.c w funkcji funcall_lambda:

if (EQ (XCAR (fun), Qclosure)) 
{ 
    fun = XCDR (fun); /* Drop `closure'. */ 
    lexenv = XCAR (fun); 
    CHECK_LIST_CONS (fun, fun); 
} 
    else 
lexenv = Qnil; 

closure (t) wydaje się być leksykalny odpowiednik lambda. Drugi element, (t), zostaje przypisany do lexenv, więc myślę, że ten element służy do zamykania wartości leksykalnych zdefiniowanych poza samą funkcją lub czymś.

Podejrzewam, że brak samodzielnego cytowanie może być niedopatrzenie, którym można zaradzić w następujący sposób:

(defmacro make-self-quoting (name) 
    "Make NAME into a self-quoting function like `lambda'." 
    `(defmacro ,name (&rest cdr) 
    (list 'function (cons ',name cdr)))) 
(make-self-quoting closure) 
+0

Racja, w przypadku stosowania-częściowo, środowisko leksykalne jest puste, ale wciąż jest jedna różnica: argument "args" będzie leksykalny, podczas gdy z 'lambda' będzie dynamicznie związany. Zapewnia to, że nazwa 'args' nie będzie zakłócać innych zastosowań tej zmiennej w innym miejscu. – Stefan

+0

Jeśli chodzi o brak cytatów, to nie jest to naprawdę niedopatrzenie, po prostu nie jest potrzebne: '(zamknięcie ...)' nigdy nie powinno występować w kodzie źródłowym. – Stefan

1

z moim "GNU Emacs 23.2.1 (i686-pc-Cygwin)" jest zdefiniowany jako

(defun apply-partially (fun &rest args) 
    "Return a function that is a partial application of FUN to ARGS.    
ARGS is a list of the first N arguments to pass to FUN.       
The result is a new function which does the same as FUN, except that    
the first N arguments are fixed at the values with which this function   
was called." 
    (lexical-let ((fun fun) (args1 args)) 
    (lambda (&rest args2) (apply fun (append args1 args2))))) 

zrozumienia jak to działa wydaje się być dość łatwe Oto jest: lambda pamięta częściowy zestaw args i dołącza resztę podczas wywoływania oryginalnej funkcji.

+0

biegnę Emacsa 24, który ma teraz swój własny leksykalny scopingu, które nie opierają się na pakiecie cl. Domyślam się, że rzecz "zamknięcia" jest nowa dla Emacsa 24. –

+0

Jeśli "zamknięcie" jest symbolem, to czy ludzie muszą mieć coś z tym wspólnego? –

+0

http://www.emacswiki.org/emacs/closure2.el ma "zamknięcie defmacro", ale nie jest jasne, czy jest częścią Emacs. –