Comment défalias lambda?

8

J'ai ceci dans mon .emacs:

(defalias 'λ 'lambda)

qui fonctionne bien pour des choses simples comme (funcall (λ (x) x) 1).

Mais quand je fais quelque chose comme (org-add-link-type "foo" (λ (s) (message s)))ou (add-to-list 'auto-mode-alist '("foo" . (λ () (message "bar")))), ça ne marche pas et je reçois

org-open-at-point: fonction non valide: (λ (s) (message s))

et

Erreur de spécification du mode fichier: (fonction invalide (λ nil (message "bar"))))

respectivement.

Quelqu'un sait-il ce qui ne va pas ici?

rtrn
la source
4
Pas une réponse à la question sur le defalias, mais vous voudrez peut-être vérifier prettify-symbols-mode, ce qui, entre autres, vous permettra d'afficher lambdacomme λsans réellement changer le texte sous-jacent.
Dan
Une bibliothèque simple qui enjolive seulement lambdaλ): pretty-lambdada.el.
Drew
Si vous voulez juste de jolis symboles, utilisez github.com/akatov/pretty-mode
grettke

Réponses:

11

Avec l'aide de lunaryorn sur reddit , je suppose que j'ai pu comprendre pourquoi vous observez le comportement "bizarre".

Le problème est que vous citez l'expression

'("foo" . (λ () (message "bar")))

Ce qui équivaut à la forme

(cons "foo" '(λ () (message "bar")))

Maintenant, quand emacs ouvre un fichier avec l'extension "foo", il fait quelque chose comme ceci

(funcall '(λ () (message "bar")))

Remarquez la citation supplémentaire, avant , ce n'est évidemment pas une fonction valide et vous obtenez l'erreur Invalid function: ... Mais alors pourquoi ça ("foo" . (lambda () (message "bar")))marche, cela s'explique par l'observation de lunaryorn

Une «liste lambda», c'est-à-dire une liste dont la voiture est lambda, est également une fonction valide

'(lambda () (message "bar"))Est donc une fonction valide, cela peut être vérifié par le code suivant

(functionp (lambda () "hello"))  => t
(functionp (λ () "hello"))       => t
(functionp '(lambda () "hello")) => t
(functionp '(λ () "hello"))      => nil

La solution serait donc de ne pas citer simplement l'expression à la place

(add-to-list 'auto-mode-alist (cons "foo" (λ () (bar))))
Iqbal Ansari
la source
Merci pour l'explication approfondie! Tout fonctionne bien maintenant :)
rtrn
3

Il semble que le problème ne soit pas avec le defalias, mais plutôt où et comment vous appelez λ. funcallprend, comme arguments, une fonction et les arguments de cette fonction, donc votre funcallexemple fonctionne très bien.

Les deux org-add-link-typeet le auto-mode-alist, cependant, attendent des symboles qui contiennent les fonctions pertinentes. Par conséquent, à partir de vos exemples, les éléments suivants devraient fonctionner:

(defun a-silly-fnx (s)
  (message s))
(defalias #'my-link-alias #'a-silly-fnx)
(org-add-link-type "foo" #'my-link-alias)

(defun a-tester-fnx ()
  (message "Testing!")
  (sit-for 2))
(defalias #'my-alist-alias #'a-tester-fnx)
(add-to-list 'auto-mode-alist '("foo" . my-alist-alias))

Si vous cherchez surtout à λapparaître dans votre tampon, pensez à essayer prettify-symbols-mode, qui s'affichera lambdacomme λsans changer le texte du tampon.

Dan
la source
La chose étrange est que tout fonctionne bien lorsque j'utilise lambdadirectement.
rtrn
@rtrn: ah, bon point. Je suppose que c'est parce que la lambdamacro renvoie une lambdaforme spéciale auto-citée que l'alias ne reprend pas, mais il pourrait y avoir plus de magie noire ici. Invoquez @Malabarba.
Dan