То, что я подразумеваю под «прозрачной« проходной »функцией-оберткой», - это функция, давайте назовем ее wrapper
, которая возвращает результат передачи всех своих аргументов какой-то другой функции, давайте назовем ее wrappee
.
Как это делается в Emacs Lisp?
NB: Идеальная wrapper
функция агностик о в wrappee
подписи функции в; то есть он ничего не знает о количестве, позициях, именах и т. д. wrappee
аргументов России; он просто передает все свои аргументы wrappee
, как если бы wrappee
он был первоначально вызван. (Однако нет необходимости связываться со стеком вызовов, чтобы заменить вызов на wrapper
вызов wrappee
.)
Я разместил частичный ответ на мой вопрос:
(defun wrapper (&rest args) (apply 'wrappee args))
Это работает только тогда, когда неwrappee
является интерактивным. Очевидно, способ, которым интерактивные функции получают свои аргументы, представляет собой «канал», отличный от того, что описывается в заклинании. Поэтому мне по-прежнему нужен равноагностический аналог сигнатуры для случая, когда есть интерактивная функция.(&rest args)
wrappee
(&rest args)
wrappee
(Этот вопрос был мотивирован проблемой, описанной в этом предыдущем вопросе .)
В случае, если необходимо дальнейшее разъяснение того, что я запрашиваю, ниже приведены несколько примеров, показывающих эквиваленты Python и JavaScript того, что мне нужно.
В Python пара стандартных способов реализации такой оболочки показана ниже:
def wrapper(*args, **kwargs):
return wrappee(*args, **kwargs)
# or
wrapper = lambda *args, **kwargs: wrappee(*args, **kwargs)
(Здесь *args
означает «все позиционные аргументы» и **kwargs
«все ключевые аргументы».)
Эквивалент JavaScript будет примерно таким:
function wrapper () { return wrappee.apply(this, arguments); }
// or
wrapper = function () { return wrappee.apply(this, arguments); }
Для справки , я не согласен, что этот вопрос является дубликатом Как применить mapcar к функции с несколькими аргументами . Я затрудняюсь объяснить, почему, поскольку эти два вопроса кажутся мне совершенно разными. Это все равно, что спросить: «Объясните, почему яблоко не следует считать эквивалентом апельсина». Простой вопрос настолько сумасшедший, что можно сомневаться в том, что кто-то может придумать ответ, который удовлетворил бы того, кто его спрашивал.
advice
материал достаточно проблематичным, поэтому предпочел бы избежать этого. На самом деле, мотивом для этого вопроса была попытка найти решение неразрешимой проблемы, которую я имею, с помощью рекомендованной функции ...interactive
спецификации.Ответы:
Конечно, это возможно, включая
interactive
спецификацию. Мы имеем дело здесь с elisp ! (Лисп - это язык, где наиболее важными конструкциями являются списки. Вызываемые формы - это просто списки. Поэтому вы можете создавать их по своему усмотрению.)Приложение: Вы хотите добавить некоторые функции к некоторым функциям автоматически. Расширенным функциям должны быть присвоены новые имена, чтобы они
defadvice
не применялись.Во-первых, версия, которая в точности соответствует вашим целям. Мы устанавливаем функцию cell (
fset
) символаwrapper
со всей необходимой информациейwrappee
и добавляем наш дополнительный материал.Это работает для обоих
wrappee
определений. Первая версияwrappee
является интерактивной, вторая - нет.Но удобнее определить макрос, который создает расширенные функции. При этом мы можем даже указать имена функций впоследствии. (Хорошо для автоматической версии.)
После выполнения кода ниже вы можете звонить в
wrapper-interactive
интерактивном иwrapper-non-interactive
неинтерактивном режиме.Обратите внимание, до сих пор я не нашел способ передачи форм объявлений, но это также должно быть возможно.
источник
edebug
. Кроме того, есть функции, гдеinteractive
спецификация значительно больше, чем тело функции. В таких случаях переписываниеinteractive
спецификации может быть довольно утомительным. Вопрос и ответ касаются требуемых принципов.Мне пришлось решить очень похожую проблему
nadvice.el
, поэтому вот решение (которое использует некоторый код из nadvice.el):По сравнению с другими решениями, опубликованными до сих пор, у этого есть преимущество правильной работы, если
wrappee
его переопределить с другой интерактивной спецификацией (то есть он не будет продолжать использовать старую спецификацию).Конечно, если вы хотите, чтобы ваша оболочка была действительно прозрачной, вы можете сделать это проще:
источник
advice-eval-interactive-spec
предложенное здесь, я могу создать интерактивную спецификацию, соответствующую этой динамической оболочке.called-interactively-p
возвратt
вwrappee
? Есть,funcall-interactively
но нетapply-interactively
(apply #'funcall-interactively #'wrappee args)
если хотите. Но делать это нужно только в том случае, если функция вызывается интерактивно, так что-то вроде(apply (if (called-interactively-p 'any) #'funcall-interactively #'funcall) #'wrappee args)
.редактировать: ответ Тобиаса лучше, чем это, так как он получает точную интерактивную форму и строку документации обернутой функции.
Комбинируя ответы Аарона Харриса и Кджо, вы можете использовать что-то вроде:
Применение:
Вызовите упаковщик с одним из:
M-x
wrapper-func
источник