OVH Cloud OVH Cloud

caractere # mystérieux

7 réponses
Avatar
Francois Maltey
Bonjour,

Je recherchais le code de read-buffer-name dans xemacs parce qu'il
fait à peu près ce que je veux, et découvre le caractère #, employé deux fois

...
(mapcar #'(lambda (buf) (list (buffer-name buf))) (buffer-list))
;; don't take buffers that start with a blank
#'(lambda (list) (not (eq (aref (car list) 0) ? )))

A quoi sert donc le # ?

Bien cordialement.

François

7 réponses

Avatar
drkm
Francois Maltey writes:

#'(lambda (list) (not (eq (aref (car list) 0) ? )))

A quoi sert donc le # ?



,----[ (info (elisp)Anonymous Functions) ]
| The read syntax `#'' is a short-hand for using
| `function'. For example,
|
| #'(lambda (x) (* x x))
|
| is equivalent to
|
| (function (lambda (x) (* x x)))
|
| -- Special Form: function function-object
| This special form returns FUNCTION-OBJECT without
| evaluating it. In this, it is equivalent to `quote'.
| However, it serves as a note to the Emacs Lisp
| compiler that FUNCTION-OBJECT is intended to be used
| only as a function, and therefore can safely be
| compiled. Contrast this with `quote', in *Note
| Quoting::.
`----

Mais il me semble avoir vu que 'lambda' impliquait déjà
'function', et qu'il était dans ce cas plus néfaste qu'autre
chose d'utiliser 'function'. C'est lié, je pense, au fait qu'il
ne faut pas quoter les lambdas expressions :

,----[ C-h f lambda RET ]
| (lambda args [docstring] [interactive] body)
|
| Return a lambda expression.
| A call of the form (lambda args docstring interactive body)
| is self-quoting; the result of evaluating the lambda
| expression is the expression itself.
`----

--drkm
Avatar
Pascal Bourguignon
Francois Maltey writes:

Bonjour,

Je recherchais le code de read-buffer-name dans xemacs parce qu'il
fait à peu près ce que je veux, et découvre le caractère #, employé deux fois

...
(mapcar #'(lambda (buf) (list (buffer-name buf))) (buffer-list))
;; don't take buffers that start with a blank
#'(lambda (list) (not (eq (aref (car list) 0) ? )))

A quoi sert donc le # ?



À rien. lambda est une macro qui se dévelope en (function (lambda ...))

(macroexpand '(lambda (x) x)) C-u C-x C-e
--> (function (lambda (x) x))

Il est donc totalement inutile, et vachement laid, d'écrire #'(lambda ...)
D'ailleurs, je préfère toujours écrire (function x) plutôt que #'x.

--
__Pascal Bourguignon__ http://www.informatimago.com/
I need a new toy.
Tail of black dog keeps good time.
Pounce! Good dog! Good dog!
Avatar
Matthieu Moy
drkm writes:

Mais il me semble avoir vu que 'lambda' impliquait déjà
'function', et qu'il était dans ce cas plus néfaste qu'autre
chose d'utiliser 'function'.



Use the source, Luke, ...

(defmacro lambda (&rest cdr)
"[...]"
(list 'function (cons 'lambda cdr)))

En fait, comme expliqué dans la doc que tu cites, #'(lambda ...) et
(lambda ...) autorise le compilo à byte-compiler le contenu de la
fonction, ce qui a deux avantages :

1) Ça va plus vite que du code non compilé

2) Les macros sont expansées à la compilation, ce qui permet de ne pas
charger certains packages à l'exécution. Typiquement, on peut
souvent ne mettre qu'un (eval-when-compile (require 'cl)) à la
place d'un (eval-and-compile (require 'cl)).

--
Matthieu
Avatar
drkm
Matthieu Moy writes:

drkm writes:

Mais il me semble avoir vu que 'lambda' impliquait déjà
'function', et qu'il était dans ce cas plus néfaste qu'autre
chose d'utiliser 'function'.



Use the source, Luke, ...



Je ne sais pas où j'ai été cherché ça. J'ai sans doute
confondu avec le fait de quoter (avec quote) la fonction :

'(lambda () ...)

ce qui, si je ne m'abuse, empêche sa compilation (puisqu'il
s'agit d'une simple liste).

--drkm
Avatar
Matthieu Moy
drkm writes:

Matthieu Moy writes:

drkm writes:



Mais il me semble avoir vu que 'lambda' impliquait déjà
'function', et qu'il était dans ce cas plus néfaste qu'autre
chose d'utiliser 'function'.





Use the source, Luke, ...



Je ne sais pas où j'ai été cherché ça. J'ai sans doute
confondu



Ben non, tu avais raison. Dans le bout de code que je cite (pour
étayer tes propos, pas pour les contredire), y'a bien le 'function.

En résumé :

#'(lambda ...) => bien, mais compliqué
'(lambda ...) => mal
(lambda ...) => bien et simple.

--
Matthieu
Avatar
drkm
Matthieu Moy writes:

Ben non, tu avais raison.

#'(lambda ...) => bien, mais compliqué



Ben non, je n'avais pas raison. Je pensais justement que
l'utilisation de 'function' (et non seulement de 'quote') était
un problème avec 'lambda'.

--drkm, que si, il avait tord ;-)
Avatar
Pascal Bourguignon
Matthieu Moy writes:
En résumé :

#'(lambda ...) => bien, mais compliqué
'(lambda ...) => mal
(lambda ...) => bien et simple.



Oui. Mais '(lambda ...) n'est pas forcément mal. Ça dépend de ce
qu'on veut faire.

(defun dessine-moi-un-mouton ()
(lambda (x) (list x x x x))) ; un mouton a quatre pattes.
(byte-compile 'dessine-moi-un-mouton)
(caddr (dessine-moi-un-mouton))
--> Debugger entered--Lisp error: (wrong-type-argument listp #[(x) "‰‰‰F‡" [x] 4])
(funcall (dessine-moi-un-mouton) 'patte)
--> (patte patte patte patte)

(defun dessine-moi-un-mouton ()
(quote (lambda (x) (list x x x x)))) ; un mouton a quatre pattes.
(byte-compile 'dessine-moi-un-mouton)
(caddr (dessine-moi-un-mouton))
--> (list x x x x)
(funcall (dessine-moi-un-mouton) 'patte)
--> (patte patte patte patte)


Ainsi, si ce qu'on veut, c'est manipuler le source de la fonction
annonyme, il vaut mieux la quoter pour la traiter comme des données,
alors que si ce qu'on veut c'est l'exécuter, il vaut mieux ne pas la
quoter. Ensuite, comme emacs lisp est un interpréteur, il arrive à se
débrouiller avec une lambda list, mais ça ne marcherait pas en
Common Lisp par exemple.


[245]> (defun dessine-moi-un-mouton ()
(quote (lambda (x) (list x x x x)))) ; un mouton a quatre pattes.

DESSINE-MOI-UN-MOUTON
[246]> (compile 'DESSINE-MOI-UN-MOUTON)
DESSINE-MOI-UN-MOUTON ;
NIL ;
NIL
[247]> (caddr (dessine-moi-un-mouton))
(LIST X X X X)
[248]> (funcall (dessine-moi-un-mouton) 'patte)

*** - FUNCALL: argument (LAMBDA (X) (LIST X X X X)) is not a function.
To get a function in the current environment, write (FUNCTION ...).
To get a function in the global environment, write (COERCE '...
'FUNCTION).
The following restarts are available:
ABORT :R1 ABORT
Break 1 [249]>




(defun dessine-moi-un-mouton-a-cinq-pattes ()
(let ((mouton (copy-tree (dessine-moi-un-mouton))))
(push (cadr (caddr mouton)) (cdr (caddr mouton)))
mouton))

(dessine-moi-un-mouton-a-cinq-pattes)
--> (lambda (x) (list x x x x x))

(funcall (dessine-moi-un-mouton-a-cinq-pattes) 'patte)
--> (patte patte patte patte patte)

(dessine-moi-un-mouton)
--> (lambda (x) (list x x x x))

(funcall (dessine-moi-un-mouton) 'patte)
--> (patte patte patte patte)


--
__Pascal Bourguignon__ http://www.informatimago.com/
Our enemies are innovative and resourceful, and so are we. They never
stop thinking about new ways to harm our country and our people, and
neither do we. -- Georges W. Bush