OVH Cloud OVH Cloud

problème de lisp

8 réponses
Avatar
Sébastien Kirche
Bonsoir,

ce soir j'ai fait du ménage dans mes archives de mail et après avoir
bataillé de longues heures, j'arrive enfin à avoir un archivage dans
Gnus des messages sortants séparé mail/news au format nnml
(1 msg = 1 fichier) et dans le répertoire de mon choix.

Rigolez pas, ça a l'air simple à dire, mais jusqu'à maintenant il avait
choisi le format nnfolder (1 fichier = 1 groupe) et je n'arrivais pas à
le changer.

Pour ceux que ça peut intéresser, ça donne le paramétrage suivant :
(setq gnus-secondary-select-methods
'(
;;...
;; (autres serveurs)
;;...
(nnml "archives"
(nnml-directory "/home/seki/.gnus.d/archives")
(nnml-active-file "/home/seki/.gnus.d/archives/active")
(nnml-inhibit-expiry t)
(nnml-get-new-mail nil))
))
(setq gnus-message-archive-group
'((if (message-news-p)
(concat "nnml+archives:News-sent." (format-time-string "%Y-%m"))
(concat "nnml+archives:Mail-sent." (format-time-string "%Y-%m"))
)))

Tout semble fonctionner correctement.
Seulement pendant mes essais j'ai essayé de paramétrer la valeur de
nnml-directory à (concat gnus-home-directory "/archives/active") et ça
explose au lancement de Gnus avec le backtrace suivant (excusez les
lignes trop longues) :

Debugger entered--Lisp error: (wrong-type-argument stringp (function (concat gnus-home-directory "/archives/active")))
insert-file-contents((function (concat gnus-home-directory "/archives/active")))
byte-code("bytecode supprimé" [nnmail-file-coding-system nnmail-pathname-coding-system file-name-coding-system auto-mode-alist coding-system-for-read file mm-auto-mode-alist insert-file-contents t] 3)
nnmail-find-file((function (concat gnus-home-directory "/archives/active")))
nnml-request-list("archives")
gnus-request-list((nnml "archives"))
gnus-read-active-file-1((nnml "archives") nil)
gnus-read-active-file(nil nil)
gnus-setup-news(nil nil nil)
byte-code("j'ai viré le bytecode à la citation" [dont-connect did-connect gnus-startup-file gnus-current-startup-file gnus-slave gnus-use-dribble-file gnus-group-quit gnus-run-hooks gnus-startup-hook gnus-make-newsrc-file gnus-dribble-read-file gnus-request-create-group "queue" (nndraft "") "drafts" (nndraft "") gnus-setup-news nil gnus-setup-news-hook gnus-start-draft-setup gnus-group-list-groups gnus-group-first-unread-group gnus-configure-windows group gnus-group-set-mode-line gnus-started-hook gnus-agent level] 4)
gnus-1(nil nil nil)
gnus(nil)
call-interactively(gnus)
execute-extended-command(nil)
call-interactively(execute-extended-command)


Je ne comprends pas pourquoi je ne peux pas utiliser le concat, ou
comment ça doit s'écrire si c'est possible. C'est à cause du quotage de
la liste des serveurs : il prend le tout comme une chaîne sans
interpréter ?

Un tuyau de la part de nos lisp power users ?

--
Sébastien Kirche

8 réponses

Avatar
Pascal Bourguignon
Sébastien Kirche writes:
nnmail-find-file((function (concat gnus-home-directory "/archives/active")))

Je ne comprends pas pourquoi je ne peux pas utiliser le concat, ou
comment ça doit s'écrire si c'est possible. C'est à cause du quotage de
la liste des serveurs : il prend le tout comme une chaîne sans
interpréter ?

Un tuyau de la part de nos lisp power users ?



Tu peux l'utiliser, mais tu _dois_ l'utiliser. Pas seulement le _nommer_!

En lisp, comme c'est de la programmation _symbolique_, les symboles
d'un programme peuvent être évalués, ou non. Le programmeur indique
quelles parties d'un programme doivent ne pas être évalués, c'est à
dire, doivent être considérés comme des données avec les opérateurs
spéciaux quote, ou function.

(list 1 (+ 1 1) (+ 1 1 1))

est un programme qui lorsqu'il s'exécute, appelle la fonction list, en
lui passant trois arguments: les résultats de l'évaluation des trois
expressions 1, (+ 1 1) et (+ 1 1 1), soit 1, 2 et 3; laquelle fonction
va construire une liste contenant ces arguments [en faisant: (cons 1
(cons 2 (cons 3 nil))) ] et la retourner: (1 2 3)


(quote (list 1 2 3))

est un programme qui lorsqu'il s'exécute, remarque que quote est un
opérateur spécial qui retourne son argument sans l'évaluer; il
retourne donc la donnée, la liste qui contient le symbole list, le
nombre 1, le nombre 2 et le nombre 3: (list 1 2 3)

(function sin)
(function (lambda (x) (* x x)))

sont des programmes qui lorsqu'ils s'exécutent, remarquent que
function est un opérateur spécial qui fonctionne sur emacs exactement
comme quote (sauf que si on compile ces programme, le compilateur
compilera aussi les fonctions passées en argument de function au lieu
de les traiter comme une simple donnée comme quote.


Avec un vrai language de programmation, comme Common Lisp, le langage
détecterait que:

(function (concat gnus-home-directory "/archives/active"))

est une erreur:

--> *** - FUNCTION: (CONCAT GNUS-HOME-DIRECTORY "/archives/active") is not a
function name; try using a symbol instead

Mais pour un jouet comme emacs lisp, comme function est comme quote,

(function (concat gnus-home-directory "/archives/active"))

retourne simplement la donnée, la liste:

--> (concat gnus-home-directory "/archives/active")

sans l'évaluer, comme le ferait quote.


Si tu veux obtenir le résultat de la concaténation, il ne faut pas
"quoter" avec function ton expression, ce qui de toutes façon est
invalide:

(funcall (function (concat gnus-home-directory "/archives/active")))

--> Debugger entered--Lisp error: (invalid-function (concat gnus-home-directory "/archives/active"))



(function (concat gnus-home-directory "/archives/active"))

--> (concat gnus-home-directory "/archives/active")


(concat gnus-home-directory "/archives/active")

--> "~//archives/active"


Donc enlève ce function, est ça devrait fonctionner...


--
__Pascal Bourguignon__ http://www.informatimago.com/
The mighty hunter
Returns with gifts of plump birds,
Your foot just squashed one.
Avatar
drkm
Sébastien Kirche writes:

C'est à cause du quotage de
la liste des serveurs : il prend le tout comme une chaîne sans
interpréter ?



C'est un peu ça. Sauf qu'il ne s'agit pas de chaînes de
caractères (pas seulement), mais de symboles, chaînes, etc.

Un tuyau de la part de nos lisp power users ?



Yep :

(setq gnus-secondary-select-methods
`((nnml "archives"
(nnml-directory ,(concat ... "..."))
(nnml-active-file "/home/seki/.gnus.d/archives/active")
(nnml-inhibit-expiry t)
(nnml-get-new-mail nil))))

Remarque que j'utilise une backquote « ` » au lieu d'une quote
normale « ' », ainsi qu'une virgule. L'explication, c'est qu'une
backquote quote comme une quote (à prononcer très vite), sauf les
élements précédés d'une virgule, qui sont eux évalués.

Dans le cas :

'(nnml (concat sym "str"))

tu obtiens une liste constituée de deux éléments. Le symbole
« nnml » et une liste. Elle-même contient trois éléments : le
symbole « concat », le symbole « sym » et la chaîne "str".

La chaîne, théoriquement, est quotée. Mais les chaînes de
caractères sont automatiquement quotées. Il n'y a pas de
différence entre une chaîne quotée ou non (je pense que
l'explication exacte est qu'une chaîne s'évalue en elle-même).
Il y a quelques autres types qui s'évaluent en eux-mêmes.

Dans le cas :

`(nnml ,(concat sym "str"))

tu obtiens une liste constituée de deux éléments. Le symbole
« nnml », toujours, et une chaîne de caractères, résultat de
l'évaluation de la concaténation (entre la valeur de la variable
« sym » et la chaîne "str").

Note que si tu enlèves la virgule, tu te retrouves exactement
dans le même cas que précédemment.

Enfin, j'espère que c'est bien la solution. Je n'ai pas
réellement investigué, et je ne sais pas d'où vient le
« function » dans le backtrace.

--drkm
Avatar
drkm
Pascal Bourguignon writes:

Si tu veux obtenir le résultat de la concaténation, il ne faut pas
"quoter" avec function ton expression



Mmh. Sébastien a dit avoir tenté de fixer 'nnml-directory' à
(concat gnus-home-directory "/archives/active"). Il n'a pas
parlé de 'function'. Par 'nnml-directory', j'imagine qu'il parle
de la valeur associée à cette entrée dans une sous-liste de
'gnus-secondary-select-methods'.

Mais il est vrai que je ne m'explique pas ce 'function'. Ce
serait évidemment l'explication la plus évidente. Sébastien,
as-tu fait cette bêtise ?-).

Si je comprend bien le problème, il a essayé d'évaluer le
'concat' dans la liste au moyen de 'function', comme ceci :

(setq gnus-secondary-select-methods
'((nnml "archives"
(nnml-directory (function (concat gnus-home-directory
"/archives/active")))
(nnml-active-file "/home/seki/.gnus.d/archives/active")
(nnml-inhibit-expiry t)
(nnml-get-new-mail nil))))

quand ce qu'il veut est plutôt :

(setq gnus-secondary-select-methods
`((nnml "archives"
(nnml-directory ,(concat gnus-home-directory
"/archives/active"))
(nnml-active-file "/home/seki/.gnus.d/archives/active")
(nnml-inhibit-expiry t)
(nnml-get-new-mail nil))))

Combien je gagne ?

--drkm
Avatar
Pascal Bourguignon
drkm writes:

Pascal Bourguignon writes:

Si tu veux obtenir le résultat de la concaténation, il ne faut pas
"quoter" avec function ton expression



Mmh. Sébastien a dit avoir tenté de fixer 'nnml-directory' à
(concat gnus-home-directory "/archives/active"). Il n'a pas
parlé de 'function'. Par 'nnml-directory', j'imagine qu'il parle
de la valeur associée à cette entrée dans une sous-liste de
'gnus-secondary-select-methods'.

Mais il est vrai que je ne m'explique pas ce 'function'. Ce
serait évidemment l'explication la plus évidente. Sébastien,
as-tu fait cette bêtise ?-).



Le plus probable, c'est que l'expression concat ait été saisie avec
customize-option où on a un menu où on peut sélectionner "fonction" et
taper le nom de la fonction à utiliser...

Si je comprend bien le problème, il a essayé d'évaluer le
'concat' dans la liste au moyen de 'function', comme ceci :

(setq gnus-secondary-select-methods
'((nnml "archives"
(nnml-directory (function (concat gnus-home-directory
"/archives/active")))
(nnml-active-file "/home/seki/.gnus.d/archives/active")
(nnml-inhibit-expiry t)
(nnml-get-new-mail nil))))

quand ce qu'il veut est plutôt :

(setq gnus-secondary-select-methods
`((nnml "archives"
(nnml-directory ,(concat gnus-home-directory
"/archives/active"))
(nnml-active-file "/home/seki/.gnus.d/archives/active")
(nnml-inhibit-expiry t)
(nnml-get-new-mail nil))))

Combien je gagne ?



Oui, mais ça a certainement été généré automatiquement par l'interface
utilisateur "customize" dans une utilisation mal comprise.


--
__Pascal Bourguignon__ http://www.informatimago.com/
-----BEGIN GEEK CODE BLOCK-----
Version: 3.12
GCS d? s++:++ a+ C+++ UL++++ P--- L+++ E+++ W++ N+++ o-- K- w---
O- M++ V PS PE++ Y++ PGP t+ 5+ X++ R !tv b+++ DI++++ D++
G e+++ h+ r-- z?
------END GEEK CODE BLOCK------
Avatar
drkm
Pascal Bourguignon writes:

Le plus probable, c'est que l'expression concat ait été saisie avec
customize-option où on a un menu où on peut sélectionner "fonction" et
taper le nom de la fonction à utiliser...



Ha, ok. Je ne connaissais pas. Je dois d'ailleurs bien avouer
que je n'utilise jamais Customize, et que je connais donc très
mal la customization (via Customize).

--drkm
Avatar
Sébastien Kirche
Le 4 jun 2005, drkm a dit :

Pascal Bourguignon writes:

> Si tu veux obtenir le résultat de la concaténation, il ne faut pas
> "quoter" avec function ton expression



Mais le function n'est pas de moi. C'est ainsi que le debugger présente
le code quand il bute sur ce que j'ai essayé de configurer.

Mmh. Sébastien a dit avoir tenté de fixer 'nnml-directory' à
(concat gnus-home-directory "/archives/active").



Oui.

Il n'a pas parlé de 'function'. Par 'nnml-directory', j'imagine qu'il
parle de la valeur associée à cette entrée dans une sous-liste de
'gnus-secondary-select-methods'.

Mais il est vrai que je ne m'explique pas ce 'function'. Ce
serait évidemment l'explication la plus évidente. Sébastien,
as-tu fait cette bêtise ?-).



Heuuu... :/


Si je comprend bien le problème, il a essayé d'évaluer le
'concat' dans la liste au moyen de 'function', comme ceci :

(setq gnus-secondary-select-methods
'((nnml "archives"
(nnml-directory (function (concat gnus-home-directory
"/archives/active")))
(nnml-active-file "/home/seki/.gnus.d/archives/active")
(nnml-inhibit-expiry t)
(nnml-get-new-mail nil))))



Presque, sauf que je n'ai pas employé de (function) mais directement le
(concat) pour la valeur de nnml-directory.

quand ce qu'il veut est plutôt :

(setq gnus-secondary-select-methods
`((nnml "archives"
(nnml-directory ,(concat gnus-home-directory
"/archives/active"))
(nnml-active-file "/home/seki/.gnus.d/archives/active")
(nnml-inhibit-expiry t)
(nnml-get-new-mail nil))))



Bingo ! Je viens de modifier et ça fonctionne.
Merci pour l'explication détaillée dans l'autre message sur l'usage de
backquote et de la virgule.

Par contre un détail : si je regarde la valeur avec C-h v
gnus-secondary-select-methods je remarque que le concat a disparu,
remplacé par le résultat de l'évaluation de toute l'expression. C'est
bien ça ?

Combien je gagne ?



Toute ma gratitude. Ç'est assez ? ;)

--
Sébastien Kirche
Avatar
Sébastien Kirche
Le 4 jun 2005, Pascal Bourguignon a formulé :

> quand ce qu'il veut est plutôt :
>
> (setq gnus-secondary-select-methods
> `((nnml "archives"
> (nnml-directory ,(concat gnus-home-directory
> "/archives/active"))
> (nnml-active-file "/home/seki/.gnus.d/archives/active")
> (nnml-inhibit-expiry t)
> (nnml-get-new-mail nil))))
>
> Combien je gagne ?

Oui, mais ça a certainement été généré automatiquement par l'interface
utilisateur "customize" dans une utilisation mal comprise.



Non non, ça a été généré à l'os par l'interface chaise-clavier qui fait
qutidiennement du C/C++, Python et ce genre de choses et pour qui le
lisp est assez... énigmatique :)

J'utilise très peu l'interface customise. Le plus sauvent quand je ne
sais comment écrire un paramétrage je l'utilise mais je reprend ensuite
le résultat pour l'intégrer à mes .emacs/.gnus

L'expérience venant, j'arrive quand même à aller plus loin en cas de
problème que le simple message d'erreur dans le minibuffer pour savoir
où ça se passe (notamment avec debug-on-error) et j'ai bien vu que le
souci du moment était que ma construction concat était prise
littéralement et non évaluée. Mais je ne savais pas aller plus loin que
de remplacer (concat) par la chaîne résultat «en dur».

Merci de vos explications.

--
Sébastien Kirche
Avatar
drkm
Sébastien Kirche writes:

Le 4 jun 2005, drkm a dit :

[...]

Par contre un détail : si je regarde la valeur avec C-h v
gnus-secondary-select-methods je remarque que le concat a disparu,
remplacé par le résultat de l'évaluation de toute l'expression. C'est
bien ça ?



Voui. C'est bien ce que tu veux. Tu spécifies la liste
directement, sauf pour cette valeur, que tu laisses à 'concat' le
soin de calculer. Le résultat est alors substitué à l'évaluation
(lors de l'affectation).

Combien je gagne ?



Toute ma gratitude. Ç'est assez ? ;)



Je ne sais pas. Où en est le taux de change ?-)

--drkm