В AutoLISP возможно ли получить имя функции в теле функции?

В указанных условиях я хочу напечатать имя функции в этой функции. но я не знаю, как его получить. В C++ я могу использовать макрос препроцессора __FUNCTION__. И что-то похожее в AutoLISP?


person CAD Developer    schedule 29.03.2016    source источник
comment
Поддерживает ли autolisp (лисп) макросы?   -  person Daniel Jour    schedule 29.03.2016
comment
@DanielJour: я не думаю, что это так (хотя вы, вероятно, могли бы реализовать для него систему макросов).   -  person    schedule 30.03.2016
comment
Я работаю с AutoLISP уже несколько лет, но никогда не встречал лисповских макросов. Что вы подразумеваете под макросами в lisp? Любой пример?   -  person CAD Developer    schedule 30.03.2016
comment
Макросы @CADDeveloper Lisp являются одной из особенностей, которые, как считается, делают его таким мощным языком. Комментарий слишком мал для хорошего ответа, но дело в том, что вы можете изменить исходный код во время части процесса компиляции. Например, в Common Lisp макрос with-open-file превращает (with-open-file (x "/tmp/foo") ...) во что-то вроде (let ((x (open "/tmp/foo")) (unwind-protect (progn ...) (close x))). Я думаю, дело здесь в том, что вы можете написать макрос на Common Lisp, такой как defunx, который превратит (defunx name (...) ...) во что-то вроде...   -  person Joshua Taylor    schedule 30.03.2016
comment
... (defun name (...) (let ((__function__ 'name)) ...)), что дало бы вам эффект, аналогичный тому, что вы могли бы получить в C.   -  person Joshua Taylor    schedule 30.03.2016
comment
Беглый взгляд на руководство по AutoLisp не показывает очевидного defmacro, что меня удивляет, потому что в XLisp он есть. На странице Википедии для AutoLisp говорится ... отсутствуют такие обычные функции LISP, как система макросов, ... поэтому я подозреваю, что макросов нет.   -  person Vatine    schedule 31.03.2016
comment
Итак, у нас нет макросов. Но я до сих пор не понимаю, как макросы могут помочь получить имя функции. Какую идею мы можем получить с помощью макросов? Я думаю, что только один из них - определить функцию, и одна из локальных переменных может быть именем   -  person CAD Developer    schedule 31.03.2016
comment
@caddeveloper Я пытался показать это в своих предыдущих комментариях. Если бы у вас была система макросов, вы могли бы определить функцию, определяющую макрос, который определял бы функции с доступом к их собственным именам.   -  person Joshua Taylor    schedule 31.03.2016
comment
Если я правильно понимаю, я могу получить аналогичный эффект с помощью текстового редактора. Я использую Notepad++ и сниппеты. (defun example () (setq __FUNCTION__ "example" ) (print (strcat "this is the name of my function: " __FUNCTION__) ) ) Может быть, это может быть какое-то решение Спасибо всем за помощь   -  person CAD Developer    schedule 31.03.2016
comment
@cadDeveloper Я не знаком с AutoLisp, но, вероятно, это должно быть (let ((__function__ ...)) ...), а не setq. Вы, вероятно, не хотите, чтобы функция была глобальной...   -  person Joshua Taylor    schedule 31.03.2016
comment
да __function__ должен быть локальным, но он должен быть setq, потому что в AutoLISP у нас нет let   -  person CAD Developer    schedule 01.04.2016


Ответы (1)


Это определенно возможно. Рассмотрим две ситуации:

1) Вы пишете функцию.

Это должно быть легко, просто определите переменную с тем же именем, что и у функции, и все готово. (Как обсуждалось в комментариях выше.)

Вы даже можете использовать что-то более описательное, чем фактическое имя функции. (defun af () ...) можно было бы назвать "Потрясающая функция" вместо "af".

Я бы также рекомендовал использовать стандартное форматирование постоянных значений: заглавные буквы с подчеркиванием для разделения слов. (setq FUNCTION_NAME "AwesomeFunction"). (Это точно так же, как PI, которое установлено для вас, и вы не должны его менять — это константа.)

2) Вы вызываете функцию, название которой вы можете не знать, пока код не запустится.

Некоторые примеры этого:

(apply someFunctionInThisVariable '(1 2 3))

(mapcar 'printTheNameOfAFunction '(+ setq 1+ foreach lambda))

(eval 'anotherFunctionInAVariable)

Чтобы напечатать имя функции, хранящейся в переменной, например, (setq function 'myFunction), вам нужно использовать функцию (vl-princ-to-string).

(vl-princ-to-string function)   ;; Returns "MYFUNCTION"
(strcase (vl-princ-to-string function) T)   ;; Returns "myfunction"

(princ
   (strcase 
      (vl-princ-to-string function)
      T
   )
)            ;; Command line reads: myfunction

Функцию (vl-princ-to-string) можно использовать для любого печатаемого типа, и она всегда будет возвращать строку. Это здорово, если вы не знаете, есть ли у вас число или слово и т. д.

Надеюсь, это поможет!

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

person J.D. Sandifer    schedule 27.07.2016
comment
Я не понимаю, почему это помечено как ответ. В любом случае упоминается, что не существует волшебного метода для получения имени функции. Вы должны как-то это обеспечить. Возможно, это все, чего хотел CAD Developer. - person Tom Haws; 08.03.2017
comment
Функция должна быть предоставлена ​​где-то в переменной или аргументе, чтобы вы могли ее использовать, верно? Во втором примере выше показано, как получить доступ к имени предоставленной функции, не зная его заранее. Или вы думаете, что оператор спрашивал что-то еще? - person J.D. Sandifer; 15.03.2017
comment
Что ж, в C ++ _ _ F U N C T I O N _ _ имеет имя функции, в которой вы находитесь. Я предположил, что это то, о чем просил ОП. Я, честно говоря, понятия не имею, что еще можно было иметь в виду. - person Tom Haws; 16.03.2017
comment
Согласно этой документации, __FUNCTION__ рассматривается как константа, определенная в верхней части функции, как в ответе 1 выше. Я могу понять, что копирование может сэкономить время, а не печатать имена функций, но даже в примере на этой странице было бы проще ввести имя функции, а не __FUNCTION__. Ответ выше может потребовать немного больше работы, но он создает ту же функциональность: возможность использовать имя функции, внутри которой вы находитесь. - person J.D. Sandifer; 23.03.2017
comment
Я думаю, вы упускаете из виду всю суть __FUNCTION__ или __func__ . Идентификатор __func__ неявно объявляется переводчиком как будто.... (курсив добавлен мной). - person Tom Haws; 24.03.2017