Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Lisp et Unicode

3 views
Skip to first unread message

yliur

unread,
Mar 8, 2009, 10:21:33 PM3/8/09
to
Bonjour

Ca y est, me voilà lancé dans Lisp. Je crois que je vais ranimer la
fr.comp.lang.lisp (s'il reste des gens connectés :) )

Donc ma première question porte sur la gestion des caractères Unicode.
Je lis un fichier xml en me connectant à une URL mais j'ai un problème
pour le stocker dans une chaîne.

J'utilise SBCL.

Voici ce que print affiche pour mon flux de lecture :
#<SB-SYS:FD-STREAM for "a socket" {B3330D9}>

Et pour mon flux d'écriture dans une chaîne (créé avec
with-output-to-string) :
#<SB-IMPL::FILL-POINTER-OUTPUT-STREAM {B3F4791}>

Bon, ça n'a pas l'air très utile comme information (?).

Je lis les caractères avec read-char dans le flux de lecture.
Je les écris avec write-char dans le flux d'écriture.

Voici le texte de l'erreur :
debugger invoked on a TYPE-ERROR in thread #<THREAD "initial thread"
RUNNING {A8EA811}>:
The value #\LATIN_SMALL_LETTER_A_WITH_GRAVE is not of type BASE-CHAR.

La création de ma chaîne passée à with-output-to-string :
(setf chaine (make-array '(0) :element-type 'base-char
:fill-pointer 0 :adjustable t))

De ce que je comprends, write-char a été embêté pour écrire un caractère
Unicode dans ma chaîne parce qu'elle contient des "caractères simples".
C'est ça ? Et donc comment faire pour créer une chaîne Unicode ?

Merci

Pascal J. Bourguignon

unread,
Mar 9, 2009, 3:10:01 PM3/9/09
to
yliur <yl...@free.fr> writes:

> Bonjour
>
> Ca y est, me voilà lancé dans Lisp. Je crois que je vais ranimer la
> fr.comp.lang.lisp (s'il reste des gens connectés :) )
>
> Donc ma première question porte sur la gestion des caractères Unicode.

> [...]


> La création de ma chaîne passée à with-output-to-string :
> (setf chaine (make-array '(0) :element-type 'base-char
> :fill-pointer 0 :adjustable t))
>
> De ce que je comprends, write-char a été embêté pour écrire un
> caractère Unicode dans ma chaîne parce qu'elle contient des
> "caractères simples". C'est ça ? Et donc comment faire pour créer une
> chaîne Unicode ?

Utiliser des CHARACTER au lieu de BASE-CHAR.


* (let ((chaine (make-array 0
:element-type 'character
:fill-pointer 0
:adjustable t)))
(with-output-to-string (out chaine)
(format out "« Ça ira mieux en été »"))
chaine)

"« Ça ira mieux en été »"
*

Note que les caractères standards de Common Lisp, ceux que BASE-CHAR
doit contenir au minimum, sont #\newline, #\space et :

!"#$%&'()*+,-./0123456789:;<=>?
@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
`abcdefghijklmnopqrstuvwxyz{|}~

(C'est un pur hasard, si ce sont les caractères imprimables du code
ASCII).

Quand on veut écrire un program 100% portable, il faut se limiter à
ces caractères. Mais bien sur, de nos jours, la plupart des
implémentations supportent tous les caractères Unicode; mais il faut
alors utiliser CHARACTER, car certaines comme SBCL considèrent que
BASE-CHAR ne contient que les caractères standards.

--
__Pascal Bourguignon__

Philippe Brochard

unread,
Mar 9, 2009, 4:56:15 PM3/9/09
to
yl...@free.fr a écrit :

> Bonjour
>
Hello,

> Ca y est, me voilà lancé dans Lisp. Je crois que je vais ranimer la
> fr.comp.lang.lisp (s'il reste des gens connectés :) )
>

Bienvenue à bord. Ca va peut-être rebouger ici alors :)

> Donc ma première question porte sur la gestion des caractères Unicode.
> Je lis un fichier xml en me connectant à une URL mais j'ai un problème
> pour le stocker dans une chaîne.
>
> J'utilise SBCL.
>
> Voici ce que print affiche pour mon flux de lecture :
> #<SB-SYS:FD-STREAM for "a socket" {B3330D9}>
>
> Et pour mon flux d'écriture dans une chaîne (créé avec
> with-output-to-string) :
> #<SB-IMPL::FILL-POINTER-OUTPUT-STREAM {B3F4791}>
>
> Bon, ça n'a pas l'air très utile comme information (?).
>
> Je lis les caractères avec read-char dans le flux de lecture.
> Je les écris avec write-char dans le flux d'écriture.
>
> Voici le texte de l'erreur :
> debugger invoked on a TYPE-ERROR in thread #<THREAD "initial thread"
> RUNNING {A8EA811}>:
> The value #\LATIN_SMALL_LETTER_A_WITH_GRAVE is not of type BASE-CHAR.
>
> La création de ma chaîne passée à with-output-to-string :
> (setf chaine (make-array '(0) :element-type 'base-char
> :fill-pointer 0 :adjustable t))
>
> De ce que je comprends, write-char a été embêté pour écrire un
> caractère Unicode dans ma chaîne parce qu'elle contient des
> "caractères simples". C'est ça ? Et donc comment faire pour créer une
> chaîne Unicode ?
>

Y a-t-il une raison particulière pour laquelle tu te limite aux
caractères de base ?

Tu peux essayer avec des éléments de type character ou extended-char
parce qu'effectivement #\LATIN_SMALL_LETTER_A_WITH_GRAVE n'est pas du
type base-char:

(typep #\LATIN_SMALL_LETTER_A_WITH_GRAVE 'base-char)
NIL
(typep #\LATIN_SMALL_LETTER_A_WITH_GRAVE 'extended-char)
T
(typep #\LATIN_SMALL_LETTER_A_WITH_GRAVE 'character)
T
(characterp #\LATIN_SMALL_LETTER_A_WITH_GRAVE)
T


De même es-tu vraiment obligé de construire toi même la chaîne.
Un truc du genre ne suffit-il pas ?

(with-output-to-string (str)
(write-char #\LATIN_SMALL_LETTER_A_WITH_GRAVE str)
(write-char #\LATIN_SMALL_LETTER_E_WITH_ACUTE str))

str étant renvoyée par with-output-to-string.

Philippe

yliur

unread,
Mar 9, 2009, 3:58:24 PM3/9/09
to
Ok, merci ça marche :) .

Et donc en fait les caractères Unicode sont un sous-type de character,
mais qui ne se trouve pas dans l'HyperSpec ?

yliur

unread,
Mar 9, 2009, 4:15:28 PM3/9/09
to

> Y a-t-il une raison particulière pour laquelle tu te limite aux
> caractères de base ?

Oui, si on veut : je ne connais pas bien tout ça et j'ai (un peu
bêtement) copié un exemple trouvé quelque part... Du genre : on part de
ce qu'on trouve (on fait avec ce qu'on a) et on améliore quand on trouve
mieux :) .

Ma spécialité c'est plutôt Java pour l'instant.


> Tu peux essayer avec des éléments de type character ou extended-char
> parce qu'effectivement #\LATIN_SMALL_LETTER_A_WITH_GRAVE n'est pas du
> type base-char:

Si j'ai bien compris, extended-char c'est tous les caractères gérés par
l'interpréteur, sauf ceux qui sont dans base-char ? Et character c'est
l'ensemble ? Donc plutôt character (je lis un fichier xml, il y a de
tout dedans).


> De même es-tu vraiment obligé de construire toi même la chaîne.
> Un truc du genre ne suffit-il pas ?
>
> (with-output-to-string (str)
> (write-char #\LATIN_SMALL_LETTER_A_WITH_GRAVE str)
> (write-char #\LATIN_SMALL_LETTER_E_WITH_ACUTE str))
>
> str étant renvoyée par with-output-to-string.

Non, je ne suis pas obligé, ça marche aussi comme tu l'écris. Là encore
j'ai récupéré un exemple, toutes les remarques sont donc les bienvenues :) .

Effectivement, c'est beaucoup plus simple.

Par contre ce que tu as appelé str c'est a priori plutôt un flux
d'écriture dans une chaîne, pas strictement une chaîne (même si en fait
on ne s'en préoccupe pas dans la forme que tu présentes). Et la macro
renvoie bien la chaîne.

Merci pour les informations

Philippe Brochard

unread,
Mar 9, 2009, 5:45:39 PM3/9/09
to
yl...@free.fr a écrit :

>> Y a-t-il une raison particulière pour laquelle tu te limite aux
>> caractères de base ?
>
> Oui, si on veut : je ne connais pas bien tout ça et j'ai (un peu
> bêtement) copié un exemple trouvé quelque part... Du genre : on part
> de ce qu'on trouve (on fait avec ce qu'on a) et on améliore quand on
> trouve mieux :) .
>

Oui, c'est une bonne méthode :)

> Ma spécialité c'est plutôt Java pour l'instant.
>
>
>> Tu peux essayer avec des éléments de type character ou extended-char
>> parce qu'effectivement #\LATIN_SMALL_LETTER_A_WITH_GRAVE n'est pas du
>> type base-char:
>
> Si j'ai bien compris, extended-char c'est tous les caractères gérés
> par l'interpréteur, sauf ceux qui sont dans base-char ? Et character
> c'est l'ensemble ? Donc plutôt character (je lis un fichier xml, il y
> a de tout dedans).
>

Oui c'est ça. Il faut donc que tu utilises le type character.

>
>> De même es-tu vraiment obligé de construire toi même la chaîne.
>> Un truc du genre ne suffit-il pas ?
>>
>> (with-output-to-string (str)
>> (write-char #\LATIN_SMALL_LETTER_A_WITH_GRAVE str)
>> (write-char #\LATIN_SMALL_LETTER_E_WITH_ACUTE str))
>>
>> str étant renvoyée par with-output-to-string.
>
> Non, je ne suis pas obligé, ça marche aussi comme tu l'écris. Là
> encore j'ai récupéré un exemple, toutes les remarques sont donc les
> bienvenues :) .
>
> Effectivement, c'est beaucoup plus simple.
>
> Par contre ce que tu as appelé str c'est a priori plutôt un flux
> d'écriture dans une chaîne, pas strictement une chaîne (même si en
> fait on ne s'en préoccupe pas dans la forme que tu présentes). Et la
> macro renvoie bien la chaîne.
>
> Merci pour les informations
>

C'est encore ça. str est un nom de variable associée à un flux mais par
abus je l'ai appelé comme ça vue que with-output-to-string renvoie une
chaîne de caractères.
Pis si on chipote str(ing) ou str(eam) :)

Pascal J. Bourguignon

unread,
Mar 9, 2009, 6:17:30 PM3/9/09
to
yliur <yl...@free.fr> writes:

Le standard Common Lisp a été terminé en 1986.
Le standard Unicode a été commencé en 1991.

De là on voit la qualité du standard Common Lisp, puisqu'il permet aux
implémentations d'intégrer des nouveautés de façon ordonné, et qu'il
permet aux programmes d'être écrits de manière portable.


Notez que (equal '() (intersection BASE-CHAR EXTENDED-CHAR)) alors je
ne conseillerais pas vraiment d'utiliser un vecteur d'EXTENDED-CHAR:

(TYPEP #\A 'EXTENDED-CHAR) --> NIL


--
__Pascal Bourguignon__

Thomas F. Burdick

unread,
Mar 25, 2009, 8:05:16 AM3/25/09
to
On Mar 9, 11:17 pm, p...@informatimago.com (Pascal J. Bourguignon)
wrote:

> yliur <yl...@free.fr> writes:
> > Ok, merci ça marche :) .
>
> > Et donc en fait les caractères Unicode sont un sous-type de character,
> > mais qui ne se trouve pas dans l'HyperSpec ?
>
> Le standard Common Lisp a été terminé en 1986.
> Le standard Unicode a été commencé en 1991.

N'importe quoi. Le standard Common Lisp a été terminé en 1994. Ceci
dit, je ne pense pas qu'il fallait changer quoi que ce soit des
characters entre CLTL et le standard ANSI.

Pascal J. Bourguignon

unread,
Mar 25, 2009, 9:42:56 AM3/25/09
to

Oui, excusez moi. Ces deux standards sont à peut près contemporains:

Common Lisp a été commencé en 1984 et fini en 1994.
Unicode a été commencé en 1987, version 1.0 en 1991, et version 5.1 en 2008.

Il est donc assez naturel que le standard de Common Lisp ne s'appuit
pas sur le standard d'Unicode, mais qu'il permette aux implémentations
de l'utiliser.


--
__Pascal Bourguignon__

0 new messages