Como defalias lambda?

8

Eu tenho isso no meu .emacs:

(defalias 'λ 'lambda)

o que funciona bem para coisas simples como (funcall (λ (x) x) 1).

Mas quando faço algo como (org-add-link-type "foo" (λ (s) (message s)))ou (add-to-list 'auto-mode-alist '("foo" . (λ () (message "bar")))), não funciona e recebo

org-open-at-point: Função inválida: (λ (s) (mensagem (s))

e

Erro de especificação do modo de arquivo: (função inválida (λ nil (mensagem "barra"))))

respectivamente.

Alguém sabe o que há de errado aqui?

rtrn
fonte
4
Não é uma resposta à pergunta sobre o defalias, mas você pode querer verificar para fora prettify-symbols-mode, o que, entre outras coisas, permitirá que você exibir lambdacomo λsem realmente mudar o texto subjacente.
Dan
Uma simples biblioteca que prettifies única lambda (a λ): pretty-lambdada.el.
Tirou
Se você quiser apenas símbolos bonitos, use github.com/akatov/pretty-mode
grettke

Respostas:

11

Com alguma ajuda de lunaryorn no reddit , acho que consegui entender por que você está observando o comportamento "estranho".

O problema é que você está citando a expressão

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

Que é equivalente ao formulário

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

Agora, quando o emacs abre um arquivo com a extensão "foo", ele faz algo como o seguinte

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

Observe a cotação extra, antes , isso obviamente não é uma função válida e você obtém o erro. Invalid function: ... Mas por que ("foo" . (lambda () (message "bar")))funciona, isso é explicado pela observação de lunaryorn

Uma “lista lambda”, ou seja, uma lista cujo carro é lambda, também é uma função válida

Portanto, '(lambda () (message "bar"))é uma função válida, que pode ser verificada pelo seguinte código

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

Portanto, a solução seria simplesmente não citar a expressão, use o seguinte

(add-to-list 'auto-mode-alist (cons "foo" (λ () (bar))))
Iqbal Ansari
fonte
Obrigado pela explicação completa! Funcionando bem de tudo agora :)
RTRN
3

Parece que o problema não está no defalias, mas onde e como você está ligando λ. funcallusa, como argumentos, uma função e os argumentos dessa função; portanto, seu funcallexemplo funciona perfeitamente.

Ambos org-add-link-typee auto-mode-alist, no entanto, esperam símbolos que contenham as funções relevantes. Portanto, com base nos seus exemplos, o seguinte deve funcionar:

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

Se você está procurando principalmente para ter λaparecer em seu buffer, considerar a experimentar prettify-symbols-mode, que irá mostrar lambdacomo λsem alterar texto th do buffer.

Dan
fonte
O estranho é que tudo funciona bem quando eu uso lambdadiretamente.
RTRN
@ rtrn: ah, bom ponto. Acho que é porque a lambdamacro retorna um lambdaformulário especial auto-citado , que o alias não está captando, mas pode haver mais magia negra aqui. Convocar @Malabarba.
Dan