OVH Cloud OVH Cloud

elisp: interactive et concat

7 réponses
Avatar
Benoit Izac
Bonjour,

Ce qui marche :
(interactive "sfoo: \nsbar: ")
(interactive "sfoo:
sbar: ")

En revanche, je pensais naïvement que je pouvais faire :
(interactive (concat "sfoo: \n"
"sbar: "))

Mais j'ai le droit à :

Debugger entered--Lisp error: (wrong-type-argument listp "sfoo:
sbar: ")
call-interactively((lambda (&rest args) (interactive (concat "sfoo: \n" "sbar: ")) args))
eval((call-interactively (quote (lambda ... ... args))))
eval-last-sexp-1(nil)
eval-last-sexp(nil)
call-interactively(eval-last-sexp)


Pourquoi ?

Merci.
--
Benoit Izac

7 réponses

Avatar
Bastien
Benoit Izac writes:

En revanche, je pensais naïvement que je pouvais faire :
(interactive (concat "sfoo: n"
"sbar: "))



Ce qui vient après (interactive ...) est un argument spécial -
ARG-DESCRIPTOR dans ce qui suit.

,----[ (info "(elisp)Using interactive") ]
| There are three possibilities for the argument ARG-DESCRIPTOR:
|
| * It may be omitted or `nil'; then the command is called with no
| arguments. This leads quickly to an error if the command requires
| one or more arguments.
|
| * It may be a Lisp expression that is not a string; then it should
| be a form that is evaluated to get a list of arguments to pass to
| the command.
|
| [...]
|
| * It may be a string; then its contents should consist of a code
| character followed by a prompt (which some code characters use and
| some ignore). The prompt ends either with the end of the string
| or with a newline. Here is a simple example:
|
| (interactive "bFrobnicate buffer: ")
`----

C'est seulement dans le troisième cas que tu as le droit d'utiliser
les lettre come `s' ou `b' pour spécifier le type de variable attendu
dans le minibuffer. Ce que tu as essayé de faire correspond au
deuxième cas.

--
Bastien
Avatar
Benoit Izac
Bonjour,

le 11/04/2006 à 19:08, Bastien a écrit
dans le message :

(interactive (concat "sfoo: n"
"sbar: "))



| * It may be a Lisp expression that is not a string; then it should
| be a form that is evaluated to get a list of arguments to pass to
| the command.



C'est subtile... Je pensais que (concat ...) était évalué _avant_ d'être
passé en argument comme c'est le cas généralement (enfin c'est ce que
j'avais cru lire quelque part).

C'est fréquent des fonctions comme ça ?

--
Benoit Izac
Avatar
Bastien
Benoit Izac writes:

(interactive (concat "sfoo: n"
"sbar: "))





| * It may be a Lisp expression that is not a string; then it should
| be a form that is evaluated to get a list of arguments to pass to
| the command.



C'est subtile... Je pensais que (concat ...) était évalué _avant_ d'être
passé en argument



Mais si tu pensais ça, alors pourquoi avoir mis le `s' dans "sfoo:n"?

Anyway, la page d'info que j'ai indiquée est vraiment très utile. Par
exemple le passage sur ce qu'il ne faut *pas* faire quand on veut
passer une région du buffer en argument - ce n'est pas évident...

--
Bastien
Avatar
Benoit Izac
Bonjour,

le 11/04/2006 à 19:53, Bastien a écrit
dans le message :

(interactive (concat "sfoo: n"
"sbar: "))





| * It may be a Lisp expression that is not a string; then it
| should be a form that is evaluated to get a list of arguments
| to pass to the command.



C'est subtile... Je pensais que (concat ...) était évalué _avant_
d'être passé en argument



Mais si tu pensais ça, alors pourquoi avoir mis le `s' dans "sfoo:n"?



Ça n'a aucun rapport avec ma question initiale (il me semble). J'ai mis
un « s » c'est car j'ai fait un « C-h f interactive » et que j'ai lu :
| The argument of `interactive' is usually a string containing a code
| letter followed by a prompt.
[...]
| s -- Any string. Does not inherit the current input method.

Sur cette même page, on peut effectivement lire :
| If the argument is not a string, it is evaluated to get a list of
| arguments to pass to the function.

Comme je pensais que (concat ...) était évalué avant (sic) et que le
résultat était bien une string :
(type-of (concat "foo" "bar")) -> renvoie string
je pensais être dans le cas d'une chaîne.

D'où ma question sur le sens d'évaluation que je ne saisis plus trop ;
pour moi, lorsque l'interpréteur rencontre l'expression suivante
« (* 7 (+ 1 5)) », il évalue d'abord « (+ 1 5) » puis « (* 7 6) ».

Or ici, ça semble différent. Pourquoi (et comment) ?

Anyway, la page d'info que j'ai indiquée est vraiment très utile. Par
exemple le passage sur ce qu'il ne faut *pas* faire quand on veut
passer une région du buffer en argument - ce n'est pas évident...



Je compte bien la lire mais mon premier réflexe est souvent de faire
« C-h f ... » qui est rapide et dans la plupart des cas suffisant.

--
Benoit Izac
Avatar
lhabert
Benoit Izac :

C'est subtile... Je pensais que (concat ...) était évalué _avant_ d'être
passé en argument comme c'est le cas généralement (enfin c'est ce que
j'avais cru lire quelque part).

C'est fréquent des fonctions comme ça ?



Ça s'appelle une forme spéciale. C'est comme « if » ou « defun ». C'est
expliqué dans la doc.
Avatar
Bastien
Benoit Izac writes:

Comme je pensais que (concat ...) était évalué avant (sic) et que le
résultat était bien une string :
(type-of (concat "foo" "bar")) -> renvoie string
je pensais être dans le cas d'une chaîne.



Oui, mais en suivant ta logique jusqu'au bout, tu aurais du t'attendre
à ce que ça concatène "sFoo:n" et "sBar:" en "sFoo:nsBar" avant
d'être interprété par (interactive ...). Or le "s" n'a de sens que
lorsqu'il est *directement* traité par (interactive ...).

D'où ma question sur le sens d'évaluation que je ne saisis plus trop ;
pour moi, lorsque l'interpréteur rencontre l'expression suivante
« (* 7 (+ 1 5)) », il évalue d'abord « (+ 1 5) » puis « (* 7 6) ».



Exact.

Or ici, ça semble différent. Pourquoi (et comment) ?



Ce n'est pas si différent. Il interprète d'abord ARG-DESCRIPTOR et le
passe à (interactive ...). Mais quand ARG-DESCRIPTOR n'est pas une
chaîne, il attend une *liste* d'argument. Or (concat ...) renvoie une
chaîne, pas une liste.

(defun ...
(interactive (list (concat "a" "b"))
...)

passe la liste ("ab") à interactive, qui le passera en argument de
defun.

Je compte bien la lire mais mon premier réflexe est souvent de faire
« C-h f ... » qui est rapide et dans la plupart des cas suffisant.



Oui... mais on a vite fait besoin de la doc!

--
Bastien
Avatar
Pascal Bourguignon
Benoit Izac writes:

Bonjour,

le 11/04/2006 à 19:08, Bastien a écrit
dans le message :

(interactive (concat "sfoo: n"
"sbar: "))





| * It may be a Lisp expression that is not a string; then it should
| be a form that is evaluated to get a list of arguments to pass to
| the command.



C'est subtile... Je pensais que (concat ...) était évalué _avant_ d'être
passé en argument comme c'est le cas généralement (enfin c'est ce que
j'avais cru lire quelque part).

C'est fréquent des fonctions comme ça ?



Non, des _fonctions_ comme ça, ça n'existe pas.

Mais des opérateurs spéciaux comme ça, ou des macros comme ça, c'est
assez courant:

interactive is a special form in `C source code'.
^^^^^^^^^^^^

Quand on voit "special form" (ou "macro"), il faut faire SPECIALement
attention aux règles d'évaluation des arguments.


--
__Pascal Bourguignon__ http://www.informatimago.com/

THIS IS A 100% MATTER PRODUCT: In the unlikely event that this
merchandise should contact antimatter in any form, a catastrophic
explosion will result.