Как работает определение `apply-частично` в Emacs 24? - PullRequest
5 голосов
/ 27 октября 2011

Код Emacs для apply-partially таков:

(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)))

Возвращает список, который очень похож на лямбда-выражение, за исключением того, что lambda заменяется на closure (t).Например, (apply-partially 'cons 1) возвращает это:

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

, который, насколько я могу судить, выглядит и работает именно так:

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

за исключением того, что выражение "closure"не имеет свойства «самоквартирования» лямбды, поэтому, когда я пытаюсь оценить его, Emacs сообщает мне, что closure не имеет определения функции: Lisp error: (void-function closure).

Я не могу найти ни одногоссылки в руководстве Elisp на использование символа closure таким образом.Кажется, это какая-то внутренняя магия Emacs.Выражение замыкания явно не оценивается в соответствии с обычными правилами (поскольку выполнение этого вручную приводит к ошибке).

Так что здесь происходит?Нужно ли использовать grep-код C для ссылок на «замыкание», чтобы узнать?

РЕДАКТИРОВАТЬ: Похоже, что в Emacs 23 и ниже, apply-partially просто использует lexical-let из пакета cl, чтобы сделатьзакрытиеВышеприведенное определение взято из версии "24.0.90.1".

Ответы [ 2 ]

3 голосов
/ 27 октября 2011

Я нашел ответ в eval.c, в функции 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) представляется лексическим эквивалентом lambda.Второй элемент, (t), присваивается lexenv, поэтому я предполагаю, что этот элемент предназначен для закрытия лексических значений, определенных вне самой функции или чего-то подобного.Это может быть упущение, которое можно исправить следующим образом:

(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)
1 голос
/ 27 октября 2011

С моим "GNU Emacs 23.2.1 (i686-pc-cygwin)" оно определяется как

(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)))))

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

...