Rebol Documentation Project

Aller au contenu | Aller au menu | Aller à la recherche

dimanche 30 avril 2006

"Copy or not copy", telle est la question.

Carl Sassenrath, CTO REBOL Technologies 9-Apr-2006 18:03 GMT Article #0006

Ok, ce sujet est profond et vaste, mais je veux vous faire réfléchir là dessus ...

Un problème que nous devons régler très bientôt est celui rencontré lorsqu'on copie ou lorsqu'on ne copie pas des séries REBOL (strings, blocks, etc.). Ce problème a un impact toutes les versions de REBOL et est important parce que les règles pour copier/ne-pas-copier doivent être fortement présentes dans votre esprit, tandis que vous programmez en REBOL.

Par exemple, voici le simple cas, où vous utilisez des chaînes de caractères littérales en REBOL, comme dans une fonction :


fun: func [str] [append "example " str]

La plupart d'entre vous reconnaisse ce problème. La première fois, nous appelons la fonction :


print fun "test"
example test

et la seconde fois :


print fun "this"
example testthis

La chaîne littérale a été modifiée. Pour prévenir cela, vous deviez écrire :


fun: func [str] [append copy "example " str]

C'est l'une des premières choses qu'un débutant apprend - et, habituellement, en s'étant fait avoir.

Mais, le problème devient vite vraiment important rapidement parce qu'il s'applique à toutes les séries de REBOL (series !) soit les blocs, des parens, des noms de fichier, des URLs, etc...

Par exemple, quand vous créez un objet de cette manière :


obj-body: [a: 10 b: [print a]]
obj1: make object! obj-body
obj2: make object! obj-body

Vous percevez notre problème si le bloc obj-body doit être copié avant qu'il soit lié (binding des variables attributs de l'objet). Le "obj-body" original est modifié par la fonction make. Si vous ne savez pas cela, vous pourriez être étonné. Surprise !

La même chose peut être dite à propos des spécifications ou du corps de fonctions, etc.

De sorte que ce problème vaut la peine d'être revu dans REBOL 3.0.

Il y a deux principes de REBOL qui sont opposés et à l'oeuvre :

1. Simplicité : nous voulons minimiser les effets de bords dans le code normal. Bon pour les débutants et bon probablement aussi pour les experts.

2. Optimisation : minimiser le coût mémoire et optimiser la performance. Si nous avons à copier des chaînes et des blocs à de nombreux endroits dans notre code, cela consomme du temps et de la mémoire.

Ainsi, il y a quelques problèmes auquel vous devriez réfléchir si vous voulez programmer finement en REBOL. Nous avons besoin d'une solution bien définie. Elle peut être n'importe laquelle de :

1. Ne rien faire. Laisser cela en l'état.

2. Modifier là où c'est le plus approprié et le plus optimal.

3. Modifier partout et ignorer le surcoût en mémoire et la diminution de performance.

Voici donc quelque chose à considérer la prochaine fois que vous vous relaxerez dans un bar, fumerez votre pipe dans votre fauteuil, ou escaladerez les montagnes dans votre coin.

Et, je vous invite à partager vos réflexions avec tout le monde, soit sur le blog dans la section "comments", ou via votre propre blog ou page web.

(Traduction : Philippe Le Goff)

Nommage : Typemap or Typeset ?

Carl Sassenrath, CTO REBOL Technologies 9-Apr-2006 17:54 GMT Article #0005

Information : La modification évoquée ci-dessous a déjà été faite. "Typemap" est maintenant appelé "typeset".

Comme vous le savez, je prends au sérieux le processus de nommage dans REBOL.

Ironiquement, proposer le meilleur nom pour une fonction ou toute autre structure peut prendre plus de temps qu'écrire cette fonction complète dans REBOL.

Le datatype typemap! est un bon exemple, et nous devrions en parler à présent.

A l'origine, je pensais que le meilleur nom était typeset! pour être cohérent avec le datatype bitset!.

Mais, j'ai été préoccupé par le fait que le mot "typeset" a déjà une signification technique concrète en anglais (encore plus pour ceux d'entre nous qui ont édité des livres avant, ce qui est mon propre cas). (NdT : il s'agit de la composition, pour l'édition littéraire.)

Cependant, ce conflit de nom n'est-il pas finalement sans intérêt ? Après tout, quelle est la probabilité que la composition de livres ait un jour un impact avec REBOL ?

Faites moi donc remonter vos commentaires sur ce point. Personnellement, je penche fortement pour changer le nom en typeset! et, à présent, il est temps de se décider.

(Traduction : Philippe Le Goff)

vendredi 28 avril 2006

Ajout des commentaires au Blog Rebol 3.0

Carl Sassenrath, CTO REBOL Technologies 9-Apr-2006 17:06 GMT Article #0004

Les commentaires sont à présent possibles pour le blog, merci aux services gratuits d'Haloscan.com.

Il n'y a pas de fantaisie, cela résout le besoin immédiat avec seulement 60 secondes de programmation REBOL requise de mon côté.

Faites-moi savoir si cela fonctionne, ou s'il y a des problèmes. Au besoin, nous pouvons ajouter un modérateur volontaire, ou deux, pour aider à gérer les commentaires.

Merci à ED et Chris pour la suggestion de Haloscan.

(Traduction : Philippe Le Goff)

Make Function ! doit changer

Carl Sassenrath, CTO REBOL Technologies 8-Apr-2006 22:39 GMT Article #0003

Il existe une contradiction, depuis longtemps, dans l'implémentation de la fonction make sous REBOL, qui sera modifiée dans REBOL 3.0. (Mais, cela n'aura que peu d'effet sur la plupart des programmes.)

Si j'interroge REBOL à propos de la fonction make, il répond quelque chose comme cela :


>> ? make
USAGE:
MAKE type spec

DESCRIPTION:
Constructs and returns a new value.
MAKE is an action value.

ARGUMENTS:
type -- The datatype or example value. (Type: any-type)
spec -- The attributes of the new value. (Type: any-type)

Donc, si ceci est exact, comment la ligne ci-dessous peut elle être valide ?


f: make function! [a] [print a]

Dans cet exemple, make prend trois arguments, mais la description de la fonction mentionne uniquement deux arguments : type et spec.

Ceci va être changé dans REBOL 3.0. Voici pourquoi :

1. Un programme doit pouvoir s'appuyer avec précision sur les caractéristiques d'interface de fonction. C'est important non seulement pour des choses comme des outils de déboguage, mais également pour la réflexion appropriée (du code vers des données qui renvoient du code).

2. L'ancienne approche nécessitait un hack dans l'implémentation de l'évaluation de REBOL pour "faire marcher" l'argument supplémentaire. Effacer cela simplifierait le code et augmenterait la rapidité de REBOL.

La nouvelle forme de la fonction make sera :


f: make function! [[a] [print a]]

Cela sera cohérent avec la spécification de l'interface de la fonction.

Comment ceci va-t-il affecter la compatibilité ? Très peu. La plupart des programmes n'utilisent pas cette forme de création de fonction ; ils utilisent les fonctions comme func, function, does, ou has.

(Traduction : Philippe Le Goff)

jeudi 27 avril 2006

Un nouveau datatype : Typeset !

Carl Sassenrath, CTO REBOL Technologies 8-Apr-2006 20:21 GMT Article #0002

“Cet article a été modifié depuis sa première version. Le mot "typemap" a été changé en "typeset".”

Dans REBOL 3.0, un typeset est essentiellement un ensemble de datatypes.

Par exemple, lorsque vous définissez une fonction, vous spécifiez de la manière suivante les types de données (datatypes) des arguments :


f: func [arg1 [integer! number!] arg2 [string! url!]] ...

Ce qui suit chaque mot définissant un argument (arg1, arg2,...) est un bloc de datatypes.

REBOL 3.0 ajoute un nouveau type de données appelé un typeset !. Un typeset est simplement une méthode compacte, efficace de stocker des ensembles de datatypes, comme une nouvelle sorte de type de données.

Les typesets sont importants car l'interpréteur les utilise pour valider rapidement les arguments des fonctions.

Le datatype typeset ! sait comment convertir un bloc contenant des noms de datatypes comme [integer ! decimal ! money !] en une représentation interne (similaire au datatype bitset !). Il peut aussi traduire ce format interne en un bloc compréhensible, en vue d'une édition ou de modifications.

L'ajout de ce datatype typeset ! élimine le recours aux pseudo-datatypes REBOL spéciaux que sont series ! et number !. Ils sont à présent implémentés comme des typesets, mais vous pouvez continuer à les utiliser de la même manière que précédemment.

Ils peuvent être utilisés dans les spécifications d'arguments de fonction :


f: func [arg1 [number!] arg2 [series!]] ...

et aussi pour des tests de datatypes :


if series? value [....]

Notez, cependant, cette différence avec REBOL 2.* :


type? series!
datatype!

qui devient dans REBOL 3.0 :


type? series!
typeset!

Pour les utilisateurs avertis, REBOL 3.0 fournira une méthode pour créer et gérer vos propres typesets.



tmp-type: make typeset! [time! money! percent!]

f: func [arg1 [tmp-type]] [...]

J'en dirai plus bientôt au sujet de quelques problèmes liés aux typesets.

(Traduction : Philippe Le Goff)

Bienvenue sur la ligne de front de REBOL 3.0...

Carl Sassenrath, CTO REBOL Technologies 8-Apr-2006 20:18 GMT Article #0001

Comme je l'ai mentionné dans mes notes publiées sur www.rebol.net/article/0263.html, j'ai cherché un moyen de poster mes notes relatives à REBOL 3.0. Mais, à la différence du fonctionnement mon blog actuel, il était aussi vraiment important pour moi de permettre aux utilisateurs de poster leurs remarques et idées.

J'ai demandé des contributions pour définir un bon outil de blog et reçu quelques réponses, mais jusqu'ici rien n'a été mis en place. Le programme n'était soit pas opérationnel, soit nécessitait une installation compliquée, ou comme avec blogger.com, pas vraiment utilisable comme je le voulais.

Mais, du temps a passé. Je dois permettre que mes notes soient publiées, de sorte que pour l'instant, j'utilise mon script blogger.r. Cela m'a pris seulement 30 secondes pour obtenir ce blog configuré et en ligne. "A présent, c'est de celui-ci que je parle."

Mais, bon, qu'en est-il de vos commentaires ? Pour le moment, je ne suis pas encore sûr. Je présenterai quelque chose très bientôt. Peut-être puis-je trouver une manière de lier ensemble blogger.r et le BBS de REBOL, partant de l'hypothèse que cela prendrait quelques heures pour avoir un résultat correct.

Notez que le lien RSS devrait fonctionner également, mais je ne l'ai pas testé. Merci de me contacter si vous avez un problème.

(traduction : Philippe Le Goff)

vendredi 18 novembre 2005

Manuel de l'utilisateur de REBOL/Core

Sous ce lien vous trouverez la traduction francaise du manuel de l'utilisateur de REBOL/Core (R2).

mardi 08 novembre 2005

Manuel de l'utilisateur - Annexe 3 - La console

Historique de la traduction

Date Version Commentaires Auteur Email
16 Septembre 2005 07:03 1.0.0 Traduction initiale Philippe Le Goff lp—legoff—free—fr

Le prompt de la ligne de commande

NdT : On appelle "prompt" l'indicateur alphanumérique qui indique que la console attend une saisie. En console Dos, ou Unix, cette notion est bien connue. REBOL possède aussi un prompt en mode console.

Le prompt par défaut de la ligne de commande est ">>". Il est possible de modifier cela avec par exemple le code suivant :


system/console/prompt: "Input: "

Le prompt devient alors :


Input:

Le prompt peut être un bloc qui sera évalué à chaque fois. La ligne suivante affiche l'heure courante :


system/console/prompt: [reform [now/time " >> "]]

Le résultat devrait ressembler à un prompt comme ceci :


10:30 >>

Indicateur de résultat

Par défaut, l'indicateur de résultat est "==", il peut être aussi modifié avec une ligne telle que :


system/console/result: "Result: "

Ces exemples modifiant les paramètres par défaut peuvent être placés dans votre fichier user.r pour les rendre permanent, à chaque démarrage de REBOL.

Rappel de l'historique

Chaque ligne saisie dans la console REBOL est conservée dans un bloc, en historique, et peut être rappelée plus tard en utilisant les touches "flèche haut" et "flèche bas" (up et down).

Par exemple, si vous appuyez une seule fois sur la touche "flèche haut", vous rappellerez la dernière ligne de commande saisie.

Le bloc d'historique contenant toutes les lignes entrées à la console peut être consulté en appelant l'attribut history de l'objet system/console.


probe system/console/history

Vous pouvez sauvegarder ce bloc dans un fichier :


save %history.r system/console/history

et il peut être rechargé plus tard :


system/console/history: load %history.r

Ces lignes peuvent être placées dans le fichier user.r pour sauvegarder et recharger votre historique entre deux sessions.

Indicateur d'activité

Lorsque REBOL attend qu'une opération (par exemple, une requête réseau) se termine, un indicateur d'activité apparaît à l'écran pour indiquer que quelque chose est en cours.

Vous pouvez changer l'indicateur d'activité avec un ligne comme celle-ci par exemple :


system/console/busy: "123456789-"

Quand REBOL travaille en mode "silencieux" (quiet mode), l'indicateur d'activité n'est pas affiché.

Opérations spécifiques avec la console

La console se comporte comme un "terminal virtuel" qui vous permet des opérations comme le mouvement et l'adressage du curseur, l'édition de la ligne, l'effacement de l'écran, l'usage de touches de contrôle, et de requêtes sur la position du curseur. Les séquences de contrôle suivent le standard ANSI. Cela vous permet de définir votre propre terminal (indépendamment de la plate-forme sur laquelle vous êtes) pour des programmes comme des éditeurs de textes, des client emails, ou des émulateurs telnet.

Les fonctionnalités de la console s'appliquent aux entrées et aux sorties. Pour les entrées, les touches de fonctions seront converties en séquences d'échappement de plusieurs caractères. Pour les sorties, les séquences d'échappement peuvent être utilisées pour contrôler l'affichage du texte dans la fenêtre de la console. Aussi bien les entrées que les sorties commencent avec le caractère d'échappement ANSI : 27 en décimal (1B en hexa). Le caractère suivant dans la séquence indique les contrôles en entrée ou l'opération en sortie pour le contrôle du terminal. Les caractères ANSI sont sensibles à la casse et nécessitent en principe d'être en majuscules.

Séquences entrées au clavier

Les séquences saisies avec les touches de fonctions sont listées dans la table ci-dessous (pour les systèmes et les shells qui les supportent, comme Linux, BSD, etc.). Pour recevoir ces séquences en un flux de caractères non évalués, vous devez bloquer le mode "lignes" pour le port "input" de REBOL :


set-modes system/ports/input [lines: false]

A présent, vous pouvez récupérer l'entrée à partir du port (avec les fonctions copy ou read-io) ou utiliser une fonction comme input pour récupérer chaque caractère :


while [
code: input
code <> 13 ; ENTER
][
probe code
]

Voici quelques unes des fonctions ANSI les plus courantes :

Touches de fonction Comme séquences d'échappement Comme bloc REBOL
F1 ESC O P [27 79 80]
F2 ESC O Q [27 79 81]
F3 ESC O R [27 79 82]
F4 ESC O S [27 79 83]
F5 ESC [ 1 5 [27 91 49 53 126]
F6 ESC [ 1 7 [27 91 49 55 126]
F7 ESC [ 1 8 [27 91 49 56 126]
F8 ESC [ 1 9 [27 91 49 57 126]
F9 ESC [ 2 0 [27 91 50 48 126]
F10 ESC [ 2 1 [27 91 50 49 126]
F11 ESC [ 2 2 [27 91 50 50 126]
F12 ESC [ 2 3 [27 91 50 51 126]
Home ESC [ 1 [27 91 49 126]
End ou Fin ESC [ 4 [27 91 52 126]
Page-up ESC [ 5 [27 91 53 126]
Page-down ESC [ 6 [27 91 54 126]
Insert ESC [ 2 [27 91 50 126]
Up ESC [ A [27 91 65]
Down ESC [ B [27 91 66]
Left ESC [ D [27 91 68]
Right ESC [ C [27 91 67]

Séquences en sortie pour le terminal

Il y a plusieurs variantes dans les séquences de caractère de contrôle. Certaines commandes sont précédées par un chiffre (en ASCII), indiquant que l'opération doit être réalisée le nombre de fois indiquées par le chiffre.

Par exemple aussi, la commande permettant le déplacement du curseur peut être précédée par deux nombres séparés d'un point virgule, pour indiquer que la position du curseur doit être modifiée selon la ligne et la colonne courante. Les commandes de contrôle du curseur (les majuscules sont requises) sont indiquées dans la table suivante :

Séquence en sortie Description
(1B) Séquence d'échappement à utiliser avant les codes ci-dessous
D Déplace le curseur d'un espace vers la gauche
C Déplace le curseur d'un espace vers la droite
A Déplace le curseur d'un espace vers le haut
B Déplace le curseur d'un espace vers le bas
n D Déplace le curseur de n espaces vers la gauche
n C Déplace le curseur de n espaces vers la droite
n A Déplace le curseur de n espaces vers le haut
n B Déplace le curseur de n espaces vers le bas
r ; c H Déplace le curseur vers la ligne r, colonne c*
H Déplace le curseur vers le coin gauche supérieur (home)*
P Efface un caractère à la droite de la position courante
n P Efface deux caractères à la droite de la position courante
@ Insère un espace blanc à la position courante
n @ Insère n espaces blancs à la position courante
J Efface l'écran et déplace le curseur dans le coin supérieur gauche (home)*
K Efface tous les caractères entre la position courante et la fin de la ligne
6n Place la position courante du curseur dans un buffer (input buffer)
7n Place les dimensions de l'écran dans un buffer (input buffer)

Le coin supérieur gauche est défini à la colonne 1, ligne 1.

L'exemple suivant déplace le curseur de huit espaces vers la droite :


print "^^(1B)[10CHi!"
Hi

Cet exemple déplace le curseur de sept espaces vers la gauche et efface le restant de la ligne :


cursor: func [parm [string!]][join "^^(1B)[" parm]
print ["How are you" cursor "7D" cursor "K"]
How a

Pour trouver la taille courante de la fenêtre de la console, vous pouvez utiliser cet exemple :


cons: open/binary [scheme: 'console]

print cursor "7n"
screen-dimensions: next next to-string copy cons
33;105R
close cons

L'exemple précédent ouvre la console, envoie un caractère de contrôle vers le buffer de l'input, et copie la valeur retournée. Elle lit la valeur (dimension de l'écran) qui est renvoyée après le caractère de contrôle et ferme la console. La valeur renvoyée est la hauteur et la largeur, séparées par un point-virgule ( ;), et suivies par un "R". Dans cet exemple, l'écran fait 33 lignes et 105 colonnes.

* : Autoscrolling

L'affichage d'un caractère dans le coin inférieur droit de certains terminaux force la création d'une nouvelle ligne, et un réajustement de l'écran. D'autres terminaux n'ont pas le même comportement. Ces différences de fonctionnement doivent être prises en compte pour écrire des scripts REBOL multi-platformes.

Manuel de l'utilisateur - Annexe 2 - Les Erreurs

Historique de la traduction

Date Version Commentaires Auteur Email
19 Septembre 2005 19:56 1.0.0 Traduction initiale Philippe Le Goff lp—legoff—free—fr

Présentation

Les erreurs sont des exceptions qui se produisent lors de certaines situations anormales. Ces situations peuvent se rencontrer pour des erreurs de syntaxe jusqu'à des erreurs liées aux accès réseau ou fichiers.

Voici quelques illustrations :


12-30
** Syntax Error: Invalid date -- 12-30.
** Where: (line 1) 12-30
1 / 0
** Math Error: Attempt to divide by zero.
** Where: 1 / 0
read %nofile.r
** Access Error: Cannot open /example/nofile.r.
** Where: read %nofile.r

Les erreurs sont traitées au sein de langage comme des valeurs de datatype error !. Une erreur est un objet qui, s'il est évalué, affichera un message d'erreur et stoppera le programme. Vous pouvez aussi capturer et manipuler des erreurs dans vos scripts. Les erreurs peuvent être passées à des fonctions, ou récupérées depuis des fonctions, et affectées à des variables.

Catégories d'erreurs

Il y a plusieurs catégories d'erreurs.

Erreurs de syntaxe

Les erreurs de syntaxe surviennent quand un script REBOL utilise une syntaxe incorrecte. Par exemple, si un crochet fermant est manquant ou qu'une apostrophe ne ferme pas une chaîne de caractère, une erreur de syntaxe va être générée. Ces erreurs se produisent uniquement durant le chargement ou l'évaluation d'un fichier ou d'une chaîne.

Erreurs de script

Les erreurs de script sont en général des erreurs d'exécution. Par exemple, un argument invalide fourni à une fonction causera une erreur de script.

Erreurs mathématiques

Les erreurs mathématiques se produisent quand une opération mathématique ne peut être effectuée. Par exemple, si une division par zéro est tentée, une erreur se produit.

Erreurs d'accès

Les erreurs d'accès apparaissent quand un problème intervient lors de l'accès à un fichier, à un port ou au réseau. Par exemple, une erreur d'accès se produira si vous essayez de lire un fichier qui n'existe pas.

Erreurs utilisateur

Les erreurs utilisateurs sont générées explicitement par un script en créant une valeur d'erreur et en la retournant.

Erreurs internes

Les erreurs internes sont produites par l'interpréteur REBOL.

Capture des erreurs

Vous pouvez récupérer les erreurs avec la fonction try. La fonction try est similaire à la fonction do. Elle évalue un bloc, mais renvoie toujours une valeur, même quand une erreur se produit. Si aucune erreur n'est apparue, la fonction try retourne la valeur du bloc.

Par exemple :


print try [100 / 10]
10

Quand une erreur apparaît, try renvoie cette erreur. Si vous écrivez :


print try [100 / 0]
** Math Error: Attempt to divide by zero.
** Where: 100 / 0

l'erreur est renvoyée par la fonction try et la fonction print n'est pas effectuée.

Pour manipuler les erreurs dans un script, vous devez empêcher REBOL d'évaluer l'erreur. Vous pouvez éviter l'évaluation d'une erreur en la passant à une fonction. Par exemple, la fonction error ? renverra la valeur true si son argument est bien une erreur :


print error? try [100 / 0]
true

Vous pouvez aussi afficher le type de données de la valeur renvoyée par try :


print type? try [100 / 0]
error!

La fonction disarm convertit une erreur en un objet-erreur qui peut être examiné. Dans l'exemple ci-dessous, la variable error fait référence à un objet renvoyé par disarm :


error: disarm try [100 / 0]

Quand une erreur est passée à la fonction disarm, elle est transformée en objet (type de données object !) et n'est plus du type de données error !. L'évaluation de cet objet-erreur devient possible :


probe disarm try [100 / 0]
make object! [
code: 400
type: 'math
id: 'zero-divide
arg1: none
arg2: none
arg3: none
near: [100 / 0]
where: none
]

Les valeurs d'erreur peuvent être affectées à un mot avant d'être passées à la fonction disarm. Pour attribuer un mot à une erreur, celui-ci doit être précédé par une fonction afin d'éviter que l'erreur soit réemployée ailleurs. Par exemple :


disarm err: try [100 / 0]

Associer l'erreur à un mot vous permet de récupérer sa valeur plus tard. L'exemple ci-dessous illustre le cas où il peut y avoir ou non une erreur :


either error? result: try [100 / 0] [
probe disarm result
][
print result
]

L'objet erreur

L'objet erreur montré précédemment a la structure :


make object! [
code: 400
type: 'math
id: 'zero-divide
arg1: none
arg2: none
arg3: none
near: [100 / 0]
where: none
]

avec les champs suivants :

code : Le numéro du code d'erreur. Obsolète, ne devrait plus être utilisé.

type : Le champ type identifie la catégorie d'erreur. Il s'agit toujours d'un mot comme syntax, script, math, access, user, ou internal.

id : la champ id est le nom de l'erreur, sous forme de mot REBOL. Il identifie spécifiquement l'erreur au sein de sa catégorie.

arg1 : Ce champ contient le premier argument du message d'erreur. Par exemple, il peut inclure le type de donnée de la valeur ayant causé l'erreur.

arg2 : Ce champ contient le second argument du message d'erreur.

arg3 : Ce champ contient le troisième argument du message d'erreur.

near : Le champ near est un morceau de code censé indiquer l'endroit où l'erreur s'est produite.

where : Ce champ est un champ réservé.

Vous pouvez écrire du code qui va contrôler chacun des champs de l'objet erreur. Dans cet exemple, l'erreur est affichée seulement si le champ id indique une division par zéro :


error: disarm try [1 / 0]
if error/id = 'zero-divide [
print ^{It is a Divide by Zero error^}
]
It is a Divide by Zero error

Le champ id de l'erreur fournit aussi le bloc qui sera affiché par l'interpréteur. Par exemple :


error: disarm try [print zap]
probe get error/id
[:arg1 "has no value"]

Ce bloc est défini par l'objet system/error.

Générer des erreurs

Il est possible de fabriquer des erreurs pour votre propre usage. Le moyen le plus simple est de les générer en faisant appel à la fonction make. Voici un exemple :


make error! "this is an error"
** User Error: this is an error.
** Where: make error! "this is an error"

N'importe quelle erreur existante peut être générée en la fabriquant avec un argument de type block !. Ce bloc doit contenir le nom de la catégorie d'erreur, et la désignation spécifique (id) de celle-ci. Les arguments arg1, arg2, et arg3 définissent l'erreur dans l'objet erreur créé.

Voici un exemple :


make error! [script expect-set series! number!]
** Script Error: Expected one of: series! - not: number!.
** Where: make error! [script expect-set series! number!]

NdT : ici script fait référence à la catégorie, expect-set à l'id, et series !, number ! sont les arguments.

Les erreurs personnalisées peuvent être incluses dans l'objet system/error, et la catégorie "user". Ceci est réalisé en fabriquant une nouvelle catégorie "user" avec de nouvelles entrées. Ces entrées sont utilisées lorsque des erreurs se produisent. Pour illustrer ceci, l'exemple suivant ajoute une erreur dans la catégorie "user".


system/error/user: make system/error/user [
my-error: "a simple error"
]

A présent, une erreur peut être produite, et utiliser le message de l'id my-error :


if error? err: try [
make error! [user my-error]
] [probe disarm err]
make object! [
code: 803
type: 'user
id: 'my-error
arg1: none
arg2: none
arg3: none
near: [make error! [user my-error]]
where: none
]

Pour créer des erreurs avec plus d'informations, définissez une erreur qui utilise les données courantes lorsqu'elle est générée. Ces données seront incluses dans l'objet erreur, et affichées en tant qu'éléments de cet objet. Par exemple, pour utiliser les trois champs d'arguments dans l'objet erreur :


system/error/user: make system/error/user [
my-error: [:arg1 "doesn't go into" :arg2 "using" :arg3]
]

if error? err: try [
make error! [user my-error [this] "that" my-function]
] [probe disarm err]
make object! [
code: 803
type: 'user
id: 'my-error
arg1: [this]
arg2: "that"
arg3: 'my-function
near: [make error! [user my-error [this] "that" my-function]]
where: none
]

Le message d'erreur produit pour my-error peut être affiché, sans bloquer l'exécution du script :


disarmed: disarm err
print bind (get disarmed/id) (in disarmed 'id)
this doesn't go into that using my-function

Une nouvelle catégorie d'erreur peut aussi être créée si vous avez besoin de grouper un ensemble spécifique d'erreurs :


system/error: make system/error [
my-errors: make object! [
code: 1000
type: "My Error Category"
error1: "a simple error"
error2: [:arg1 "doesn't go into" :arg2 "using" :arg3]
]
]

Le type défini l'objet erreur correspond au type d'erreur affiché quand l'erreur se produit. L'exemple suivant illustre la génération d'erreurs pour deux sortes d'erreurs (error1 et error2) dans la catégorie my-error .

Création d'une erreur à partir d'error1. Cette erreur ne requiert aucun argument.


disarmed: disarm try [make error! [my-errors error1]]
print get disarmed/id
a simple error

La création d'une erreur à partir d'error2 nécessite, elle, trois arguments :


disarmed: disarm try [
make error! [my-errors error2 [this] "that" my-function]]
print bind (get disarmed/id) (in disarmed 'id)
this doesn't go into that using my-function

Et pour finir, la description de la catégorie définie dans my-errors peut être obtenue ainsi :


probe get in get disarmed/type 'type
My Error Category

Messages d'erreurs

La liste ci-dessous présente toutes les erreurs définies dans l'objet system/error :

Erreur de syntaxe

invalid

Les données ne peuvent pas être transposées en un type valide de données REBOL. En d'autres termes, une valeur mal formée a été évaluée.

Message :


["Invalid" :arg1 "--" :arg2]

Exemple :


filter-error try [load "1024AD"]
** Syntax Error: Invalid integer -- 1024AD
** Where: (line 1) 1024AD

missing

Un bloc, une chaîne de caractère ou une expression à parenthèses (paren !) souffre d'un défaut : Une parenthèse, un crochet, un guillemet, ou une accolade manque.

Message :

["Missing" :arg2 "at" :arg1]

Exemple :


filter-error try [load "("]
** Syntax Error: Missing ) at end-of-script
** Where: (line 1) (

header

Une évaluation d'un fichier en tant que script REBOL a été essayée, mais le fichier ne présente pas d'en-tête REBOL (header).

Message :


Script is missing a REBOL header

Exemple :


write %no-header.r ^{print "data"^}
filter-error try [do %no-header.r]
** Syntax Error: Script is missing a REBOL header
** Where: do %no-header.r

Erreurs de script

no-value

Une évaluation a été essayée sur un mot qui n'est pas défini.

Message :


[:arg1 "has no value"]

Example :


filter-error try [undefined-word]
** Script Error: undefined-word has no value
** Where: undefined-word

need-value

Un essai de définir un mot sans rien a été fait. Un set-word (mot à définir) a été utilisé sans argument.

Message :


[:arg1 "needs a value"]

Exemple :


filter-error try [set-to-nothing:]
** Script Error: set-to-nothing needs a value
** Where: set-to-nothing:

no-arg

Une fonction a été évaluée sans lui fournir tous les arguments attendus.

Message :


[:arg1 "is missing its" :arg2 "argument"]

Exemple :


f: func [b][probe b]
filter-error try [f]
** Script Error: f is missing its b argument
** Where: f

expect-arg

Un argument a été fourni à une fonction mais n'était pas du type de données attendu.

Message :


[:arg1 "expected" :arg2 "argument of type:" :arg3]

Exemple :


f: func [b [block!]][probe b]
filter-error try [f "string"]
** Script Error: f expected b argument of type: block
** Where: f "string"

expect-set

Deux valeurs de type serie ! sont utilisées l'une avec l'autre d'une façon non compatible. Par exemple, en tentant la réunion entre une chaîne de caractères et un bloc.

Message :


["Expected one of:" :arg1 "- not:" :arg2]

Exemple :


filter-error try [union [a b c] "a b c"]
** Script Error: Expected one of: block! - not: string!
** Where: union [a b c] "a b c"

invalid-arg

Voici une erreur générique lorsqu'on manipule incorrectement des valeurs. Par exemple, lorsque qu'un set-word est utilisé à l'intérieur du bloc de spécification d'une fonction :

Message :


["Invalid argument:" :arg1]

Exemple :


filter-error try [f: func [word:][probe word]]
** Script Error: Invalid argument: word
** Where: func [word:] [probe word]

invalid-op

Un essai a été fait d'utiliser un opérateur qui a déjà été redéfini. L'opérateur utilisé n'est plus un opérateur valide.

Message :


["Invalid operator:" :arg1]

Exemple :


*: "operator redefined to a string"
filter-error try [5 * 10]
** Script Error: Invalid operator: *
** Where: 5 * 10

no-op-arg

Un opérateur mathématique ou de comparaison a été utilisé sans que ne soit fourni un deuxième argument.

Message :


Operator is missing an argument

Exemple :


filter-error try [1 +]
** Script Error: Operator is missing an argument
** Where: 1 +

no-return

Une fonction attendant d'un bloc une valeur de retour ne peut rien retourner. Par exemple, lors de l'usage des fonctions while et until.

Message :


Block did not return a value

Examples :


filter-error try [ ; first block returns nothing
while [print 10][probe "ten"]
]
10
** Script Error: Block did not return a value
** Where: while [print 10] [probe "ten"]
filter-error try [
until [print 10] ; block returns nothing
]
10
** Script Error: Block did not return a value
** Where: until [print 10]

not-defined

Un mot utilisé n'était pas défini dans quel que contexte que ce soit.

Message :


[:arg1 "is not defined in this context"]

no-refine

Une tentative a été faite d'utiliser pour une fonction un raffinement qui n'existe pas.

Message :


[:arg1 "has no refinement called" :arg2]

Exemple :


f: func [/a] [if a [print "a"]]
filter-error try [f/b]
** Script Error: f has no refinement called b
** Where: f/b

invalid-path

Un essai a été fait d'accéder à une valeur dans un bloc ou un objet en utilisant un path qui n'existe pas au sein du bloc ou de l'objet.

Message :


["Invalid path value:" :arg1]

Exemple :


blk: [a "a" b "b"]
filter-error try [print blk/c]
** Script Error: Invalid path value: c
** Where: print blk/c
obj: make object! [a: "a" b: "b"]
filter-error try [print obj/d]
** Script Error: Invalid path value: d
** Where: print obj/d

cannot-use

Une opération a été exécutée sur une valeur d'un type de données incompatible avec l'opération. Par exemple, en essayant d'ajouter une chaîne de caractères à un nombre.

Message :


["Cannot use" :arg1 "on" :arg2 "value"]

Exemple :


filter-error try [1 + "1"]
** Script Error: Cannot use add on string! value
** Where: 1 + "1"

already-used

Un essai a été fait pour faire un alias avec un mot qui a déjà été utilisé en alias.

Message :


["Alias word is already in use:" :arg1]

Exemple :


alias 'print "prink"
filter-error try [alias 'probe "prink"]
** Script Error: Alias word is already in use: prink
** Where: alias 'probe "prink"

out-of-range

Un essai est fait de modifier un index invalide d'une série.

Message :


["Value out of range:" :arg1]

Exemple :


blk: [1 2 3]
filter-error try [poke blk 5 "five"]
** Script Error: Value out of range: 5
** Where: poke blk 5 "five"

past-end

Une tentative d'accès à une série au delà de la longueur de la série.

Message :


Out of range or past end

Exemple :


blk: [1 2 3]
filter-error try [print fourth blk]
** Script Error: Out of range or past end
** Where: print fourth blk

no-memory

Le système ne dispose plus d'assez de mémoire pour terminer l'opération.

Message :


Not enough memory

wrong-denom

Une opération mathématique a été effectuée sur des valeurs monétaires de dénominations différentes. Par exemple, en tentant d'ajouter USD$1.00 à DEN$1.50.

Message :


[:arg1 "not same denomination as" :arg2]

Exemple :


filter-error try [US$1.50 + DM$1.50]
** Script Error: US$1.50 not same denomination as DM$1.50
** Where: US$1.50 + DM$1.50

bad-press

Une tentative pour décompresser une valeur binaire corrompue ou en format non compressé.

Message :


["Invalid compressed data - problem:" :arg1]

Exemple :


compressed: compress ^{some data^}
change compressed "1"
filter-error try [decompress compressed]
** Script Error: Invalid compressed data - problem: -3
** Where: decompress compressed

bad-port-action

Une tentative pour effectuer une action non supportée sur un port. Par exemple, en tentant d'utiliser find sur un port TCP.

Message :


["Cannot use" :arg1 "on this type port"]

needs

Se produit lors de l'exécution d'un script qui nécessite une nouvelle version de REBOL ou quand un fichier ne peut être trouvé. Cette information devra être trouvée dans l'en-tête du script REBOL.

Message :


["Script needs:" :arg1]

locked-word

Apparaît lorsqu'une tentative est faite visant à modifier un mot protégé. Le mot devra avoir été protégé avec la fonction protect.

Message :


["Word" :arg1 "is protected, cannot modify"]

Exemple :


my-word: "data"
protect 'my-word
filter-error try [my-word: "new data"]
** Script Error: Word my-word is protected, cannot modify
** Where: my-word: "new data"

dup-vars

Une fonction a été évaluée et possède plusieurs occurrences du même mot défini dans son bloc de spécification. Par exemple, si le mot arg a été défini à la fois comme premier et second argument.

Message :


["Duplicate function value:" :arg1]

Exemple :


filter-error try [f: func [a /local a][print a]]
** Script Error: Duplicate function value: a
** Where: func [a /local a] [print a]

Erreurs d'accès

cannot-open

Un fichier ne peut être ouvert. Il peut s'agir d'un fichier en local ou en réseau. L'une des raisons la plus courante est la non existence du répertoire.

Message :


["Cannot open" :arg1]

Exemple :


filter-error try [read %/c/path-not-here]
** Access Error: Cannot open /c/path-not-here
** Where: read %/c/path-not-here

not-open

Un essai a été fait d'utiliser un port qui était fermé.

Message :


["Port" :arg1 "not open"]

Exemple :


p: open %file.txt
close p
filter-error try [copy p]
** Access Error: Port file.txt not open
** Where: copy p

already-open

Se produit lorsqu'on essaye d'ouvrir un port déjà ouvert.

Message :


["Port" :arg1 "already open"]

Exemple :


p: open %file.txt
filter-error try [open p]
** Access Error: Port file.txt already open
** Where: open p

already-closed

Se produit lorsqu'on essaye de fermer un port qui a déjà été fermé.

Message :


["Port" :arg1 "already closed"]

Exemple :


p: open %file.txt
close p
filter-error try [close p]
** Access Error: Port file.txt not open
** Where: close p

invalid-spec

Apparaît lorsqu'on essaye de créer un port avec la fonction make, en utilisant des spécifications incorrectes ou inadaptées ne permettant pas de le créer.

Message :


["Invalid port spec:" :arg1]

Exemple :


filter-error try [p: make port! [scheme: 'naughta]]
** Access Error: Invalid port spec: scheme naughta
** Where: p: make port! [scheme: 'naughta]

socket-open

Le système d'exploitation ne dispose plus de sockets à allouer.

Message :


["Error opening socket" :arg1]

no-connect

Une connexion défectueuse avec une autre machine. C'est une erreur générique qui couvre plusieurs situations possibles d'erreur lors de la connexion. Si une raison plus précise est connue, une erreur plus spécifique est générée.

Message :


["Cannot connect to" :arg1]

Exemple :


filter-error try [read http://www.host.dom/]
** Access Error: Cannot connect to www.host.dom
** Where: read http://www.host.dom/

no-delete

Se produit lorsqu'on essaye de supprimer un fichier qui est utilisé par un autre processus, ou protégé.

Message :


["Cannot delete" :arg1]

Exemple :


p: open %file.txt
filter-error try [delete %file.txt]
** Access Error: Cannot delete file.txt
** Where: delete %file.txt

no-rename

Une tentative a été faite de renommer un fichier utilisé par un autre processus ou protégé.

Message :


["Cannot rename" :arg1]

Exemple :


p: open %file.txt
filter-error try [rename %file.txt %new-name.txt]
** Access Error: Cannot rename file.txt
** Where: rename %file.txt %new-name.txt

no-make-dir

Une tentative de création d'un répertoire avec un chemin (path) qui n'existe pas ou qui a été protégé en écriture.

Message :


["Cannot make directory" :arg1]

Exemple :


filter-error try [make-dir %/c/no-path/dir]
** Access Error: Cannot make directory /c/no-path/dir/
** Where: m-dir path return path

timeout

Le délai de time-out s'est écoulé sans qu'une réponse ait été reçue d'une autre machine. Le time-out est défini dans l'attribut timeout du port.

Message :


Network timeout

new-level

Une tentative a été faite dans un script d'abaisser la sécurité, vers un niveau qui a été interdit. Lorsqu'un script demande à abaisser le niveau de sécurité et que l'utilisateur refuse, cette erreur est générée.

Message :


["Attempt to change security level to" :arg1]

Exemple :


secure quit
filter-error try [secure none] ; denied request
secure none

security

Une violation de sécurité s'est produite. Ceci arrive lorsqu'une tentative d'accès à un fichier ou au réseau est réalisée, avec un niveau de sécurité positionné sur "throw".

Message :


REBOL - Security Violation

Exemple :


secure throw
filter-error try [open %file.txt]
** Access Error: REBOL - Security Violation
** Where: open %file.txt
secure none

invalid-path

Un path mal formé a été employé.

Message :


["Bad file path:" :arg1]

Exemple :


filter-error try [read %/]

Erreurs internes

bad-path

Un chemin commençant par un mot invalide a été évalué.

Message :


["Bad path:" arg1]

Exemple :


path: make path! [1 2 3]
filter-error try [path]
** Internal Error: Bad path: 1
** Where: path

not-here

Se produit lorsqu'on essaye d'utiliser des caractéristiques de REBOL/Command ou de REBOL/View à partir de REBOL/Core.

Message :


[arg1 "not supported on your system"]

stack-overflow

Un débordement de la mémoire du système en exécutant une opération.

Message :


["Stack overflow"]

Exemple :


call-self: func [][call-self]
filter-error try [call-self]
** Internal Error: Stack overflow
** Where: call-self

globals-full

Le nombre maximum autorisé de définitions de mots globaux a été dépassé.

Message :


["No more global variable space"]

Manuel de l'utilisateur - Annexe 1 - Les valeurs

Historique de la traduction

Date Version Commentaires Auteur Email
18 Août 2005 21:02 1.0.0 Traduction initiale Philippe Le Goff lp—legoff—free—fr

Valeurs relatives aux nombres

Decimal

Concept

Le type de données decimal ! est basé sur le standard IEEE, c'est à dire des nombres sur 64 bits en virgule flottante. Ils se distinguent des nombres entiers via le séparateur décimal (un point, ou une virgule, peuvent être utilisés pour un usage international, voir les notes ci-dessous).

Format

Les valeurs décimales sont une séquence de chiffres numériques suivis par un point ou une virgule, puis encore d'autres chiffres.

Un signe (+) ou (-) présent immédiatement avant le premier chiffre indique le signe (positif ou négatif). Les zéros présents avant le séparateur des décimales sont ignorés. Les espaces, les points virgules et les points en trop ne sont pas autorisés.


1.23
123.
123.0
0.321
0.123
1234.5678

Une virgule (elle est la norme dans de nombreux pays) peut être utilisée au lieu d'un point pour représenter le séparateur décimal


1,23
0,321
1234,5678

Utilisez une apostrophe simple (`) pour séparer les chiffres dans les grands nombres décimaux. Les apostrophes simples peuvent apparaître après le premier chiffre dans le nombre, mais pas avant ce premier chiffre.


100'234'562.3782
100'234'562,3782

La notation scientifique peut être utilisée pour spécifier l'exposant d'un nombre en ajoutant au nombre la lettre E ou e suivie d'une série de chiffres. L'exposant peut être un nombre positif ou négatif.


1.23E10
1.2e007
123.45e-42
56,72E300
-0,34e-12
0.0001e-001

Les nombres décimaux s'étendent de 2.2250738585072e-308 jusqu'à 1.7976931348623e+308 et peuvent avoir une précision sur 15 chiffres.

Création

Utilisez la fonction to-decimal pour convertir une chaîne de caractère (string !), un nombre entier (integer !), un bloc (block !), ou type de données decimal ! en nombre décimal :


probe to-decimal "123.45"
123.45
probe to-decimal 123
123
probe to-decimal [-123 45]
-1.23E+47
probe to-decimal [123 -45]
1.23E-43
probe to-decimal -123.8
-123.8
probe to-decimal 12.3
12.3

Si un nombre décimal et un nombre entier sont combinés dans une expression, le nombre entier est converti en nombre décimal :


probe 1.2 + 2
3.2
probe 2 + 1.2
3.2
probe 1.01 > 1
true
probe 1 > 1.01
false

Infos connexes

Utilisez decimal ? pour déterminer si une valeur est bien du type de données decimal ! :


print decimal? 0.123
true

Utilisez les fonctions form, print et mold avec un nombre en argument pour afficher la valeur décimale dans sa forme la plus réduite :
entière s'il est possible de l'afficher ainsi.
décimal sans exposant s'il n'est pas trop grand ou trop petit.
en notation scientifique s'il est trop grand ou trop petit.

Par exemple ,


probe mold 123.4
123.4
probe form 2222222222222222
2.22222222222222E+15
print 1.00001E+5
100001

Les apostrophes simples (quotes) et un signe "plus" (+) précédant le nombre n'apparaissent pas dans l'affichage d'un décimal :


print +1'100'200.222'112
1100200.222112

Integer

Concept

Le type de données integer ! caractérise les nombres positifs et négatifs (et zéro) sur 32 bits. Contrairement aux nombres décimaux, les nombres entiers ne contiennent pas de décimales.

Format

Les valeurs entières consistent en une séquence de chiffres. Un signe plus (+) ou un signe moins (-) placé immédiatement avant le premier chiffre indique le signe. (Il ne peut y avoir d'espace entre le signe et le premier chiffre). Les zéros qui précédent le premier chiffre sont ignorés.


0
1234
+1234
-1234
00012
-0123

N'utilisez pas de points, ni de virgules dans les entiers. Si une virgule ou un point est trouvé dans un entier, celui-ci sera interprété comme une valeur décimale. D'autre part, vous pouvez utilisez une apostrophe (`) pour séparer les chiffres dans les grands nombres entiers. Les apostrophes peuvent apparaître n'importe où après le premier chiffre dans le nombre, mais pas avant ce premier chiffre.


2'147'483'647

Les nombres entiers varient entre -2147483648 et 2147483647.

Création

Utilisez la fonction to-integer pour convertir un type de données string !, logic !, decimal !, ou integer ! en un entier :


probe to-integer "123"
123
probe to-integer false
0
probe to-integer true
1
probe to-integer 123.4
123
probe to-integer 123.8
123
probe to-integer -123.8
-123

Si un décimal et un entier sont combinés dans une expression, le nombre entier sera converti en nombre décimal :


probe 1.2 + 2
3.2
probe 2 + 1.2
3.2
probe 1.01 > 1
true
probe 0 < .001
true

Infos connexes

Utilisez integer ? pour déterminer si une valeur a pour type de données integer !.


probe integer? -1234
true

Utilisez les fonctions form, print et mold avec un argument de type integer ! pour afficher la valeur entière sous forme d'une chaîne de caractères :


probe mold 123
123
probe form 123
123
print 123
123

Les entiers qui sont en dehors de l'intervalle décrit plus haut ou qui ne peuvent être représentés sur 32 bits génèrent une erreur.

Valeurs relatives aux séries

Binary

Concept

Les valeurs binaires comprennent arbitrairement des données binaires de n'importe quel type. N'importe quelle séquence d'octets peut être stockée, comme une image, un son, un fichier exécutable, des données compressées, et des données cryptées.

Format

Les chaînes binaires sont écrites sous la forme d'un signe (#) dièse, suivi d'une chaîne de caractères incluse entre deux accolades. Les caractères au sein de la chaîne sont encodés dans l'un des divers formats comme l'indique le nombre (optionnel) qui précède le signe (#).

Le codage en base 16 (hexadécimal) est le format par défaut.


#^{3A18427F 899AEFD8^} ; default base-16
2#^{10010110110010101001011011001011^} ; base-2
64#^{LmNvbSA8yw9CB0aGvXmgUkVCu2Uz934b^} ; base-64

Les espaces, les tabulations et les sauts de lignes sont autorisés dans la chaîne. Une donnée binaire peut s'étendre sur plusieurs lignes.


probe #^{
3A
18
92
56
^}
#^{3A189256^}

Les chaînes de caractères, pour lesquelles manquent des caractères permettant de retrouver un résultat binaire correct, sont décalées sur la droite (au niveau des bits).

Création

La fonction to-binary convertit des données dans le type binary !, avec l'encodage existant par défaut dans system/options/binary-base :


probe to-binary "123"
#^{313233^}
probe to-binary "today is the day..."
#^{746F64617920697320746865206461792E2E2E^}

Pour convertir un nombre entier en son équivalent en valeur binaire, mettez-le dans un bloc :


probe to-binary [1]
#^{01^}
probe to-binary [11]
#^{0B^}

La conversion d'une série de nombres entiers en binaire se fait par la conversion de chacun des entiers, et en concaténant l'ensemble en une seule valeur binaire :


probe to-binary [1 1 1 1]
#^{01010101^}

Infos supplémentaires

L'usage de la fonction binary ? permet de déterminer si une valeur est de type de données binary !.


probe binary? #^{616263^}
true

Les valeurs binaires font partie du type series ! :


probe series? #^{616263^}
true
probe length? #^{616263^} ; three hex values in this binary
3

Les fonctions enbase et debase sont très importantes dans la manipulation des valeurs de type binary !. La fonction enbase convertit des chaînes en leur représentation en base-2, en base 16 ou en base 64. La fonction debase transforme des chaînes codées en une valeur binaire, en utilisant la base numérique spécifiée dans system/options/binary-base.

Block

Concept

Les blocs sont des groupes de valeurs et de mots. Les blocs sont utilisés partout, comme depuis un script lui-même jusqu'aux blocs de données et de code fournis dans le script. Les valeurs de type block sont indiquées avec des crochets ouvrants et fermants ([ ]) et une quantité variable de datas contenues entre eux.


[123 data "hi"] ; bloc avec des datas
[] ; bloc vide

Les blocs peuvent permettre de manipuler des enregistrements :


woodsmen: [
"Paul" "Bunyan" paul@bunyan.dom
"Grizzly" "Adams" grizzly@adams.dom
"Davy" "Crocket" davy@crocket.dom
]

Les blocs peuvent contenir du code :


[print "this is a segment of code"]

Les blocs sont également rattachés au type series !, et tout ce qui peut être réalisé avec une série peut l'être aussi avec un bloc.

Il est possible d'effectuer des recherches dans des blocs :


probe copy/part (find woodsmen "Grizzly") 3
[
"Grizzly" "Adams" grizzly@adams.dom]

Les blocs peuvent être modifiés :


append woodsmen [
"John" "Muir" john@muir.dom
]
probe woodsmen
[
"Paul" "Bunyan" paul@bunyan.dom
"Grizzly" "Adams" grizzly@adams.dom
"Davy" "Crocket" davy@crocket.dom
"John" "Muir" john@muir.dom
]

Les blocs peuvent être évalués :


blk: [print "data in a block"]
do blk
data in a block

Les blocs peuvent contenir d'autres blocs :


blks: [
[print "block one"]
[print "block two"]
[print "block three"]
]
foreach blk blks [do blk]
block one
block two
block three

Format

Les blocs peuvent contenir un nombre variable de valeurs ou aucune valeur. Ils peuvent s'étendre sur plusieurs lignes et peuvent inclure n'importe quel type de valeurs, y compris d'autres blocs.

Un bloc vide :


[ ]

Un bloc de nombres entiers :


[24 37 108]

Un en-tête (header) REBOL :


REBOL [
Title: "Test Script"
Date: 31-Dec-1998
Author: "Ima User"
]

Un bloc conditionnel et un bloc évalué d'une fonction :


while [time < 10:00] [
print time
time: time + 0:10
]

Les mots dans un bloc ont besoin d'être définis :


blk: [undefined words in a block]
probe value? pick blk 1
false

Les blocs autorisent n'importe quel nombre de lignes, d'espaces, ou de tabulations. Les lignes et les espaces peuvent être placés n'importe où au sein du bloc, tant qu'ils ne segmentent pas des valeurs.

Création

La fonction to-block convertit une data en une valeur de type de données block ! :


probe to-block luke@rebol.com
[luke@rebol.com]
probe to-block ^{123 10:30 "string" luke@rebol.com^}
[123 10:30 "string" luke@rebol.com]

Autres informations

Utilisez block ? pour déterminer si une valeur est ou non du datatype block ! .


probe block? [123 10:30]
true

Les blocs étant un sous-ensemble du pseudo type series !, vous pouvez utilisez series ? pour vérifier qu'un bloc est bien de ce type :


probe series? [123 10:30]
true

L'usage de la fonction form sur une valeur de type block ! produit une chaîne de caractères à partir du contenu du bloc :


probe form [123 10:30]
123 10:30

L'usage de la fonction mold sur une valeur de type block a pour effet, elle, de créer une chaîne de caractères avec le contenu du bloc, comme form, mais en permettant que le résultat soit récupérable sous forme d'un bloc REBOL :


probe mold [123 10:30]
[123 10:30]

Les types de données hash ! et list ! sont très similaires au type block !. Ils sont utilisables de la même façon que les valeurs de type block ! mais possèdent des caractéristiques particulières. Les valeurs de type list ! sont conçues pour permettre des modifications de listes plus rapidement que les valeurs block !, et les valeurs de type hash ! permettent de gérer des tris et l'indexation de données. Ils sont assez commodes lorsqu'on se sert de jeux de données importants.

Email

Concept

Une adresse email est un type de données. En REBOL, le type de données email ! exprime facilement ce que représente des adresses email.


send luke@rebol.com ^{some message^}

emails: [
john@keats.dom
lord@byron.dom
edger@guest.dom
alfred@tennyson.dom
]
mesg: ^{poetry reading at 8:00pm!^}
foreach email emails [send email mesg]

Le type de données email ! fait partie aussi du type series !, de sorte que les règles s'appliquant aux séries s'appliquent aussi aux valeurs de type email ! :


probe head change/part jane@doe.dom "john" 4
john@doe.dom

Format

Le format standard d'une adresse email est le suivant : un nom, suivi du symbole arobase (@), suivi d'un nom de domaine. Une adresse email peut être de n'importe quelle longueur, mais ne doit pas comprendre un seul caractère non autorisé comme les crochets, les apostrophes (quotes), les accolades, les espaces, les caractères de fin de ligne, etc.

Les valeurs suivantes ont un format valide pour le type de données email ! :


info@rebol.com
123@number-mail.org
my-name.here@an.example-domain.com

Les caractères minuscules et majuscules sont conservés dans les adresses email.

Raffinements

Deux raffinements peuvent être utilisés avec une valeur email ! pour récupérer le nom d'utilisateur ou le domaine. Ces raffinements sont :

/user : Récupère le nom d'utilisateur.

/host : Récupère le domaine.

Voici quelques illustrations du fonctionnement de ces raffinements :


email: luke@rebol.com
probe email/user
luke
probe email/host
rebol.com

Création

La fonction to-email transforme une donnée en une valeur de type email ! :


probe to-email "info@rebol.com"
info@rebol.com
probe to-email [info rebol.com]
info@rebol.com
probe to-email [info rebol com]
info@rebol.com
probe to-email [user some long domain name out there dom]
user@some.long.domain.name.out.there.dom

Autres Informations

Utilisez la fonction email ? pour déterminer si une valeur est de type email !.


probe email? luke@rebol.com
true

Le type de donnée email ! étant un sous-ensemble du type de donnée series !, vous pouvez aussi utilisez series ? pour savoir si la valeur testée est une série :


probe series? luke@rebol.com
true
probe pick luke@rebol.com 5
#"@"

File

Concept

Le type de données file ! peut concerner un nom de fichier, un nom de répertoire ou un chemin complet dans une arborescence (path).


%file.txt
%directory/
%directory/path/to/some/file.txt

Les valeurs de type file ! sont aussi des séries et peuvent être manipulées comme telles :


probe find %dir/path1/path2/file.txt "path2"
%path2/file.txt
f: %dir/path/file.txt
probe head remove/part (find f "path/") (length? "path/")
%dir/file.txt

Format

Les fichiers se caractérisent par un signe "pourcentage" (%) suivi par une suite de caractères :


load %image.jpg
prog: load %examples.r
save %this-file.txt "This file has few words."
files: load %../programs/

Les caractères "inhabituels" dans les noms de fichiers doivent être encodés avec leurs équivalents hexadécimaux selon la convention en vigueur sur Internet. Un nom de fichier avec un espace (en hexadécimal : %20) devrait ressembler à ceci :


probe %cool%20movie%20clip.mpg
%cool%20movie%20clip.mpg
print %cool%20movie%20clip.mpg
cool movie clip.mpg

Une autre possibilité est d'englober le nom de fichier entre deux apostrophes :


probe %"cool movie clip.mpg"
%cool%20movie%20clip.mpg
print %"cool movie clip.mpg"
cool movie clip.mpg

Le caractère standard pour séparer des répertoires dans un chemin est le caractère slash (/), et NON le backslash (\). Cependant, le langage REBOL transforme automatiquement les symboles backslash trouvés dans les noms de fichiers en caractères slash :


probe %\some\path\to\some\where\movieclip.mpg
%/some/path/to/some/where/movieclip.mpg

Création

La fonction to-file transforme une donnée en une valeur de type de données file ! :


probe to-file "testfile"
%testfile

Lorsqu'un bloc est passé en argument à to-file, les éléments du bloc sont concaténés pour former un chemin de fichier, le dernier élément du bloc servant de nom de fichier :


probe to-file [some path to a file the-file.txt]
%some/path/to/a/file/the-file.txt

Autres informations

Utilisez la fonction file ? pour savoir si une valeur est de type file ! :


probe file? %rebol.r
true

Comme le type file ! est un sous-ensemble de series !, la fonction series ? est aussi utilisable :


probe series? %rebol.r
true

Hash

Concept

Un hash est un bloc présentant une organisation particulière afin d'y trouver très rapidement des données. Lorsqu'une recherche est réalisée sur une valeur de type hash !, celle-ci est réalisée en utilisant une indexation spécifique à la table, qui permet pour de grands blocs, d'accélèrer la recherche d'un facteur 100 et plus.

Format

Les blocs de type hash ! doivent être construits en utilisant la fonction make ou la fonction to-hash. Il n'y a pas de format spécifique.

Création

Utilisez make pour initialiser un hash :


hsh: make hash! 10 ; alloue un espace pour 10 élements

La fonction to-hash transforme une donnée en une valeur de type hash !.

Transformer un bloc :


blk: [1 "one" 2 "two" 3 "three" 4 "four"]
probe hash: to-hash blk
make hash! [1 "one" 2 "two" 3 "three" 4 "four"]
print select hash 2
two

Transformer diverses valeurs :


probe to-hash luke@rebol.com

probe to-hash 123.5

probe to-hash ^{123 10:30 "string" luke@rebol.com^}

Autres infos

Utilisez hash ? pour tester le type de données.


hsh: to-hash [1 "one" 2 "two" 3 "three" 4 "four"]
probe hash? Hsh
true

Le type hash ! étant un sous-ensemble du type series !, la fonction series ? peut là encore être utilisée :


probe series? hsh
true

L'usage de la fonction form sur une valeur de type hash renvoie une chaîne de caractères composée avec le contenu du hash :


probe form hsh
"1 one 2 two 3 three 4 four"

Avec la fonction mold, on crée une chaîne de caractère avec la valeur hash et son contenu, mais celle-ci peut être récupérable sous forme d'une valeur de type hash pour REBOL :


probe mold hsh
make hash! [1 "one" 2 "two" 3 "three" 4 "four"]

Image

Concept

Le type de données image ! permet la manipulation des images RGB. Ce datatype est utilisé avec REBOL/View. Les formats d'image supportés sont le GIF, le JPEG, et le BMP. Les images chargées en mémoire peuvent être manipulées comme des séries.

Format

Les images sont en principe chargées à partir d'un fichier. Cependant, elles peuvent être exprimées sous forme de code source, ou aussi fabriquées. L'exemple suivant illustre l'exemple d'une image exprimée sous forme d'un bloc incluant la taille de l'image et les données RGB.


image: make image! [192x144 #^{
B34533B44634B44634B54735B7473
84836B84836B84836BA4837BA4837
BC4837BC4837BC4837BC4837BC483 ...
^}

Création

Des images "vides" peuvent être créées avec les fonctions make ou to-image :


empty-img: make image! 300x300
empty-img: to-image 150x300

La taille de l'image est fournie.

Les images peuvent aussi être créées avec des copies d'écran ou des objets de type 'face. Par exemple, en utilisant make ou to-image :


face-shot: make image! face
face-shot: to-image face

Utilisez la fonction load pour charger en mémoire une image à partir d'un fichier. Si le format de l'image n'est pas supporté, le chargement n'aura pas lieu.

Pour charger en mémoire une image :


img: load %bay.jpg

Autres informations

Utilisez la fonction image ? pour savoir si une valeur est ou non du type image ! :


probe image? img

Les valeurs de type image ! sont des séries :


probe series? img

Le raffinement /size renvoie la taille de l'image sous la forme d'une valeur de type pair ! :


probe img/size

Les valeurs des pixels d'une image sont obtenus en utilisant la fonction pick et modifiées avec poke. La valeur retournée par la fonction pick est un tuple RGB. (voir plus loin les tuples). La valeur remplacée avec la fonction poke doit elle aussi être un tuple RGB.

Récupérer des pixels spécifiques :


probe pick img 1

probe pick img 1500

Modifier des pixels particuliers :


poke img 1 255.255.255
probe pick img 1

poke img 1500 0.0.0
probe pick img 1500

Issue

Concept

Une valeur de type issue ! consiste en une série de caractères utilisés pour mettre en forme des choses comme des numéros de téléphones, des numéros de séries ou de modèles, des numéros de cartes de crédits.

Les valeurs de type issue ! sont un sous-ensemble de celles de type series !, et peuvent être manipulées comme telles :


probe copy/part find #888-555-1212 "555" 3
#555

Format

Les valeurs de type issue ! commencent avec le signe dièse (#) et continuent avec une série de caractères jusqu'au premier caractère délimiteur (comme l'espace) trouvé.


#707-467-8000
#A-0987654321-CD-09876
#1234-5678-4321-8765
#MG82/32-7

Les valeurs qui contiennent des caractères délimiteurs devraient être écrites sous forme de chaînes de caractères plutôt que sous forme d'"issues".

Création

La fonction to-issue transforme une donnée en une valeur de datatype issue !.


probe to-issue "1234-56-7890"
#1234-56-7890

Autres informations

Utilisez issue ? pour savoir si une valeur est ou non du type de donnée issue !.


probe issue? #1234-56-7890
true

Comme les valeurs "issues" sont un sous-ensemble de valeurs series, la fonction series ? s'applique aussi :


probe series? #1234-56-7890
true

La fonction form renvoie une chaîne de caractères constituée par la séquence de caractères de la valeur issue ! mais sans le signe (#) :


probe form #1234-56-7890
1234-56-7890

La fonction mold s'utilise comme la fonction form, elle renvoie une chaîne pouvant être interprétée par REBOL comme une valeur issue ! :


probe mold #1234-56-7890
#1234-56-7890

La fonction print permet d'afficher une valeur de type issue ! après un "reform" sur celle-ci :


print #1234-56-7890
1234-56-7890

List

Concept

Les listes sont des énumérations sous formes de blocs qui permettent des ajouts et des suppressions très efficaces en terme de performances. Elles peuvent être utilisables dans les cas où de nombreuses modifications sont à effectuer sur de grands volumes de données (grands blocs).

Format

Les listes doivent être construites en utilisant la fonction make ou la fonction to-list. Il n'y a pas de format lexical spécifique.

Les valeurs de type list ! ne sont pas des subsituts aux valeurs block !. Il existe quelques différences entre les blocs et les listes :

L'insertion dans une liste modifie son index, que se positionne juste après le point d'insertion. La suppression d'un élément référencé dans une liste conduit à remettre à jour la position finale de la liste (tail).

Les exemples suivants montre la différence de comportement entre l'insertion dans un bloc et dans une liste.

Initialisation d'un bloc et d'une liste :


blk: [1 2 3]

lst: to-list [1 2 3]

Insertion dans un bloc et dans une liste :


insert blk 0

insert lst 0

Regardez le mot dans le bloc et dans la liste juste après l'insertion. Remarquez que le bloc blk pointe sur la tête du bloc (head), comme avant l'insertion de la valeur 0, mais la liste lst pointe sur la position juste après le point d'insertion :


print blk
0 1 2 3
print lst
1 2 3
print head lst
0 1 2 3

Les exemples suivants montrent la différence entre un bloc et une liste, lors de la suppression d'un élément.

Initialisation du bloc et de la liste :


blk: [1 2 3]

lst: to-list [1 2 3]

Suppression au sein du bloc et de la liste :


remove blk

remove lst

Si on regarde l'état du bloc et de la liste, on constate qu'à présent la liste lst pointe sur la fin de la série (tail) :


print blk
2 3
print tail? lst
true
print head lst
2 3

Si vous ne voulez pas pointer sur la fin de la série, après avoir supprimé une valeur, il convient de vous déplacer dans la série et d'enlever la valeur après l'index courant. L'exemple suivant illustre cela :

Initialisation de la liste :


lst: to-list [1 2 3]

Déplacement dans la série et suppression de la valeur après l'index courant :


remove back (lst: next lst)

Si on regarde à l'endroit où la valeur a été supprimée :


probe lst
make list! [2 3]
print tail? lst
false

Création

Il faut utiliser la fonction make pour initialiser une valeur de type list ! :


lst: make list! 10 ; alloue de l'espace pour 10 éléments

La fonction to-list convertit son argument en une valeur de type de donnée list ! :

Pour transformer un bloc :


blk: [1 "one" 2 "two" 3 "three" 4 "four"]
probe to-list blk
make list! [1 "one" 2 "two" 3 "three" 4 "four"]

Informations complémentaires

Utilisez list ? pour déterminer si une valeur est ou non du type de données list !.


lst: to-list [1 "one" 2 "two" 3 "three" 4 "four"]
probe list? Lst
true

Puisque les listes sont aussi des séries, la fonction series ? est aussi utile :


probe series? lst
true

L'usage de la fonction form sur une liste génère une chaîne de caractères composée à partir du contenu de la liste :


probe form lst
"1 one 2 two 3 three 4 four"

Avec la fonction mold, c'est presque comme pour form, si ce n'est que le résultat peut être immédiatement récupérable par REBOL sous forme d'une valeur list ! :


probe mold lst
make list! [1 "one" 2 "two" 3 "three" 4 "four"]

Paren

Concept

Une valeur de type paren ! est un bloc (Ndt : avec usage de parenthèses) qui est immédiatement évalué. Cette valeur est en tous points identique à un bloc, à l'exception du fait qu'elle est évaluée lorsqu'elle est rencontrée, et que le résultat de l'évaluation est retourné. Lorsqu'on l'utilise à l'intérieur d'une expression à évaluer, une valeur de type paren ! permet de contrôler l'ordre de l'évaluation.


print 1 + (2 * 3)
7
print 1 + 2 * 3
9

Comme pour un bloc, une valeur de type paren ! peut être modifiée. Cependant, si on souhaite faire référence à cette valeur paren !, des précautions doivent être prises pour éviter qu'elle soit évaluée.

Si vous stockez une valeur paren ! dans une variable, vous devrez utilisez la forme get-word (c'est-à-dire :word) pour prévenir une éventuelle évaluation. Les "parens" étant un sous-ensemble des séries, ce qui peut être fait avec une série est aussi possible avec une valeur paren !.


paren: first [(1 + 2 * 3 / 4)]
(1 + 2 * 3 / 4)
print type? :paren
paren
print length :paren
7
print first :paren
1
print last :paren
4
insert :paren [10 + 5 *]
probe :paren
(10 + 5 * 1 + 2 * 3 / 4)
print paren
12.75

Format

Les valeurs de type paren ! sont identifiées par des parenthèses ouvrantes et fermantes. Elles peuvent s'étendre sur plusieurs lignes et contenir n'importe quelle donnée, dont d'autres valeurs paren !.

Création

Le fonction make peut être utilisée pour définir une valeur paren ! :


paren: make paren! 10
insert :paren 10
insert :paren `+
insert :paren 20

print :paren
20 + 10
print paren
30

La fonction to-paren transforme une donnée en une valeur de datatype paren ! :


probe to-paren "123 456"
(123 456)
probe to-paren [123 456]
(123 456)

En plus

Utilisez paren ? pour tester le type de la donnée.


blk: [(3 + 3)]
probe pick blk 1
(3 + 3)
probe paren? pick blk 1
true

Comme les parens sont un sous-ensemble de celui des séries, il est possible d'utiliser series ? :


probe series? pick blk 1
true

L'utilisation de form sur une valeur de type paren ! crée une chaîne de caractères à partir du contenu de cette valeur :


probe form pick blk 1
3 + 3

Path

Concept

Les paths (NdT : on pourrait traduire par "chemins"), l'idée générale étant d'avoir une valeur en REBOL qui traduit l'idée de se déplacer dans une arborescence, ou de préciser une particularité d'une fonction, par exemple) sont un ensemble de mots et de valeurs délimités par des slashs (/).

Les paths sont utilisés pour naviguer vers quelque chose, préciser ou trouver quelque chose.

Les mots et les valeurs d'un path sont appelés des raffinements, et ils sont assemblés pour donner une direction, un sens de "navigation" au travers d'une valeur ou d'une fonction. Les paths sont utilisés avec les blocs, les fichiers, les chaînes de caractères, les listes, les hashs, les fonctions, et les objets.

La façon dont les paths agissent dépend du type de données avec lesquels ils sont utilisés.

Les paths peuvent être utilisés pour sélectionner des valeurs dans des blocs, ou des caractères dans une chaîne, accéder à des variables dans des objets, donner un comportement particulier à une fonction :

Type de path Action
USA/CA/Ukiah/size sélection dans un bloc
names/12 position dans une chaîne
account/balance fonction dans un objet
match/any raffinement d'une fonction

L'exemple ci-dessous montre la simplicité d'usage qu'offre un path pour accéder aux informations d'une mini base de données créées à partir de quelques blocs :


towns: [
Hopland [
phone #555-1234
web http://www.hopland.ca.gov
]

Ukiah [
phone #555-4321
web http://www.ukiah.com
email info@ukiah.com
]
]

print towns/ukiah/web
http://www.ukiah.com

Résumé des concepts de paths :

Type de path Type de mot Type de Test Fonction de conversion
path/word : set-path ! set-path ? to-set-path
path/word path ! path ? to-path
'path/word lit-path ! lit-path ? to-lit-path

Exemples de paths :

Pour évaluer une fonction (une méthode) liée à un objet :


obj: make object! [
hello: func [] [print "hello! hello!"]
]
obj/hello
hello! hello!

Pour évaluer un attribut d'un objet :


obj: make object! [
text: "do you believe in magic?"
]
probe obj/text
do you believe in magic?

Des raffinements de fonction :


hello: func [/again] [
print either again ["hello again!"]["hello"]
]
hello/again
hello again!

Pour effectuer une sélection à partir de blocs :


USA: [
CA [
Ukiah [
population 15050
elevation [610 feet]
]
Willits [
population 5073
elevation [1350 feet]
]
]
]
print USA/CA/Ukiah/population
15050
print form USA/CA/Willits/elevation
1350 feet

Pour récupérer des éléments à partir d'une série, via leur position numérique dans celle-ci :


string-series: "abcdefg"
block-series: ["John" 21 "Jake" 32 "Jackson" 43 "Joe" 52]
block-with-sub-series: [ "abc" [4 5 6 [7 8 9]]]
probe string-series/4
#"d"
probe block-series/3
Jake
probe block-series/6
43
probe block-with-sub-series/1/2
#"b"
probe block-with-sub-series/2/2
5
probe block-with-sub-series/2/4/2
8

Les mots fournis en tant que paths sont symboliques, et par conséquent ne sont pas évalués. Ceci permet de construire la forme la plus intuitive pour référencer un objet.

Pour utiliser la référence au mot, une référence explicite à la valeur du mot est requise :


city: 'Ukiah
probe USA/CA/:city ; << :city fait ici référence à 'Ukiah
[
population 15050
elevation "610 feet"
]

Les chemins dans les blocs, les hashs, ou les objets sont évalués en utilisant la correspondance avec le mot au plus haut niveau dans le path, et en vérifiant si le mot est de type block !, hash ! ou object !. Ensuite le mot suivant est recherché en tant que mot présent dans le bloc, le hash ou l'objet, et une sélection se fait. La valeur qui suit le mot recherché est renvoyée. Quand la valeur retournée est un bloc, un hash, ou un objet, le path peut être exprimé ainsi :

Récupération de la valeur associée au mot CA dans USA :


probe USA/CA
[
Ukiah [
population 15050
elevation "610 feet"
]
Willits [
population 9935
elevation "1350 feet"
]
]

Récupération de la valeur associée avec Willits dans USA/CA :


probe USA/CA/Willits
[
population 9935
elevation "1350 feet"
]

Récupération de la valeur associée au mot "population" dans USA/CA/Willits :


probe USA/CA/Willits/population
9935

Quand un mot utilisé dans un path n'existe pas à un endroit donné de la structure, une erreur se produit :


probe USA/CA/Mendocino
** Script Error: Invalid path value: Mendocino.
** Where: probe USA/CA/Mendocino

Les paths peuvent être utilisés pour modifier des valeurs dans des blocs et des objets :


USA/CA/Willits/elevation: "1 foot, after the earthquake"
probe USA/CA/Willits
[
population 9935
elevation "1 foot, after the earthquake"
]
obj/text: "yes, I do believe in magic."
probe obj
make object! [
text: "yes, I do believe in magic."
]

Les blocs, les hashs, les fonctions et les objets peuvent être mélangés dans les paths.

Pour choisir des éléments dans un bloc, lui-même dans un objet :


obj: make object! [
USA: [
CA [
population "too many"
]
]
]
probe obj/USA/CA/population
too many

Utilisation de raffinements de fonctions au sein d'un objet :


obj: make object! [
hello: func [/again] [
print either again [
"hello again"
] [
"oh, hello"
]
]
]
obj/hello/again
hello again

Les paths sont aussi des séries, de sorte que ce qui peut être réalisé avec une série peut aussi l'être avec une valeur de type path ! :


root: [sub1 [sub2 [
word "a word at the end of the path"
num 55
] ] ]
path: 'root/sub1/sub2/word
probe :path
root/sub1/sub2/word

Dans l'exemple précédent, la notation :path a été utilisée pour récupérer le path lui-même, et non sa valeur :


probe path
a word at the end of the path

Pour connaître la longueur d'un path :


probe length? :path
4

Trouver un mot à l'intérieur d'un path :


probe find :path 'sub2
sub2/word

Modifier un mot dans un path :


change find :path 'word 'num
probe :path
root/sub1/sub2/num
probe path
55

Format

Les paths sont exprimés relativement à un mot-racine, en fournissant un certain nombre de raffinements, chacun étant séparé des autres par le symbole slash (/).

Ces raffinements peuvent être des mots ou des valeurs. Leur interprétation particulière dépend du type de données du mot situé à la racine.

Les mots fournis comme raffinement dans les paths sont symboliques et ne sont pas évalués. Ceci est nécessaire pour garder une forme de référencement assez intuitive. Pour utilisez la référence d'un mot, une référence explicite est nécessaire comme vu précédemment :


root/:word

Cet exemple utilise la valeur de la variable, plutôt que son nom.

Création

Vous pouvez créer un path vierge d'une taille donnée comme dans l'exemple suivant :


path: make path! 10
insert :path `test
insert tail :path `this
print :path
test/this

La fonction to-path transforme son argument en une valeur de type path !.


probe to-path [root sub]
root/sub
probe to-path "root sub"
root/sub

La fonction to-set-path convertit des valeurs en type set-word (mot défini) :


probe to-set-path "root sub"
root/sub:

La fonction to-lit-path convertit des valeurs en type lit-word (mot litéral) :


probe to-lit-path "root sub"
'root/sub

Informations complémentaires

Utilisez path ?, set-path ?, et lit-path ? pour déterminer le type de données d'une valeur.


probe path? second [1 two "3"]
false
blk: [sub1 [sub2 [word 1]]]
blk2: [blk/sub1/sub2/word: 2]
if set-path? (pick blk2 1) [print "it is set"]
it is set
probe lit-path? first ['root/sub]
true

Comme les paths sont un sous-ensemble du pseudo type series !, la fonction series ? peut également être utilisée :


probe series? pick [root/sub] 1
true

L'application de la fonction form sur un path génére une chaîne de caractères à partir du path :


probe form pick [root/sub] 1
root/sub

Avec la fonction mold, on crée aussi une chaîne de caractère comme pour form, mais celle-ci peut être rechargée sous forme d'un path REBOL :


probe mold pick [root/sub] 1
root/sub

String

Concept

Les chaînes (strings) sont des séries de caractères. Toutes les opérations possibles sur les valeurs de type série peuvent également être faites avec des chaînes de caractère.

Format

Les valeurs de type string ! se présentent sous la forme d'une séquence de caractères entourés par des apostrophes " " ou des accolades . Les chaînes incluses entre des apostrophes sont limitées à une unique ligne, et ne peuvent contenir certains caractères non imprimables.


"This is a short string of characters."

Les chaînes comprises entre accolades sont utilisées pour de grands morceaux de texte, pouvant s'étaler sur plusieurs lignes. Tous les caractères de la chaîne, comme les espaces, les tabulations, les apostrophes, et les sauts de ligne font partie de la chaîne.


^{This is a long string of text that will
not easily fit on a single line of source.
These are often used for documentation
purposes.^}

Les accolades sont comptées dans la chaîne, de sorte qu'une chaîne de caractères peut inclure d'autres accolades à condition que le nombre d'accolades ouvrantes soit identique au nombre d'accolades fermantes.


^{
This is another long string of text that would
never fit on a single line. This string also
includes braces ^{ a few layers deep ^{ and is
valid because there are as many closing braces ^}
as there are open braces ^} in the string.
^}

Vous pouvez inclure des caractères spéciaux et effectuer certaines opérations dans les chaînes de caractères en préfixant ces caractères spéciaux par le symbole (^^) :

Inclusion de caractères spéciaux :

Caractère Définition
^^" Insère une double quote (").
^^ Insère une accolade fermante ().
^^^^ Insère le symbole caret (^^).
^^/ Insère le symbole slash
^^(line) Débute une nouvelle ligne.
^^- Insère une tabulation.
^^(tab) Insère aussi une tabulation.
^^(page) Démarre une nouvelle page
^^(back) Efface un caractère à gauche du point d'insertion.
^^(null) Insère le caractère "null".
^^(escape) Insère le caractère "escape".
^^(letter) Insère un caractère de contrôle (A-Z).
^^(xx) Insère un caractère ASCII via son équivalent hexadécimal (xx). Ce format permettra une extension pour les caractères Unicode dans le futur.

Création

Utilisez make pour allouer une quantité d'espace mémoire pour une chaîne de caractères vide :


make string! 40'000 ; espace pour 40k (caractères)

La fonction to-string transforme le type de la donnée fournie en argument, en type de donnée string !.


probe to-string 29-2-2000
"29-Feb-2000"
probe to-string 123456.789
"123456.789"
probe to-string #888-555-2341
"888-555-2341"

Transformer un bloc de données en une chaîne, avec la fonction to-string, a pour conséquence de concaténer les éléments du bloc, mais sans les évaluer :


probe to-string [123 456]
"123456"
probe to-string [225.225.225.0 none true 'word]
"225.225.225.0nonetrueword"

Informations connexes

Utilisez string ? ou series ? pour déterminer si une valeur est de type string ! :


print string? "123"
true
print series? "123"
true

Les fonctions form et mold sont fortement corrélées aux chaînes, dans le sens où elles génèrent des chaînes de caractères à partir de données d'autres types. La fonction form permet l'obtention d'une forme humainement lisible d'un type de donnée spécifique, tandis que la fonction mold fabrique une version utilisable par le langage.


probe form "111 222 333"
"111 222 333"
probe mold "111 222 333"
^{"111 222 333"^}

Tag

Concept

Les tags (balises) sont utilisés dans les langages à balises pour indiquer comment des zones de texte doivent être traitées. Par exemple, le tag <HTML> au début d'un fichier indique qu'il devrait être analysé au moyen des règles du langage HTML.

Une balise avec un slash (/), tel que </HTML> indique la fermeture du tag.

Les tags, en tant que sous-ensemble des séries peuvent être manipulés comme tels :


a-tag: <img src="mypic.jpg">
probe a-tag
<img src="mypic.jpg">
append a-tag ^{ alt="My Picture!"^}
probe a-tag
<img src="mypic.jpg" alt="My Picture!">

Format

Les tags valides commencent par le symbole (<) et se termine avec (>).

Par exemple :


<a href="index.html">
<img src="mypic.jpg" width="150" height="200">

Création

La fonction to-tag convertit une donnée en une autre de type tag ! :


probe to-tag "title"
<title>

Vous pouvez utiliser la fonction build-tag pour construire des tags, et y inclure des attributs. La fonction build-tag prend un seul argument, un bloc. Dans ce bloc, le premier mot est utilisé pour nommer le tag, et les mots suivants servent à définir des paires d'attributs :


probe build-tag [a href http://www.rebol.com/]
<a href="http://www.rebol.com/">
probe build-tag [
img src %mypic.jpg width 150 alt "My Picture!"
]
<img src="mypic.jpg" width="150" alt="My Picture!">

Autres infos

L'usage de la fonction tag ? permet de déterminer si une valeur est bien de type de données tag ! .


probe tag? <a href="http://www.rebol.com/">
true

Comme les tags sont aussi des séries, la fonction series ? peut être appelée :


probe series? <a href="http://www.rebol.com/">
true

La fonction form renvoie le tag qui lui est fourni, sous la forme d'une chaîne :


probe form <a href="http://www.rebol.com/">
^{<a href="http://www.rebol.com/">^}

La fonction mold renvoie elle aussi une chaîne :


probe mold <a href="http://www.rebol.com/">
^{<a href="http://www.rebol.com/">^}

La fonction print affiche un tag sur la sortie standard :


print <a href="http://www.rebol.com/">
<a href="http://www.rebol.com/">

URL

Concept

Le terme "URL" est l'acronyme de Uniform Ressource Locator, un standard Internet utilisé pour accéder à des ressources comme des pages Web, des images, des fichiers, et du courrier électronique au travers du réseau.

Le type d'URL la plus connue est celle utilisée pour le Web comme http://www.rebol.com. Les valeurs URLs sont des séries, et peuvent être manipulées comme telles :


url: http://www.rebol.com/reboldoc.html
probe to-file find/reverse (tail url) "rebol"
%reboldoc.html

Format

La première partie d'un URL indique son protocole de communication, appelé le "scheme". Le langage REBOL supporte plusieurs types de protocoles, pour les pages web (HTTP :), le transfert de fichier (FTP :), les newsgroups (NNTP :), le courrier électronique (MAILTO :), les fichiers (FILE :), finger (FINGER :), whois (WHOIS :), daytime (DAYTIME :), post office (POP :), le protocole de transmission (TCP :) et celui de résolution des noms de domaines (DNS :). Ces noms de protocoles, ces "schemes" sont suivis dans l'URL par une série de caractères dépendants du protocole utilisé :


http://host.dom/path/file
ftp://host.dom/path/file
nntp://news.some-isp.net/some.news.group
mailto:name@domain
file://host/path/file
finger://user@host.dom
whois://rebol@rs.internic.net
daytime://everest.cclabs.missouri.edu
pop://user:passwd@host.dom/
tcp://host.dom:21
dns://host.dom

Certains champs sont optionnels. Par exemple, le nom d'hôte peut être suivi par un numéro de port, si ce dernier est différent de celui par défaut. Une URL FTP peut aussi comprendre un mot de passe :


ftp://user:password@host.dom/path/file

Les caractères dans l'URL doivent respectés les conventions Internet. Certains caractères doivent être encodés en hexadécimal, en les faisant précéder du caractère d'échappement "%" :


probe http://www.somesite.dom/odd%28dir%29/odd%7Bfile%7D.txt
http://www.somesite.dom/odd%28dir%29/odd%7Bfile%7D.txt
print http://www.somesite.dom/odd%28dir%29/odd%7Bfile%7D.txt
http://www.somesite.dom/odd(dir)/odd^{file^}.txt

Création

La fonction to-url transforme un bloc en une valeur de type url !, le premier élément dans le bloc est le "scheme", le second élément est le domaine (avec ou sans user:pass et le port), les éléments suivants sont le path et le nom du fichier.


probe to-url [http www.rebol.com reboldoc.html]
http://www.rebol.com/reboldoc.html
probe to-url [http www.rebol.com %examples "websend.r"]
http://www.rebol.com/examples/websend.r
probe to-url [http usr:pass@host.com:80 "(path)" %index.html]
http://usr:pass@host.com:80/%28path%29/index.html

Autres infos

La fonction url ? permet de tester si le type de données est bien url !.


probe url? ftp://ftp.rebol.com/
true

La fonction series ? est également utilisable pour vérifier le type de données.


probe series? http://www.rebol.com/
true

Autres valeurs

Character

Concept

Les caractères ne sont pas des chaînes (strings) ; ce sont les valeurs unitaires à partir desquelles les chaînes sont construites. Un caractère peut être imprimable, non imprimable, ou encore être un caractère de contrôle.

Format

Une valeur char ! est écrite avec le signe dièse (#) suivi par une chaîne comprise entre deux apostrophes.

Le signe (#) est nécessaire pour distinguer un caractère d'une chaîne :

  1. "R" ; le caractère : R
    "R" ; une chaîne de caractère a un seul caractère : R

Les caractères peuvent inclure des séquences d'échappement, qui commence avec le symbole (^^) et sont suivis par un ou plusieurs caractères. Cette codification va inclure les caractères #"^^A" to #"^^Z", c'est-à-dire du "contrôle A" au "contrôle Z" (majuscule et minuscule sont identiques).


#"^^A" #"^^Z"

De plus, si des parenthèses sont utilisées au sein du caractère, elles signifient qu'il s'agit d'une valeur spéciale. Par exemple, le caractère "nul" peut être écrit ainsi :


"^^@"
"^^(null)"
"^^(00)"

La dernière ligne est écrite au format hexadécimal (base 16). Les parenthèses autour de la valeur permettent de prévoir l'extension en Unicode (16 bits) du type char ! dans le futur.

La table ci-dessous présente les caractères de contrôle pouvant être utilisés avec REBOL :

Character Definition
#"(null)" or #"@" nul (zero)
#"(line)", #"/" or, #"." fin de ligne
#"(tab)" or #"-" tabulation horizontale
#"(page)" nouvelle page (et page eject)
#"(esc)" escape
#"(back)" retour arrière (backspace)
#"(del)" delete
#"^^" caractére "caret"
#"^^"" apostrophe
#"(00)" to #"(FF)" formes hexa des caractères

Création

Les caractères peuvent être convertis depuis et vers d'autres types de données avec la fonction to-char :


probe to-char "a"
#"a"
probe to-char "z"
#"z"

Les caractères suivent le standard ASCII, et peuvent être construits en spécifiant leurs équivalents ASCII :


probe to-char 65
#"A"
probe to-char 52
#"4"
probe to-char 52.3
#"4"

Une autre méthode pour obtenir un caractère est de récupérer le premier caractère d'une chaîne :


probe first "ABC"
#"A"

Alors que les caractères dans les chaînes ne sont sensibles à la casse, ils le deviennent lorsqu'ils sont sous forme de caractères individuels :


probe "a" = "A" ; insensibles à la casse : MAJ = min
true
probe #"a" = #"A" ; sensibles à la casse : MAJ <> min
false

Cependant, dans la plupart des fonctions, lorsqu'ils sont utilisés, la comparaison n'est pas sensible à la casse à moins de spécifier cette option. Par exemple :


select [#"A" 1] #"a"
1
select/case [#"A" 1] #"a"
none
find "abcde" #"B"
"bcde"
find/case "abcde" #"B"
none
switch #"A" [#"a" [print true]]
true

Autres informations

Utilisez char ? pour déterminer si une valeur est de type char !.


probe char? "a"
false
probe char? #"a"
true

La fonction form retourne le caractère sans le symbole (#).


probe form #"A"
"A"

La fonction mold renvoie le caractère avec le signe (#), les apostrophes (double quotes), et aussi les séquences d'échappement pour les caractères qui le nécessitent :


probe mold #"A"
^{#"A"^}

Date

Concept

Tout autour de la planète, les dates sont écrites dans divers formats. Malgré tout, la plupart des pays utilisent le format jour-mois-année (JJ-MM-AA). L'une des exceptions à cela sont les Etats-Unis, qui utilisent couramment le format mois-jour-année (MM-JJ-AA). Par exemple, une date écrite sous la forme 2/1/1999 est ambiguë. Le mois pourrait être interprété soit comme février soit comme janvier. Certains pays utilisent le trait d'union (-) comme séparateur, d'autres le symbole slash (/), et encore d'autres utilisent le point (.).

Et pour finir, les ordinateurs personnels utilisent souvent des dates dans le format ISO année-mois-jour (AA-MM-JJ).

Format

Le langage REBOL est flexible, et il permet au type de données date ! d'être exprimé dans des formats divers. Par exemple, le premier jour de mars peut s'écrire sous l'un ou l'autre des formats suivants :


probe 1/3/1999
1-Mar-1999
probe 1-3-1999
1-Mar-1999
probe 1999-3-1 ;ISO format
1-Mar-1999

L'année peut aller de 1 jusqu'à 9999. (NdT : si quelqu'un veut bien patienter jusque là pour voir s'il n'y a pas un bug ;-)). Les jours relatifs aux années bissextiles (le 29 février) n'existent que pour ces années-là.


probe 29-2-2000
29-Feb-2000
probe 29-2-2004
29-Feb-2004
probe 29-2-2002
** Syntax Error: Invalid date -- 29-2-2002
** Near: (line 1) probe 29-2-2002

Les champs des dates peuvent être séparés avec le symbole "slash" (/) ou "tiret" (-). Les dates peuvent être écrites soit au format "année-mois-jour", soit au format "jour-mois-année" :


probe 1999-10-5
5-Oct-1999
probe 1999/10/5
5-Oct-1999
probe 5-10-1999
5-Oct-1999
probe 5/10/1999
5-Oct-1999

Parce que les formats de date internationaux ne sont pas beaucoup utilisés aux Etats-Unis, un nom de mois ou son abréviation peuvent aussi être utilisés :


probe 5/Oct/1999
5-Oct-1999
probe 5-October-1999
5-Oct-1999
probe 1999/oct/5
5-Oct-1999

Quand l'année correspond au dernier champ, elle peut écrite avec 2 ou 4 chiffres :


probe 5/oct/99
5-Oct-1999
probe 5/oct/1999
5-Oct-1999

Cependant, il est préférable d'écrire l'année sur 4 chiffres. En effet, des problèmes peuvent survenir sinon, lors de comparaison de dates ou en effectuant des opérations de tris.

Quand deux chiffres sont utilisés pour exprimer l'année, l'interprétation de celle-ci est relative à l'année en cours et est uniquement valide pour une période de 50 ans dans le passé ou dans le futur.


probe 28-2-66 ; fait référence à 1966
28-Feb-1966
probe 12-Mar-20 ; fait référence à 2020
12-Mar-2020
probe 11-3-45 ; fait référence à 2045, pas à 1945
11-Mar-2045

Il est recommandé d'utiliser une année sur 4 chiffres afin d'éviter les problèmes potentiels. Pour représenter les dates dans le premier siècle (rarement fait puisque le calendrier Grégorien n'existait pas), utilisez des zéros supplémentaires pour représenter le siècle (comme dans 9-4-0029).

L'heure est séparée de la date par le symbole slash (/). Le fuseau horaire est ajouté ensuite en utilisant les signes (+) ou (-) sans aucun espace. Les fuseaux horaires sont écrits sous forme de décalage horaire (plus ou moins) relativement à l'heure GMT. La résolution pour le fuseau horaire est d'une demi-heure. Si le décalage horaire est un nombre entier, on suppose qu'il s'agit d'heures :


probe 4/Apr/2000/6:00+8:00
4-Apr-2000/6:00+8:00
probe 1999-10-2/2:00-4:00
2-Oct-1999/2:00-4:00
probe 1/1/1990/12:20:25-6
1-Jan-1990/12:20:25

Il ne peut y avoir d'espaces au sein d'une date. Par exemple, l'expression


10 - 5 - 99

sera être interprétée comme une soustraction, pas une date.

Accéder aux données d'une variable date !

Quelques raffinements peuvent être utilisés avec une valeur de type date ! pour récupérer l'un ou l'autre des champs prédéfinis :

Raffinement Description
/day retourne le jour.
/month retourne le mois.
/year retourne l'année.
/julian retourne le jour de l'année.
/weekday renvoie le jour dans la semaine (1-7/Mon-Sun).
/time retourne l'heure (si elle existe).
/hour retourne l'heure (si elle existe).
/minute retourne les minutes (si cette information existe).
/second renvoie les secondes (si cette information existe).
/zone renvoie le fuseau horaire (s'il existe).

Voici comment ces raffinements fonctionnent :


some-date: 29-Feb-2000
probe some-date/day
29
probe some-date/month
2
probe some-date/year
2000
days: ["Mon" "Tue" "Wed" "Thu" "Fri" "Sat" "Sun"]
probe pick days some-date/weekday
Tue

Quand l'heure est fournie, les raffinements relatifs à l'heure peuvent être utilisés. Les raffinements /hour, /minute et /second peuvent être utilisés avec le raffinement /time qui isole les données horaires, afin de les manipuler :


lost-time: 29-Feb-2000/11:33:22.14-8:00
probe lost-time/time
11:33:22.14
probe lost-time/time/hour
11
probe lost-time/time/minute
33
probe lost-time/time/second
22.14
probe lost-time/zone
-8:00

Création

Utilisez la fonction to-date pour convertir des valeurs en dates :


probe to-date "5-10-1999"
5-Oct-1999
probe to-date "5 10 1999 10:30"
5-Oct-1999/10:30
probe to-date [1999 10 5]
5-Oct-1999
probe to-date [5 10 1999 10:30 -8:00]
5-Oct-1999/10:30-8:00

Pour la conversion vers une date, l'année DOIT être spécifiée avec 4 chiffres.

Diverses opérations mathématiques peuvent être réalisées sur les dates :


probe 5-Oct-1999 + 1
6-Oct-1999
probe 5-10-1999 - 10
25-Sep-1999
probe 5-Oct-1999/23:00 + 5:00
6-Oct-1999/4:00

Autres informations

Utilisez la fonction date ? pour déterminer si une valeur appartient à ce type de données.


probe date? 5/1/1999
true

La fonction to-idate renvoie la date sous forme d'une chaîne au format standard en vigueur sur Internet.

Le format de date pour Internet est : jour de la semaine, jour dans le mois, mois, année, l'heure (sur 24 heures), et le décalage horaire vis-à-vis de l'heure GMT, soit :


probe to-idate now
Fri, 30 Jun 2000 14:42:26 -0700

La fonction now renvoie la date et l'heure courante (au format long incluant le décalage horaire) :


probe now
30-Jun-2000/14:42:26-7:00

Logic

Concept

Le type de données logic ! permet de représenter deux états : true ou false, c'est-à-dire : vrai ou faux.

Ce type de donnée est souvent utilisé pour des comparaison comme avec :


age: 100
probe age = 100
true
time: 10:31:00
probe time < 10:30
false
str: "this is a string"
probe (length? str) > 10
true

Le type de données logic ! est couramment utilisé avec des fonctions conditionnelles telles que if, while, et until :


if age = 100 [print "Centennial human"]
Centennial human
while [time > 6:30] [
send person "Wake up!"
wait [0:10]
]

Le complément d'une valeur logique est obtenu avec la fonction not :


there: place = "Ukiah"
if not there [...]

Format

Normalement, les valeurs logiques sont récupérées à partir de la comparaison d'expression. Cependant, des mots peuvent être définis comme valeurs logiques et utilisés comme expressions logiques : "on" ou "off".


print-me: false
print either print-me ["turned on"]["turned off"]
turned off
print-me: true
print either print-me ["turned on"]["turned off"]
turned on

La valeur false n'est pas équivalente au nombre entier zéro, ni non plus à none. Cependant, dans les expressions conditionnelles, false et none ont le même effet :


print-me: none
print either print-me ["turned on"]["turned off"]
turned off

N'importe quelle valeur assignée à un mot conduit au même effet que si vous aviez true :


print-me: "just a string"
print either print-me ["turned on"]["turned off"]
turned on
print-me: 11-11-1999
print either print-me ["turned on"]["turned off"]
turned on

Les mots suivants sont prédéfinis pour manipuler des valeurs logiques :


true
on ;identique à true
yes ;identique à true
false
off ;identique à false
no ;identique à false

Donc, au lieu de true et false, lorsque cela a du sens, les mots on et off, ou yes et no peuvent aussi être utilisés :


print-me: yes
print either print-me ["turned on"]["turned off"]
turned on
print-me: no
print either print-me ["turned on"]["turned off"]
turned off
print-me: on
print either print-me ["turned on"]["turned off"]
turned on
print-me: off
print either print-me ["turned on"]["turned off"]
turned off

Création

La fonction to-logic transforme des valeurs de type integer ! ou none ! en type de données logic ! :


probe to-logic 0
false
probe to-logic 200
true
probe to-logic none
false
probe to-logic []
true
probe to-logic "a"
true
probe to-logic none
false

Informations complémentaires

La fonction logic ? permet de savoir si la valeur testée est bien de ce type :


probe logic? 1
false
probe logic? on
true
probe logic? false
true

Utilisez les fonctions form, print, et mold pour afficher une valeur logic ! :


probe form true
true
probe mold false
false
print true
true

Money

Concept

Il existe divers symboles internationaux pour les valeurs monétaires. Certains de ses symboles apparaissent avant le montant, et d'autres après. Comme standard pour représenter des valeurs monétaires internationales, le langage REBOL utilise le format monétaire des États-Unis, mais permet aussi d'inclure des caractéristiques spécifiques.

Format

Le type de données money ! utilise la notation en virgule flottante standardisée par l'IEEE, qui fournit une précision sur 15 chiffres, centimes inclus.

Le langage limite la longueur de la valeur à 64 caractères. Les valeurs qui sont en dehors (trop grandes ou trop petites) ou qui ne peuvent être représentées sur 64 caractères génèrent une erreur.

Les valeurs monétaires sont préfixées avec un indicateur (optionnel) pour la devise, suivies d'un signe dollar ($). Un signe plus (+) ou moins (-) peut apparaître, immédiatement suivi par le premier caractère (indication de la devise, ou signe dollar), afin d'indiquer le signe.


$123
-$123
$123.45
US$12
US$12.34
-US$12.34
$12,34
-$12,34
DEM$12,34

Pour simplifier la lisibilité des grands nombres, et les mettre en morceaux lisibles, une simple quote (`) peut être placée n'importe où entre deux chiffres à l'intérieur du nombre, mais pas avant le nombre.


probe $1'234.56
$1234.56
probe $1'234'567,89
$1234567.89

N'utilisez pas de virgules ou de points pour couper des valeurs monétaires, car ces deux caractères représentent le séparateur décimal. Le datatype money ! est un type de données hybride. Conceptuellement, le montant est un scalaire. Cependant, parce que la désignation de la devise est stockée sous forme de chaîne, le type de données money ! possède deux éléments :

string ! : l'élément désignant le type de devise (USD, EUR, YEN, etc.), qui peut avoir 3 caractères maximum.

decimal ! : le montant

Pour illustrer ceci, la valeur monétaire suivante est préfixée avec la chaîne USD pour "dollar US" :


my-money: USD$12345.67

Voici ces deux composantes :


probe first my-money
USD
probe second my-money
12345.67
probe pick my-money 3 ; seulement deux éléments
none

Si aucun indicateur de devise n'est employé, l'élément qui y fait référence est vide.


my-money: $12345.67

probe first my-money
""
probe second my-money
12345.67

Les devises internationales peuvent être spécifiées avec l'indicateur de devises, comme ici :


my-money: DKM$12'345,67

probe first my-money
DKM
probe second my-money
12345.67

Création

Utilisez la fonction to-money pour transformer des valeurs de type string !, integer !, decimal !, ou block ! en valeurs de type money !.


probe to-money 123
$123.00
probe to-money "123"
$123.00
probe to-money 12.34
$12.34
probe to-money [DEM 12.34]
DEM$12.34
probe to-money [USA 12 34]
USA$12.34

Les valeurs de type money ! peuvent être ajoutées, soustraites, et comparées avec d'autres monnaies de la même devise. Une erreur se produit si des devises différentes sont mélangées pour ce genre d'opérations (les conversions automatiques ne sont pas prévues actuellement).


probe $100 + $10
$110.00
probe $100 - $50
$50.00
probe equal? DEM$100.11 DEM$100.11
true

Les valeurs monétaires peuvent être multipliées et divisées avec des nombres entiers ou décimaux.

Les valeurs monétaires peuvent aussi être divisées par d'autres valeurs monétaires, le résultat étant un nombre entier ou décimal.


probe $100 + 11
$111.00
probe $100 / 4
$25.00
probe $100 * 5
$500.00
probe $100 - 20.50
$79.50
probe 10 + $1.20
$11.20
probe 10 - $0.25
$9.75
probe $10 / .50
$20.00
probe 10 * $0.75
$7.50

Autres informations

Vous pouvez utilisez money ? pour savoir si une valeur est de type de données money !.


probe money? USD$12.34
true

Utilisez les fonctions form, print, et mold avec un argument de type money ! pour afficher une valeur monétaire, avec l'indicateur de devise et le signe dollar ($), sous forme d'un nombre décimal avec une précision à deux chiffres.


probe form USD$12.34
USD$12.34
probe mold USD$12.34
USD$12.34
print USD$12.34
USD$12.34

None

Concept

Le datatype none ! contient une unique valeur qui représente "rien" ou "aucune valeur". Le concept de none est différent de celui d'un bloc vide, d'une chaîne vide, ou d'un caractère nul. C'est une valeur qui représente une non-existence.

Une valeur none ! peut être renvoyée par des fonctions très différentes, en particulier celles qui sont utilisées avec des séries (par exemple, pick et find).

Le mot REBOL none est défini comme faisant partie du type de donnée none ! et il fait référence à une valeur none !. Le mot none n'est pas équivalent à zero ou à false.

Cependant, none va être interprété comme false par beaucoup de fonctions. Une valeur none ! autorise beaucoup d'usages comme par exemple servir de valeur de retours à des fonctions relatives aux séries comme pick, find, et select :


if (pick series 30) = none [...]

Dans des bases de données, une valeur none peut être un moyen de remplacer des valeurs manquantes :


email-database: [
"Bobby" bob@rebol.com 40
"Linda" none 23
"Sara" sara@rebol.net 33
]

None peut aussi être utilisée comme valeur logique :


secure none

Format

Le mot none est prédéfini pour manipuler une valeur de type none !. Bien que none ne soit pas équivalent à zero ou false, elle est valide dans des expressions conditionnelles et a le même effet que false :


probe find "abcd" "e"
none
if find "abcd" "e" [print "found"]

Création

Autres informations

Il est possible d'utiliser none ? pour déterminer si une valeur est ou non du type none !.


print none? 1
false
print none? find [1 2 3] 4
true

Les fonctions form, print et mold retournent la valeur none lorsqu'un argument none leur est fourni :


probe form none
none
probe mold none
none
print none
none

Pair

Concept

Le type de données pair ! est utilisé pour indiquer des coordonnées dans l'espace, comme par exemple des positions à l'écran. Les "pairs" peuvent être utilisées aussi pour définir des tailles en plus des positions.

Les valeurs de type pair ! sont en particulier utilisées dans REBOL/View.

Format

Une valeur de type pair ! est définie par deux nombres entiers séparés par un caractère "x".


100x50

1024x800

-50x200

Création

Utilisez la fonction to-pair pour transformer des blocs ou des chaînes de caractères :


p: to-pair "640x480"
probe p
640x480
p: to-pair [800 600]
probe p
800x600

Autres

La fonction pair ? permet de savoir si la valeur qui lui est fournie en argument est bien de ce type de données :


probe pair? 400x200
true
probe pair? pair
true

Les pairs peuvent être utilisées avec la plupart des opérateurs mathématiques associés aux nombres entiers :


100x200 + 10x20

10x20 * 2x4

100x30 / 10x3

100x100 * 3

10x10 + 3

Il est possible d'extraire des valeurs de type pair ! leurs composantes individuelles :


pair: 640x480
probe first pair
640
probe second pair
480

Toutes les valeurs de type pair ! supportent les raffinements /x et /y. Ces raffinements permettent la consultation et la manipulation, de façon spécifique, des coordonnées x et y.

Pour récupérer individuellement chaque coordonnée :


probe pair/x
640
probe pair/y
480

Pour modifier l'une ou l'autre des coordonnées :


pair/x: 800
pair/y: 600
probe pair
800x600

Raffinement

Concept

Les raffinements sont des "modificateurs", comme peuvent l'être les adjectifs utilisés dans les langages humains. Un raffinement indique une variation dans l'usage, ou une extension dans le sens, d'une fonction, d'un objet, d'un nom de fichier, d'une URL, ou d'un chemin (path). Les raffinements sont toujours symboliques dans leurs valeurs.

Ils sont utilisés dans les fonctions :


block: [1 2]
append/only block [3 4]

mais aussi avec les objets :


print system/version

ou les fichiers :


dir: %docs/core
print read dir/file.txt

ou encore les urls :


site: http://www.rebol.com
print read site/index.html

Format

Les raffinements sont formés par l'association d'un slash / et d'un mot REBOL valide (voir la section sur les mots ci-dessous). Par exemple :


/only
/test1
/save-it

Les raffinements sont habituellement concaténés à d'autres mots, comme dans le cas de :


port: open/binary file

Mais les raffinements peuvent aussi être écrits seuls, comme lorsqu'ils apparaissent dans la spécification d'une fonction :


save-data: function [file data /limit /reload] ...

Création

Les raffinements peuvent aussi être créés directement dans le code source :


/test

ou être composés avec la fonction to-refinement :


probe to-refinement "test"
/test

Et aussi...

Pour tester une valeur, la fonction refinement ? est utilisable :


probe refinement? /test
true
probe refinement? 'word
false

Time

Concept

Le langage REBOL supporte une expression standard du temps en heures, minutes, secondes, jusqu'à la milliseconde et plus. Des valeurs de temps négatives ou positives sont permises.

Le type de donnée time ! utilise un affichage relatif, plutôt que l'heure absolue.

Par exemple, 10:30 représente 10 heures et 30 minutes, plutôt que 10:30 A.M. ou P.M.

Format

Les valeurs de type time ! se présentent sous la forme d'un ensemble de nombres entiers séparés par le symbole ( :). Les heures et les minutes sont nécessaires, mais les secondes sont optionnelles. : Pour chaque champ (heure:minutes:secondes), les zéros additionnels sont ignorés


10:30
0:00
18:59
23:59:50
8:6:20
8:6:2

Les valeurs de minutes et de secondes peuvent être supérieures à 60.

Ces valeurs plus grandes que 60 sont automatiquement converties. Ainsi, 0:120:00 est la même chose que 2:00.


probe 00:120:00
2:00

Les dixièmes ou centièmes de seconde sont définis en utilisant le séparateur décimal dans le champ des secondes. (Utilisez un point ou une virgule comme séparateur décimal).

Les champs heures et minutes deviennent optionnels quand un nombre décimal est fourni. Les éléments inférieurs à la seconde sont encodés en nanosecondes, soit au milliardième de seconde :


probe 32:59:29.5
32:59:29.5
probe 1:10,25
0:01:10.25
probe 0:0.000000001
0:00:00.000000001
probe 0:325.2
0:05:25.2

Les valeurs de type time ! peuvent être suivies par les chaînes AM ou PM, mais AUCUN n'espace n'est permis dans ce cas.

L'ajout de la chaîne PM revient à ajouter 12 heures à l'heure indiquée :


probe 10:20PM
22:20
probe 3:32:20AM
3:32:20

Les valeurs time ! retournées se présentent avec un format standard en heures, minutes, secondes, et fractions de secondes, indépendamment de la façon dont elles ont été saisies :


probe 0:87363.21
24:16:03.21

Accès aux champs

Les valeurs de type time ! possèdent trois raffinements qui servent à retourner des informations spécifiques :

Raffinement Description
/hour Renvoie la valeur de l'heure
/minute Renvoie la valeur pour les minutes
/second Renvoie la valeur des secondes

Voici comment utiliser ces raffinements :


lapsed-time: 91:32:12.14
probe lapsed-time/hour
91
probe lapsed-time/minute
32
probe lapsed-time/second
12.14

Les données horaires avec des fuseaux horaires peuvent uniquement être utilisées dans des valeurs de type date !.

Création

Les valeurs time ! peuvent être créées avec la fonction to-time :


probe to-time "10:30"
10:30
probe to-time [10 30]
10:30
probe to-time [0 10 30]
0:10:30
probe to-time [10 30 20.5]
10:30:20.5

Dans les exemples précédents, les valeurs ne sont pas évaluées. Pour évaluer des valeurs comme des expressions mathématiques, utilisez la fonction reduce.


probe to-time reduce [10 30 + 5]
10:35

Dans les différentes opérations mathématiques mettant en oeuvre des valeurs de type time !, celles-ci ou les nombres entiers et décimaux impliqués sont manipulés ainsi :


probe 10:30 + 1
10:30:01
probe 10:00 - 10
9:59:50
probe 0:00 - 10
-0:00:10
probe 5:10 * 3
15:30
probe 0:0:0.000000001 * 1'500'600
0:00:00.0015006
probe 8:40:20 / 4
2:10:05
probe 8:40:20 / 2:20:05
3
probe 8:40:20 // 4:20
0:00:20

Autres informations

La fonction time ? permet de savoir si son argument a pour datatype time ? :


probe time? 10:30
true
probe time? 10.30
false

Utilisez la fonction now avec le raffinement /time pour retourner la date et l'heure courante :


print now/time
14:42:15

La fonction wait est utilisée pour attendre quelque chose, une certain durée, ou un port, ou les deux. Si la valeur est de type time !, wait permet une temporisation égale au temps indiqué. Si la valeur est de type date !/time !, la fonction wait permet une temporisation jusqu'à la date et l'heure indiquée. Si la valeur est de type integer ! ou decimal !, wait permet d'attendre le nombre de secondes indiqué.

Si la valeur est un port, la fonction wait attendra un événement sur ce port.

Si un bloc est fourni en argument à wait, l'attente se fera pour chacun des arguments (ports ou valeurs de temps) indiqués. Si un événement s'est produit sur un port, wait retourne ce port, ou retourne none si un time-out s'est produit. Par exemple :


probe now/time
14:42:16
wait 0:00:10
probe now/time
14:42:26

Tuple

Concept

Il est courant de représenter des numéros de versions, des adresses Internet, ou encore des valeurs de couleurs (RGB) sous la forme d'une séquence de trois ou quatre nombres entiers. Ces types de valeurs sont appelés des tuples (tuple !) (comme dans quintuple) et sont représentées sous forme d'entiers séparés par des points.


1.3.0 2.1.120 1.0.2.32 ; version
199.4.80.250 255.255.255.0 ; adresse ou masque réseau
0.80.255 200.200.60 ; couleurs en RGB (rouge/vert/bleu)

Format

Chaque entier dans une valeur de type tuple ! peut être comprise entre 0 et 255. Les nombres entiers négatifs génèrent une erreur. De trois à dix entiers peuvent être spécifiés dans un tuple.

Dans le cas où seulement deux entiers sont donnés, il doit y avoir au moins deux points, sinon la valeur sera assimilée à un nombre décimal.


probe 1.2 ; décimal
1.2
probe type? 1.2
decimal!
probe 1.2.3 ; un tuple
1.2.3
probe 1.2. ; un autre tuple
1.2.0
probe type? 1.2.
tuple!

Création

Utilisez la fonction to-tuple pour convertir des données en tuple :


probe to-tuple "12.34.56"
12.34.56
probe to-tuple [12 34 56]
12.34.56

Et aussi

La fonction tuple ? permet de déterminer si une valeur est ou non du type tuple !.


probe tuple? 1.2.3.4
true

Utilisez la fonction form pour afficher un tuple sous la forme d'une chaîne de caractères :


probe form 1.2.3.4
1.2.3.4

La fonction mold permet de convertir un tuple en chaîne de caractère, mais de façon à ce que celle-ci soit récupérable en tant que tuple :


probe mold 1.2.3.4
1.2.3.4

La fonction print affiche le tuple sur la sortie standard :


print 1.2.3.4
1.2.3.4

Words

Concept

Les mots (words) sont les symboles utilisés par REBOL. Un mot peut être ou non une variable, selon la façon dont il est utilisé. Les mots sont souvent utilisés comme symboles.

REBOL n'a pas de mots clés, il n'y a pas de restrictions sur les mots utilisés et la façon dont ils sont utilisés.

Par exemple, vous pouvez définir votre propre fonction appelée print et vous en servir à la place de la fonction prédéfinie dans le langage.

Il y a quatre formats différents pour l'utilisation des mots, selon l'opération qui est requise.

Action Type de Mot Type de Test Conversion
word : set-word ! set-word ? to-set-word
:word get-word ! get-word ? to-get-word
word word ! word ? to-word
'word lit-word ! lit-word ? to-lit-word

Format

Les mots sont composés de caractères alphabétiques, de nombres, et de n'importe lequel des caractères suivants :


? ! . ' + - * & | = _ ~

Un mot ne peut pas commencer par un nombre, et il existe aussi quelques restrictions sur les mots qui pourraient être interprétés comme des nombres. Par exemple, -1 et +1 sont des nombres, pas des mots. La fin d'un mot est marquée par un espace, un caractère de fin de ligne, ou l'un des caractères suivants :


[ ] ( ) ^{ ^} " : ; /

Par ailleurs, les crochets d'un bloc ne sont pas compris dans un mot :


[test]

Les caractères suivants ne sont pas autorisés dans des mots :


@ # $ % ^^ ,

Les mots peuvent être de n'importe quelle longueur, mais ne peuvent pas dépasser une ligne.


this-is-a-very-long-word-used-as-an-example

Voici quelques exemples de mots :


Copy print test

number? time? date!

image-files l'image

++ -- == +-

***** *new-line*

left&right left|right

Le langage REBOL n'est pas sensible à la casse des caractères. Les mots suivants :


blue

Blue

BLUE

font tous référence au même mot.

La casse des caractères est préservée lorsque le mot est affiché. Les mots peuvent être réutilisés. La signification d'un mot dépend de son contexte, de sorte qu'un mot peut être réutilisé dans différents contextes.

Vous pouvez réutiliser n'importe quel mot, même les mots REBOL prédéfinis. Par exemple, le mot REBOL if peut être réutilisé dans votre code différemment de la façon dont l'interpréteur REBOL l'utilise.

Création

La fonction to-word convertit son argument en une valeur de type word !.


probe to-word "test"
test

La fonction to-set-word convertit des valeurs en valeurs de type set-word ! (mot défini).


probe make set-word! "test"
test:

La fonction to-get-word renvoie des valeurs de type to-get-word !.


probe to-get-word "test"
:test

La fonction to-lit-word renvoie des valeurs de type lit-word ! (mot littéral).


probe to-lit-word "test"
'test

Autres informations

Utilisez les fonctions word ?, set-word ?, get-word ?, et lit-word ? pour tester le datatype :


probe word? second [1 two "3"]
true
if set-word? first [word: 10] [print "it is set"]
it is set
probe get-word? second [pr: :print]
true
probe lit-word? first ['foo bar]
true

mercredi 02 novembre 2005

REBOL Classes

"I have followed Rebol since it was called Lava and with View Pro and the IE browser plug-in it has come of age. Most of the stuff here is from other users of Rebol and my effect to build a page that has some of the best from them all".

A new approach to learning REBOL: interactive class based on the plugin. Don't miss it !

(Requires MS Windows and a plugin-compatible browser)

mercredi 19 octobre 2005

Manuel de l'utilisateur - Chapitre 13 - Protocoles Réseau

Historique de la traduction

Date Version Commentaires Auteur Email
5 juin 2005 21:02 1.0.0 Traduction initiale Philippe Le Goff lp—legoff—free—fr

Présentation

REBOL inclut en standard plusieurs des plus importants protocoles Internet.

Ces protocoles sont faciles à utiliser au sein de vos scripts ; ils ne requièrent aucune librairie ou fichier à inclure, et la plupart des opérations peuvent être réalisées en une seule ligne de code.

La liste ci-dessous indique les protocoles réseau supportés :

DNS : Domain Name Service : traduit les noms d'ordinateur en adresses IP et vice-versa.

Finger : Permet d'obtenir des informations sur des utilisateurs, par leurs profils.

Whois : Récupére des informations sur l'enregistrement d'un domaine (domain registration).

Daytime : Network Time Protocol : permet d'obtenir l'heure depuis un serveur.

HTTP : Hypertext Transfer Protocol. Utilisé pour le Web.

SMTP : Simple Mail Transfer Protocol. Utilisé pour l'envoi d'e-mails.

POP : Post Office Protocol. Utilisé pour récupérer des mails.

FTP : File Transfer Protocol. Transfert de fichiers avec un serveur.

NNTP : Network News Transfer Protocol. Pour émettre ou lire des news Usenet.

TCP : Transmission Control Protocol. Protocole de base d'Internet.

UDP : User Datagram Protocol. Protocole non orienté connexion basé sur l'envoi de datagrammes.

De plus, vous pouvez créer des agents pour d'autres protocoles Internet ou créer votre propre protocole.

Bases Réseau pour REBOL

Modes de fonctionnement

Il existe deux modes de base pour les opérations réseau : atomique ou basé sur un port.

Les opérations réseau en mode "atomique" sont celles qui sont accomplies avec une unique fonction. Par exemple, vous pouvez lire une page Web entière avec un seul appel à la fonction read. Il n'est pas nécessaire de séparer l'ouverture de la connexion et la lecture. Tout cela est fait automatiquement avec la fonction read.

Par exemple, vous pouvez saisir :


print read http://www.rebol.com

Le serveur cible est trouvé et ouvert, a page Web est transférée, et la connexion est fermée.

Les opérations réseau basées sur les ports sont celles qui s'appuient sur une approche traditionnelle en programmation. Elles supposent l'ouverture d'un port, et effectuent diverses opérations sur le port. Par exemple, si vous voulez lire votre courrier électronique depuis un serveur POP, message par message, vous devrez utiliser cette méthode. Voici un exemple qui lit et affiche tous vos emails.


pop: open pop://user:pass@mail.example.com
forall pop [print first pop]
close pop

L'approche atomique est plus facile, mais aussi plus limitée. L'approche basée sur la gestion des ports autorise plus d'opérations, mais suppose aussi une plus grande compréhension des aspects réseau.

Spécification de ressources réseaux

REBOL fournit deux approches pour spécifier des ressources réseau : les spécifications d'URLs et de ports.

Les URLs (Uniform Resource Locators) sont utilisées pour identifier une ressource réseau, comme une page Web, un site FTP, une adresse email, un fichier, une autre ressource ou un service. Les URLs sont un type de données intrinsèque à REBOL, et elles peuvent être exprimées directement dans le langage.

La notation standard pour les URLs consiste à écrire le "scheme" (NdT : souvent le protocole), suivi de sa spécification :


scheme:specification

Le scheme est souvent le nom du protocole, tel que HTTP, FTP, SMTP, et POP ; d'autre part, ce n'est pas une nécessité. Un "scheme" peut être n'importe quel nom qui identifie la méthode utilisée pour accéder à une ressource.

Le format de la spécification relative à un "scheme" dépend de celui-ci ; cependant, la plupart des schemes partagent un format commun pour identifier les serveurs réseau, les noms d'utilisateur, les mots de passe, les numéros de ports, et les chemins vers les fichiers. Voici quelques formats couramment utilisés :


scheme://host

scheme://host:port

scheme://user@host

scheme://user:pass@host

scheme://user:pass@host:port

scheme://host/path

scheme://host:port/path

scheme://user@host/path

scheme://user:pass@host/path

scheme://user:pass@host:port/path

Voici la liste des champs utilisés dans les formats précédents (Network Resource Specification).

scheme : Le nom utilisé pour identifier le type de ressource, souvent le même que le protocole. Par exemple, HTTP, FTP, et POP.

host : Le nom réseau ou l'adresse pour une machine. Par exemple, www.rebol.com, cnn.com, accounting.

port : Le numéro de port de la machine cible, pour le scheme en cours. Normalement, les ports sont standardisés, donc cette information n'est pas requise la plupart du temps. Exemples : 21, 23, 80, 8000.

user : un nom d'utilisateur pour accéder à la ressource.

pass : Un mot de passe pour authentifier le nom d'utilisateur.

path : Un chemin de fichier ou une autre méthode pour référencer la ressource. Cette valeur dépend du scheme utilisé. Certains schemes incluent des modèles et des arguments de scripts (comme avec CGI).

Une autre manière d'identifier une ressource est une spécification de port en REBOL. En fait, lorsqu'une URL est utilisée, elle est automatiquement convertie en spécification de port. Une spécification de port peut accepter beaucoup plus d'arguments qu'une URL, mais nécessite plusieurs lignes pour les définir.

Une spécification de port est une définition d'objet sous forme de bloc, qui fournit chacun des paramètres nécessaires pour accéder à la ressource réseau. Par exemple, l'URL pour accéder à un site Web est :


read http://www.rebol.com/developer.html

mais elle peut aussi être écrite sous la forme :


read [
scheme: 'HTTP
host: "www.rebol.com"
target: %/developer.html
]

L'URL pour une ressource FTP à lire peut être :


read ftp://bill:vbs@ftp.example.com:8000/file.txt

mais elle peut aussi être écrite sous la forme :


read [
scheme: 'FTP
host: "ftp.example.com"
port-id: 8000
target: %/file.txt
user: "bill"
pass: "vbs"
]

De plus, il y a beaucoup d'autres champs pour le port qui peuvent être mentionnés, comme la durée pour un time-out, le type d'accès, et la sécurité.

Schemes, Agents (handlers) et Protocoles

Le fonctionnement de REBOL pour le réseau exploite les schemes pour identifier les agents (handlers) qui communiquent avec les protocoles.

En REBOL, le scheme est utilisé pour identifier la méthode d'accès à une ressource. Cette méthode utilise un objet codé, qui est appelé un agent. Chacun des schemes, supportés par REBOL, pour une URL (comme HTTP, FTP) a un agent. La liste des schemes peut être obtenue avec :


probe next first system/schemes
[default Finger Whois Daytime SMTP POP HTTP FTP NNTP]

De surcroît, il existe de schemes de bas niveau qui ne sont pas indiqués ici. Par exemple, les schemes TCP et UDP sont utilisés pour les communications directes et de bas niveau.

De nouveaux schemes peuvent être ajoutés à cette liste. Par exemple, vous pouvez définir votre propre scheme, appelé FTP2, qui utilisera des caractéristiques spéciales pour l'accès FTP, comme fournir automatiquement votre nom d'utilisateur et votre mot de passe, de sorte que vous n'ayez pas à les inclure dans les URLs FTP.

La plupart des agents (handlers) sont utilisés pour fournir une interface à un protocole réseau. Un protocole est utilisé pour communiquer entre des périphériques divers, comme des clients et des serveurs.

Bien que chaque protocole soit légèrement différent dans sa façon de communiquer, il peut y avoir des choses communes avec d'autres protocoles.

Par exemple, la plupart des protocoles requièrent une connexion réseau à ouvrir, à lire, à écrire et à fermer. Ces opérations communes sont accomplies en REBOL par un agent par défaut.

Cet agent rend des protocoles comme finger, whois, et daytime presque triviaux à implémenter.

Les agents pour les schemes sont écrits sous forme d'objets. L'agent par défaut sert d'objet racine (root object) pour tous les autres agents. Quand un agent nécessite un champ particulier, comme une valeur de time-out à utiliser pour lire les données, si la valeur n'est pas définie spécifiquement dans l'agent, elle sera fournie par l'agent par défaut.

Donc, les agents surchargent l'agent par défaut, avec leurs champs et leurs valeurs. Vous pouvez aussi créer des agents qui utilisent les valeurs par défaut d'autres agents. Par exemple, vous pouvez utiliser un agent FTP2 qui prend ses champs manquants d'abord dans l'agent FTP, puis ensuite dans l'agent par défaut.

Lorsqu'un port est utilisé pour accéder à des ressources réseau, il est lié à un agent spécifique. Ensemble, l'agent et le port forment une unité qui est utilisée pour fournir l'information sur les données, le code, et le statut permettant de traiter tous les protocoles.

Le code source pour les agents peut être obtenu à partir de l'objet system/scheme. Ceci peut être utile si vous voulez modifiez le comportement d'un agent ou construire le votre. Par exemple, pour visualiser le code de l'agent Whois, saisissez :


probe get in system/schemes 'whois

Notez que ce que verrez est un mélange de l'agent par défaut avec l'agent whois. Le code source actuel qui est utilisé pour créer l'agent Whois fait seulement quelques lignes :


make Root-Protocol [
open-check: [[any [port/user ""]] none]
net-utils/net-install Whois make self [] 43
]

Surveillance d'agents

A des fins de déboguage, vous pouvez surveiller les actions de chaque agent. Chaque agent produit sa propre trace pour le déboguage, qui indique quelles opérations ont été réalisées. Pour mettre en route le déboguage réseau, activez-le avec la ligne suivante :


trace/net on

Pour désactiver le déboguage réseau, utilisez :


trace/net off

Voici un exemple :


read pop://carl:poof@zen.example.com
<span class="output">URL Parse: carl poof zen.example.com none none none
Net-log: ["Opening tcp for" POP]
connecting to: zen.example.com
Net-log: [none "+OK"]
Net-log: ^{+OK QPOP (version 2.53) at zen.example.com starting.^}
Net-log: [["USER" port/user] "+OK"]
Net-log: "+OK Password required for carl."
Net-log: [["PASS" port/pass] "+OK"]
** User Error: Server error: tcp -ERR Password supplied for "carl"
is incorrect.
** Where: read pop://carl:poof@zen.example.com</span>

Démarrage initial

Les fonctionnalités réseau REBOL sont intégrées. Pour créer des scripts qui utilisent des protocoles réseau, vous n'avez pas besoin d'inclure des fichiers spéciaux ou des librairies. Le seul pré-requis est de fournir l'information minimale nécessaire pour activer les protocoles pour atteindre les serveurs ou passer les pare-feux ou les proxys. Par exemple, pour envoyer un e-mail, le protocole SMTP nécessite un nom de serveur SMTP et une adresse e-mail de réponse.

Paramétrages de base pour le réseau

Quand vous utilisez REBOL pour la première fois, il vous sera demandé d'indiquer les paramétrages nécessaires au réseau, lesquels seront stockés dans le fichier user.r.

REBOL utilise ce fichier pour charger les paramétrages réseau nécessaires à chacun de ses démarrages. Si un fichier user.r n'est pas créé, et que REBOL ne peut trouver un fichier user.r existant dans son environnement, aucun paramétrage ne sera chargé. Voir le chapitre sur les Opérations pour plus d'informations.

Pour modifier les paramétrages réseau, saisissez set-user à l'invite de commande. Ceci relance le même script de configuration pour le réseau exécuté lorsque REBOL démarre pour la première fois. Ce script est chargé à partir du fichier rebol.r. Si ce fichier ne peut être trouvé, ou si vous voulez éditer le paramétrage directement, vous pouvez utiliser un éditeur de texte pour modifier le fichier user.r.

Au sein du fichier user.r, les paramétrages réseau se trouvent dans un bloc qui suit la fonction set-net. Au minimum, le bloc devrait contenir deux items :
Votre adresse email à utiliser dans les champs "From" et "Reply" d'un email et pour un login anonyme.
Votre serveur par défaut ; ce peut être également votre serveur de mail primaire.

De plus, vous pouvez indiquez un certain nombre d'autres items :
Un serveur différent pour le mail entrant (pour POP).
Un serveur proxy (pour se connecter au réseau).
Un numéro de port pour le proxy.
Le type de proxy (voir les paramétrages du Proxy ci-dessous)

Vous pouvez aussi ajouter des lignes après la fonction set-net pour configurer d'autres genres de protocoles. Par exemple, vous pouvez définir les valeurs de time-out pour les protocoles, définir un mode FTP passif, un identifier "user-agent" pour le HTTP, des proxys séparés pour des protocoles différents, et plus.

Un exemple de bloc set-net est :


set-net [user@domain.dom mail.server.dom]

Le premier champ spécifie votre adresse email, et le second champ indique votre serveur de mail par défaut (remarquez qu'il n'est pas nécessaire de mettre des guillemets ici). Pour la plupart des réseaux, c'est suffisant et aucun autre paramétrage n'est nécessaire (à moins que vous n'utilisiez un serveur proxy). Votre serveur par défaut sera également utilisé si aucun autre serveur spécifique n'est mentionné.

De plus, si vous utilisez un serveur POP (pour les courriers entrants) différent de votre serveur SMTP (courrier sortant), vous pouvez le spécifier aussi


set-net [
user@domain.dom
mail.server.dom
pop.server.dom
]

Toutefois, si les serveurs POP et SMTP sont les mêmes, ceci n'est pas nécessaire.

Paramétrages du Proxy

Si vous utilisez un proxy ou un pare-feu (firewall), vous pouvez fournir à la fonction set-net les paramétrages du proxy. Ceci comprend le nom ou l'adresse du serveur proxy, un numéro de port pour accéder au serveur, et en option, le type de proxy.

Par exemple :


set-net [
email@addr
mail.example.com
pop.example.com
proxy.example.com
1080
socks
]

Cet exemple utilisera un serveur de proxy appelé proxy.example.com sur son port TCP 1080 avec la méthode "socks" pour le proxy. Pour utiliser un serveur socks4, utilisez le mot "socks4" au lieu de socks. Pour utilisez le serveur générique CERN, utilisez le mot "generic".

Vous pouvez aussi définir un serveur de proxy spécifique pour un scheme (protocole).

Chaque protocole possède son propre objet proxy que vous pouvez adapter spécifiquement selon le scheme. Voici un exemple de paramétrages de proxy pour FTP :


system/schemes/ftp/proxy/host: "proxy2.example.com"

system/schemes/ftp/proxy/port-id: 1080

system/schemes/ftp/proxy/type: 'socks

Dans ce cas, seul le protocole FTP utilise un serveur de proxy spécial. Notez que chaque nom de machine doit être une chaîne et que le type de proxy doit être un mot littéral.

Voici deux exemples supplémentaires. Le premier exemple définit un proxy de type générique (CERN) pour le HTTP :


system/schemes/http/proxy/host: "wp.example.com"

system/schemes/http/proxy/port-id: 8080

system/schemes/http/proxy/type: 'generic

Dans l'exemple ci-dessus, toutes les requêtes HTTP passent à travers un proxy de type générique sur l'adresse wp.example.com en utilisant le port 8080.


system/schemes/smtp/proxy/host: false

system/schemes/smtp/proxy/port-id: false

system/schemes/smtp/proxy/type: false

Dans l'exemple ci-dessus, l'intégralité du courrier sortant ne passe pas par un serveur de proxy. La valeur false empêche que le serveur de proxy par défaut soit utilisé. Si vous mettiez ces champs à none, alors le serveur de proxy par défaut sera utilisé, s'il a été configuré.

Si vous voulez contourner (bypasser) les paramétrages de proxy pour des machines particulières, comme celles situées sur votre réseau local, vous pouvez fournir une liste de machines autorisées (bypass list).

Voici une liste pour le serveur de proxy par défaut :


system/schemes/default/proxy/bypass:
["host.example.net" "*.example.com"]

Notez que l'astérisque (*) et le point d'interrogation ( ?) peuvent être utilisés pour des correspondances de machines. L'astérisque (*) est utilisé dans l'exemple précédent pour autoriser toutes les machines dont le nom se termine par example.com.

Pour définir une liste de machines autorisées seulement pour le scheme HTTP, utilisez :


system/schemes/http/proxy/bypass:
["host.example.net" "*.example.com"]

Autres paramétrages

En supplément des paramètres du proxy, vous pouvez définir des valeurs de time-out pour tous les schemes (par défaut) ou pour des schemes spécifiques. Par exemple, pour augmenter la valeur du time-out pour tous les schemes, vous pouvez écrire :


system/schemes/default/timeout: 0:05

Ceci définit un time-out réseau de 5 minutes. Si vous voulez juste augmenter le time-out pour le scheme SMTP, vous pouvez écrire :


system/schemes/smtp/timeout: 0:10

Certains schemes possèdent des champs personnalisés. Par exemple, le scheme FTP vous permet de définir un mode passif pour tous les transferts :


system/schemes/ftp/passive: on

Le mode FTP passif est pratique car les serveurs FTP configurés ainsi n'essayent pas de se connecter en retour au travers de votre pare-feu.

Lorsque vous essayer d'accéder à des sites Web, vous pouvez vouloir utiliser un champ "user-agent" différent dans la requête HTTP, afin d'obtenir de meilleurs résultats sur les quelques sites qui détectent le type de navigateur :

system/schemes/http/user-agent : "Mozilla/4.0"

Accéder aux paramétrages

Chaque fois que REBOL démarre, il lit le fichier user.r pour trouver ses paramétrages réseau. Ces paramétrages sont réalisés avec la fonction set-net.

Les scripts peuvent accéder à ces paramètres au travers de l'objet system/schemes.


system/user/email ; used for email from and reply
system/schemes/default/host - your primary server
system/schemes/pop/host - your POP server
system/schemes/default/proxy/host - proxy server
system/schemes/default/proxy/port-id - proxy port
system/schemes/default/proxy/type - proxy type

Ci-dessous se trouve une fonction qui renvoie un bloc contenant le paramétrage réseau dans le même ordre que la fonction set-net les acceptent :


get-net: func [][
reduce [
system/user/email
system/schemes/default/host
system/schemes/pop/host
system/schemes/default/proxy/host
system/schemes/default/proxy/port-id
system/schemes/default/proxy/type
]
]

probe get-net

DNS - Domain Name Service

DNS est le service réseau qui traduit les noms de domaine en leur adresse IP. De surcroît, vous pouvez utiliser DNS pour trouver une machine et son nom de domaine à partir d'une adresse IP.

Le protocole DNS peut être utilisé de trois manières : vous pouvez rechercher l'adresse IP primitive d'un nom de machine, ou un nom de domaine pour une adresse IP, et vous pouvez trouver le nom et l'adresse IP de votre machine locale.

Pour retrouver l'adresse IP d'une machine spécifique dans un domaine spécifique, saisissez :


print read dns://www.rebol.com
<span class="output">207.69.132.8</span>

Vous pouvez aussi obtenir le nom de domaine qui est associé avec une adresse IP particulière :


print read dns://207.69.132.8
<span class="output">rebol.com</span>

Notez qu'il n'est pas incongru pour cette recherche en reverse DNS de retourner le résultat none. Il existe des machines qui n'ont pas de noms.


print read dns://11.22.33.44
none

Pour déterminer le nom de votre système, essayez la lecture DNS d'une URL vide de la forme :


print read dns://
<span class="output">crackerjack</span>

Les données renvoyées ici dépendent du type de la machine. Cela peut être un nom de machine sans domaine, comme indiqué précédemment, mais être aussi un nom de machine complet, comme crackerjack.example.com. Ceci dépend du système d'exploitation et de la configuration réseau du système.

Voici un exemple qui recherche et affiche les adresses IP pour un certain nombre de sites Web :


domains: [
www.rebol.com
www.rebol.org
www.mochinet.com
www.sirius.com
]

foreach domain domains [
print ["address for" domain "is:"
read join dns:// domain]
]
address for www.rebol.com is: 207.69.132.8
address for www.rebol.org is: 207.66.107.61
address for www.mochinet.com is: 216.127.92.70
address for www.sirius.com is: 205.134.224.1

Whois

le protocole whois renvoie des informations concernant des noms de domaines depuis un référentiel central. Le service Whois est fourni par les organisations qui font fonctionner Internet. Whois est souvent utilisé pour retrouver les informations d'enregistrement d'un domaine Internet ou d'un serveur.

Il peut vous dire qui est propriétaire du domaine, comment leur contact technique peut être joint, et d'autres informations.

Pour obtenir ces informations, utilisez la fonction read avec une URL Whois.

Cette URL doit contenir le nom de domaine et le nom du serveur Whois séparés par un signe (@).

Par exemple, pour obtenir des informations concernant example.com depuis le référentiel Internet :


print read whois://example.com@rs.internic.net
<span class="output">connecting to: rs.internic.net
Whois Server Version 1.1
Domain names in the .com, .net, and .org domains can now be
registered with many different competing registrars. Go to
http://www.internic.net for detailed information.
Domain Name: EXAMPLE.COM
Registrar: NETWORK SOLUTIONS, INC.
Whois Server: whois.networksolutions.com
Referral URL: www.networksolutions.com
Name Server: NS.ISI.EDU
Name Server: VENERA.ISI.EDU
Updated Date: 17-aug-1999
<<< Last update of whois database: Sun, 16 Jul 00 03:16:34 EDT >>>
The Registry database contains ONLY .COM, .NET, .ORG, .EDU domains
and Registrars.</span>

Le code précédent est seulement un exemple. Le détail de l'information renvoyée, et les serveurs qui supportent Whois changent de temps en temps.

Si au lieu d'un nom de domaine, vous fournissez un mot, toutes les entrées qui correspondent à ce mot seront renvoyées :


print read whois://example@rs.internic.net
<span class="output">connecting to: rs.internic.net
Whois Server Version 1.1
Domain names in the .com, .net, and .org domains can now be
registered with many different competing registrars. Go to
http://www.internic.net for detailed information.
EXAMPLE.512BIT.ORG
EXAMPLE.ORG
EXAMPLE.NET
EXAMPLE.EDU
EXAMPLE.COM
To single out one record, look it up with "xxx", where xxx is one
of the of the records displayed above. If the records are the same, look them
up with "=xxx" to receive a full display for each record.
<<< Last update of whois database: Sun, 16 Jul 00 03:16:34 EDT >>>
The Registry database contains ONLY .COM, .NET, .ORG, .EDU domains
and Registrars.</span>

Le protocole Whois n'accepte pas les URLs, comme www.example.com, à moins que l'URL fasse partie du nom de la société enregistrée.

Finger

Le protocole finger retrouve des informations spécifiques à un utilisateur stockées dans le fichier log de l'utilisateur.

Pour pouvoir demander des informations sur un utilisateur à un serveur, celui-ci doit exécuter ce protocole finger. L'information est demandée en appelant avec read une URL finger qui comprend le nom de l'utilisateur et un nom de domaine, et se présente au format email :


print read finger://username@example.com

L'exemple précédent renvoie les informations concernant l'utilisateur référencé par username@example.com. L'information retournée dépend de celle que l'utilisateur a fourni et des paramétrages du serveur finger. Egalement, les détails de l'information retournée sont propres à chaque serveur ; les exemples ci-dessous décrivent seulement des serveurs génériques. La plupart des serveurs peuvent avoir des comportements non standards sur les requêtes finger.

Par exemple, l'information suivante pourrait être retournée :


<span class="output">Login: username
Name: Firstname Lastname
Directory: /home/user
Shell: /usr/local/bin/tcsh
Office: City, State +1 555 555 5555
Last login Wed Jul 28 01:10 (PDT) on ttyp0 from some.example.com
No Mail.
No Plan.</span>

Remarquez que finger informe de la dernière connexion de l'utilisateur sur la machine, et aussi s'il y a des courriers électroniques en attente pour lui. Si l'utilisateur lit un email à partir de son compte, parfois finger fournit cette information : lorsque l'email a été reçu et la dernière fois que l'utilisateur a récupéré son email :


<span class="output">New mail received Sun Sep 26 11:39 1999 (PDT)
Unread since Tue Sep 21 04:45 1999 (PDT)</span>

Le serveur finger peut aussi renvoyer le contenu d'un fichier plan ou un fichier projet s'ils existent. Les utilisateurs peuvent inclure n'importe quelle information qu'ils souhaitent dans un fichier plan ou projet.

Il est aussi possible de retrouver des informations sur les utilisateurs en utilisant leur nom ou leur prénom. Les serveurs finger ont besoin que vous mettiez en majuscules

Certains serveurs finger demandent que soient écrits en majuscule les noms tels qu'ils apparaissent dans le fichier de login ou dans le fichier en ligne utilisé par le serveur finger, pour retrouver les informations sur l'utilisateur. D'autres serveurs finger sont plus tolérants vis-à-vis de la mise en majuscules.

Un serveur finger répondra aux requêtes sur le vrai nom en renvoyant toutes les listes qui correspondent aux critères de recherches. Par exemple, si il y a plusieurs utilisateurs qui possèdent le même prénom zaphod, si vous saisissez la requête :


print read finger://Zaphod@main.example.com

celle-ci renverra tous les utilisateurs ayant pour prénom ou nom zaphod. Certains serveurs finger renvoient un listing d'utilisateurs quand le nom de l'utilisateur est omis. Par exemple, le code :


print read finger://main.example.com

retournera une liste de tous les utilisateurs connectés sur la machine, si le service finger installé sur celle-ci l'autorise.

Certaines machines limitent le service finger pour des raisons de sécurité. Elles peuvent demander un nom d'utilisateur valide, et renvoyer seulement les informations liées à cet utilisateur. Si vous interrogez un serveur finger de ce genre, sans fournir des informations sur l'utilisateur, le serveur vous répondra qu'il attend des informations sur un utilisateur spécifique.

Si un serveur ne supporte pas le protocole finger, REBOL retourne une erreur d'accès :


print read finger://host.dom
<span class="output">connecting to: host.dom
Access Error: Cannot connect to host.dom.
Where: print read finger://host.dom</span>

Daytime - Network Time Protocol

Le protocole daytime retourne le jour et l'heure courante. Pour se connecter à une serveur daytime, utiliser read avec une URL daytime. Cette URL comprend le nom du serveur devant renvoyer la date :


print read daytime://everest.cclabs.missouri.edu
<span class="output">Fri Jun 30 16:40:46 2000</span>

Le format de l'information renvoyée par les serveurs peut varier, selon le serveur. Notez que l'indication du fuseau horaire peut ne pas être présente.

Si le serveur que vous interrogez ne supporte pas le protocole daytime, REBOL renvoie une erreur :


print read daytime://www.example.com
<span class="output">connecting to: www.example.com
** Access Error: Cannot connect to www.example.com.
** Where: print read daytime://www.example.com</span>

HTTP - Hyper Text Transfer Protocol

Le Web (World Wide Web - WWW) est caractérisé par deux technologies fondamentales : HTTP, et HTML. HTTP est l'acronyme de "Hyper Text Transfer Protocol", le protocole qui contrôle comment des serveurs Web et des navigateurs Web communiquent les uns avec les autres. HTML signifie "Hyper Text Markup Language" qui définit la structure et le contenu d'une page Web.

Pour récupérer une page Web, le navigateur envoie sa requête à un serveur Web utilisant HTTP. A la réception de la requête, le serveur l'interprète, parfois en utilisant des scripts CGI (voir CGI - Common Gateway Interface), et renvoie des données. Ces données peuvent être n'importe quoi, dont du HTML, du texte, des images, des programmes ou du son.

Lecture d'une page Web

Pour lire une page Web, utilisez la fonction read avec une URL HTTP.

Par exemple :


page: read http://www.rebol.com

Ceci retourne une page Web pour www.rebol.com. Notez qu'une chaîne de caractères qui contient le code HTML (NdT : c'est-à-dire le code source de la page HTML), est renvoyée par la commande read. Aucune image ou graphique, ni aucune information n'est ramenée. Pour cela, il est nécessaire d'effectuer des opérations de lectures en complément. La page Web peut être affichée sous la forme de code HTML en utilisant print, elle peut être écrite dans un fichier avec la commande write, ou être envoyée dans un email avec la commande send.


print page

write %index.html page

send zaphod@example.com page

La page peut être manipulée de bien des façons, en utilisant diverses fonctions REBOL, comme parse, find, et load.

Par exemple, pour chercher au sein d'une page Web toutes les occurrences du mot REBOL, vous pouvez écrire :


parse read http://www.rebol.com [
any [to "REBOL" copy line to newline (print line)]
]

Scripts sur des sites Web

Un serveur Web peut manipuler plus que des scripts HTML. Les serveurs Web sont tout à fait pratiques pour fournir également des scripts REBOL.

Vous pouvez charger des scripts REBOL directement depuis un serveur Web avec la commande load :


data: load http://www.rebol.com/data.r

Vous pouvez aussi évaluer des scripts directement depuis un serveur Web avec la commande do :


data: do http://www.rebol.com/code.r

Avertissement : Soyez prudent avec cet usage de do. Evaluer sans précaution des scripts sur des serveurs Internet ouverts peut provoquer des dégâts. Evaluez un script uniquement si vous êtes certain de la fiabilité de sa source, si vous avez contrôlé sa source ou que vous avez conservé vos paramétrages de sécurité REBOL à leur plus haut niveau.

De plus, les pages Web qui contiennent du HTML peuvent aussi contenir des scripts REBOL insérés dedans, et peuvent être exécuter avec :


data: do http://www.rebol.com/example.html

Pour savoir si un script existe dans une page avant de l'évaluer, utilisez la fonction script ? .


if page: script? http://www.rebol.com [do page]

La fonction script ? lit la page depuis le site Web et renvoie celle-ci à partir de la position de l'en-tête REBOL.

Chargement de pages avec balises

Les pages HTML et XML peuvent être rapidement converties en bloc REBOL avec la fonction load/markup. Cette fonction renvoie un bloc constitué de toutes les balises et les chaînes de caractères trouvées dans la page. Tous les espaces et les sauts de ligne sont conservés.

Pour filtrer une page en ôtant toutes les balises Web et juste imprimer le texte, saisissez :


tag-text: load/markup http://www.rebol.com
text: make string! 2000

foreach item tag-text [
if string? item [append text item]
]

print text

Vous pouvez alors effectuer une recherche dans ce texte avec des modèles. Il contient tous les espaces et les sauts de ligne du fichier HTML original.

Voici un autre exemple qui contrôle tous les liens trouvés dans une page Web pour s'assurer de l'existence des pages à laquelles ces liens font référence :


REBOL []

page: http://www.rebol.com/developer.html
set [path target] split-path page
system/options/quiet: true ; turn off connexion msgs
tag-text: load/markup page
links: make block! 100

foreach tag tag-text [ ; find all anchor href tags
if tag? tag [
if parse tag [
"A" thru "HREF="
[^{"^} copy link to ^{"^} | copy link to ">"]
to end
][
append links link
]
]
]

print links

foreach link unique links [ ; try each link
if all [
link/1 <> #"#"
any [flag: not find link ":"
find/match link "http:"]
][
link: either flag [path/:link][to-url link]
prin [link "... "]
print either error? try [read link]
["failed"]["OK"]
]
]

Autres Fonctions

Pour vérifier si une page Web existe, utilisez la fonction exists ?, laquelle renvoie true si la page existe.


if exists? http://www.rebol.com [
print "page still there"
]

Note :

Habituellement, il est plus rapide dans la plupart des cas de juste lire la page, plutôt que de vérifier d'abord si elle existe. Par ailleurs, le script appelle deux fois le serveur et ceci peut être assez consommateur de temps.

Pour connaître la date de dernière modification d'une page Web, utilisez la fonction modified ? :


print modified? http://www.rebol.com/developer.html

Cependant, tous les serveurs Web ne fournissent pas cette information de date de modification. Typiquement, les pages générées dynamiquement ne renvoient pas de date de modification.

Une autre manière de déterminer si une page Web a changé est de l'interroger régulièrement et de la contrôler. Une façon pratique de vérifier si la page Web a changé est d'utiliser la fonction checksum.

Si la précédente valeur de checksum calculée diffère de la valeur courante, cela signifie que la page Web a été changée depuis le dernier contrôle. Voici un exemple qui utilise cette technique. Il vérifie une page toutes les huit heures.


forever [
page: read http://www.rebol.com
page-sum: checksum page
if any [
not exists? %page-sum
page-sum <gt; (load %page-sum)
][
print ["Page changed" now]
save %page-sum page-sum
send luke@rebol.com page
]
wait 8:00
]

Lorsque la page est modifiée, elle est envoyée par email à Luke.

Agir comme un Navigateur

Normalement, REBOL s'identifie lui-même vis-à-vis d'un serveur Web quand il lit une page. Cependant, certains serveurs sont programmés pour répondre uniquement à certains navigateurs. Si une requête à un serveur ne retourne pas la bonne page Web, vous pouvez modifier la requête pour la rendre identique à une venant d'un autre type de navigateur Web.

S'identifier comme étant un navigateur Web particulier est fait par de nombreux programmes, afin de permettre à des sites Web de répondre correctement. Cependant, cette pratique peut conduire à faire échouer l'utilisation normale après l'identification du navigateur.

Pour changer les requêtes HTTP et leur donner une ressemblance avec celles envoyées par Netscape 4.0, vous pouvez modifiez la valeur du user-agent au sein de l'agent (handler) HTTP :


system/options/http/user-agent: "Mozilla/4.0"

Modifier cette variable affecte toutes les requêtes HTTP qui suivent.

Envoi de requêtes CGI

Les requêtes HTTP CGI peuvent être émises de deux manières. Vous pouvez inclure les données de la requête dans l'URL ou bien, vous pouvez fournir les données de la requête au travers d'une opération d'envoi HTTP (POST).

Une requête avec une URL CGI utilise une URL normale. L'exemple ci-dessous envoie au script CGI test.r la valeur 10 pour sa variable data.


read http://www.example.com/cgi-bin/test.r?data=10

L'émission d'une requête CGI avec post nécessite que vous fournissiez les données CGI en tant que partie du raffinement custom de la fonction read. L'exemple ci-dessous montre comment est émise la requête CGI :


read/custom http://www.example.com/cgi-bin/test.r [
post "data: 10"
]

Dans cet exemple, le raffinement /custom est utilisé pour fournir des informations supplémentaires pour la lecture avec read. Le second argument est un bloc qui débute avec le mot post et continue avec la chaîne à envoyer.

La méthode "post" est pratique pour envoyer facilement du code REBOL et des données à un serveur Web en mode CGI. L'exemple suivant illustre ceci :


data: [sell 10 shares of "ACME" at $123.45]

read/custom http://www.example.com/cgi-bin/test.r reduce [
`post mold data
]

La fonction mold produira une chaîne formatée pour REBOL prête à être émise vers le serveur Web.

SMTP - Simple Mail Transport Protocol

Le protocole SMTP (Simple Mail Transport Protocol) détermine les transferts de messages électroniques via Internet. Le SMTP définit les interactions entre les serveurs Internet qui contribuent à relayer les courriers depuis leur expéditeur jusqu'à leur destinataire.

Envoi d'Email

Un courrier électronique est envoyé avec le protocole SMTP en utilisant la fonction send. Cette fonction peut expédier un courrier électronique vers une ou plusieurs adresses emails.

Pour que la fonction send opère correctement, vos paramètres réseau doivent être définis. La fonction send nécessite que vous spécifiez une adresse email (champ From d'un email), et votre serveur d'email par défaut. Voir le début de ce chapitre.

La fonction send prend deux arguments : une adresse email et un message.

Par exemple :


send user@example.com "Hi from REBOL"

Le premier argument doit être un email ou un bloc d'adresses emails (block). Le second argument peut être de n'importe quel type de données (datatype).


send luke@rebol.com $1000.00

send luke@rebol.com 10:30:40

send luke@rebol.com bill@ms.dom

send luke@rebol.com [Today 9-Apr-99 10:30]

Chacun de ces simples messages emails peut être interprété côté receveur (avec REBOL) ou visualisé avec un client normal de messagerie électronique. Vous pouvez envoyer un fichier complet d'abord en le lisant, puis en le passant comme second argument à la fonction send :


send luke@rebol.com read %task.txt

Des données binaires, comme des images ou des programmes exécutables, peuvent aussi être envoyées :


send luke@rebol.com read/binary %rebol

Les données binaires sont encodées de façon à permettre leur transfert sous forme de texte. Pour expédier un message binaire auto-extractible, vous pouvez écrire :


send luke@rebol.com join "REBOL for the job" [
newline "REBOL []" newline
"write/binary %rebol decompress "
compress read/binary %rebol
]

Lorsque le message est réceptionné, le fichier peut être extrait en utilisant la fonction do.

Destinataires multiples

Pour envoyer un message à de multiples destinataires, vous pouvez utiliser un bloc d'adresses emails :


send [luke@rebol.com ben@example.com] message

Dans ce cas, chaque message est individuellement adressé avec seulement un nom de destinataire apparaissant dans le champ To (identique à l'adressage en copie cachée BCC).

Le bloc d'adresses email peut être de n'importe quelle longueur ou même être un fichier que vous chargez. Il vous faut juste être attentif à avoir des adresses emails valides, et non des chaînes de caractères qui, elles, sont ignorées.


friends: [
bob@cnn.dom
betty@cnet.dom
kirby@hooya.dom
belle@apple.dom
...
]
send friends read %newsletter.txt

Courrier en masse

Si vous expédiez du courrier électronique à un groupe important, vous pouvez réduire la charge sur votre serveur en distribuant à chacun dans le groupe un simple message. C'est l'objet du raffinement /only. Il utilise une propriété du protocole SMTP pour envoyer seulement un message à des adresses emails multiples. En utilisant la liste "friends" de l'exemple précédent :


send/only friends message

Les messages ne sont pas adressés individuellement. Vous pouvez avoir vu ce mode dans certains des emails que vous pouvez recevoir. Lorsque vous recevez un courrier en masse, votre adresse n'apparaît pas dans le champ To. Le mode d'envoi en masse du SMTP devrait être utilisé pour les listes de diffusion, et pas pour de l'envoi de Spam. Le Spam est contraire à la Net-étiquette, il est illégal dans de nombreux pays et états, et peut conduire à votre exclusion de votre Fournisseur d'Accès Internet, et d'autres sites.

Ligne de sujet et en-têtes

Par défaut, la fonction send utilise la première ligne de l'argument message comme ligne de sujet pour le courrier électronique. Pour fournir une ligne de sujet personnalisée, vous devrez donner un en-tête d'email à la fonction send.

En complément du sujet, vous pouvez indiquer une organisation, une date, un champ CC, et même vos propres champs personnalisés.

Pour indiquer un en-tête, utiliser le raffinement /header de la fonction send, et incluez l'en-tête sous forme d'un objet. L'objet servant d'en-tête doit être composé à partir de l'objet system/standard/email. Par exemple :

header : make system/standard/email [


Subject: "Seen REBOL yet?"
Organization: "Freedom Fighters"

]

Notez que les champs standards comme l'adresse From, ne sont pas requis et sont automatiquement complétés par la fonction send.

L'en-tête est ensuite fourni en tant qu'argument à send/header :


send/header friends message header

Le courrier électronique ci-dessus est émis en utilisant l'en-tête personnalisé pour chacun des messages.

Déboguer vos scripts

Lors des tests de vos scripts utilisant send, il est judicieux de vous expédier à vous même le courrier électronique d'abord, avant de l'expédier à d'autres. Vérifiez et testez scrupuleusement vos scripts pour être sûrs de ce que vous voulez réaliser. Une erreur commune est d'envoyer un nom de fichier plutôt que son contenu. Par exemple, si vous écrivez :


send person %the-data-file.txt

ceci envoie le nom du fichier, et non son contenu.

POP - Post Office Protocol

Le protocole POP (Post Office Protocol) vous permet de récupérer le courrier électronique qui attend dans votre boîte aux lettres, sur un serveur de mails. POP définit un certain nombre d'opérations sur la façon d'accéder à votre boîte aux lettres (BAL) et de stocker des emails sur votre serveur.

Lecture d'Email

Vous pouvez lire tout votre courrier électronique en une seule ligne sans effacer quoique ce soit de votre serveur de courrier. Ceci est réalisé en lisant avec POP une URL comprenant votre nom d'utilisateur (compte de courrier), votre mot de passe, et le serveur de mails.


mail: read pop://user:pass@mail.example.com

Les courriers sont renvoyés sous la forme d'un bloc de plusieurs chaînes de caractères, que vous pouvez afficher une par une avec un code comme celui-ci :


foreach message mail [print message]

Pour lire individuellement des emails depuis le serveur, vous aurez besoin d'ouvrir un port de connexion avec le serveur puis de gérer chaque message un par un. Pour ouvrir un port POP :


mailbox: open pop://user:pass@mail.example.com

Dans cet exemple, "mailbox" est traitée comme une série, et la plupart des fonctions standards propres aux séries sont utilisables comme length ?, first, second, third, pick, next, back, head, tail, head ?, tail ?, remove, et clear.

Pour déterminer le nombre de messages électroniques sur le serveur, utilisez la fonction length ?.


print length? mailbox
<span class="output">37</span>

De plus, vous pouvez extraire la taille totale de tous les messages et leur taille individuellement avec :


print mailbox/locals/total-size

print mailbox/locals/sizes

NdT : on utilise ici une méthode de l'objet mailbox renvoyé par la fonction open.

Pour afficher le premier, le second, et le dernier message électronique, vous pouvez écrire :


print first mailbox

print second mailbox

print last mailbox

Vous pouvez aussi utiliser le fonction pick pour rapatrier un message spécifique :


print pick mailbox 27

Vous pouvez récuperer et afficher chaque message du plus ancien au plus récent en utilisant une boucle loop qui est identique à celle utilisée pour d'autres types de série :


while [not tail? mailbox] [
print first mailbox
mailbox: next mailbox
]

Vous aussi lire vos courriers électroniques du plus récent au plus ancien avec la boucle suivante :


mailbox: tail mailbox

while [not head? mailbox] [
mailbox: back mailbox
print first mailbox
]

Une fois terminées les opérations sur le port, fermez-le. Ceci est fait avec la ligne suivante :


close mailbox

Suppression d'emails

Comme avec les séries, la fonction remove peut être appelée pour effacer un seul message, et la fonction clear peut être utilisée pour effacer tous les messages depuis la position courante dans la liste, la série, jusqu'à la fin de mailbox.

Par exemple, pour lire un message, sauvez-le dans un fichier et effacez-le du serveur.


mailbox: open pop://user:pass@mail.example.com
write %mail.txt first mailbox
remove mailbox
close mailbox

Le message électronique est effacé du serveur lorsque la fonction close est exécutée. Pour effacer le 22ème message du serveur, vous pouvez écrire :


user:pass@mail.example.com
remove at mailbox 22
close mailbox

Vous pouvez effacer un nombre donné de messages en utilisant le raffinement /part avec la fonction remove :


remove/part mailbox 5

Pour effacer tous les messages de votre boîte aux lettres, utilisez la fonction clear :


mailbox: open pop://user:pass@example.com
clear mailbox
close mailbox

La fonction clear peut aussi est utilisée à différentes positions dans la série mailbox, de façon à n'effacer que les messages entre ces positions et jusqu'à la fin de la série.

Manipulation d'en-tête de courrier électronique

Les courriers électroniques peuvent inclure un en-tête. L'en-tête contient des informations sur l'expéditeur, le sujet, la date et d'autres champs.

En REBOL, les en-têtes d'email sont manipulés en tant qu'objets qui contiennent tous les champs nécessaires. Pour transformer un message email en objet, vous pouvez utiliser la fonction import-email. Par exemple :


msg: import-email first mailbox

print first msg/from ; the email address
print msg/date
print msg/subject
print msg/content

Vous pouvez alors facilement écrire un filtre qui scanne votre courrier électronique pour les messages qui débutent par un sujet particulier :


mailbox: open pop://user:pass@example.com

while [not tail? mailbox] [
msg: import-email first mailbox
if find/match msg/subject "[REBOL]" [
print msg/subject
]
mailbox: next mailbox
]

close mailbox

Voici un autre exemple qui vous alerte lorsque un email provenant d'un groupe d'amis est reçu :


friends: [orson@rebol.com hans@rebol.com]

messages: read pop://user:pass@example.com

foreach message messages [
msg: import-email message
if find friends first msg/from [
print [msg/from newline msg/content]
send first msg/from "Got your email!"
]
]

Ce filtre de spam efface du serveur tous les messages qui ne contiennent pas votre adresse email quelque part dans le message :


mailbox: open pop://user:pass@example.com

while [not tail? mailbox] [
mailbox: either find first mailbox user@example.com
[next mailbox][remove mailbox]
]

close mailbox

Voici une simple liste email qui reçoit des messages et les envoie à un groupe. Le serveur accepte juste les courriers des personnes du groupe.


group: [orson@rebol.com hans@rebol.com]

mailbox: open pop://user:pass@example.com

while [not tail? mailbox] [
message: import-email first mailbox
mailbox: either find group first message/from [
send/only group first mailbox
remove mailbox
][next mailbox]
]

close mailbox

FTP - File Transfer Protocol

Le protocole FTP (File Transfer Protocol) est extrêmement utilisé sur Internet pour transférer des fichiers depuis et vers une machine distante. Le FTP est couramment utilisé pour télécharger et mettre à jour des pages d'un site Web, et pour avoir en ligne des archives de fichier (sites de téléchargement).

Utilisation de FTP

Avec REBOL, les opérations relatives au protocole FTP sont effectuées de la même manière que si on avait des fichiers locaux.

Les fonctions telles que read, write, load, save, do, open, close, exists ?, size ?, modified ?, et d'autres encore sont utilisables avec FTP.

REBOL fait la distinction entre les fichiers locaux et les fichiers accessibles par FTP, au moyen de l'utilisation d'une URL FTP.

L'accès à des serveurs FTP peut être libre ou contrôlé. Des accès libres permettent à n'importe qui de se connecter au site FTP et de télécharger des archives, des fichiers. Ceci s'appelle un accès anonyme et est fréquemment utilisé pour des sites de téléchargement publics.

Les accès contrôlés nécessitent que vous fournissiez un nom d'utilisateur et un mot de passe pour accéder au site. C'est le principe pour la mise à jour de pages Web sur un site Web.

Bien que le protocole FTP ne requiert pas que votre configuration réseau REBOL soit OK, si vous utilisez un accès anonyme, une adresse email est souvent demandée. Cette adresse est trouvée dans l'objet system/user/email.

Normalement, lorsque vous démarrez REBOL, cette information est définie à partir de votre fichier user.r. Voir le chapitre sur le premier démarrage pour plus de détails. Si vous utilisez le protocole FTP au travers d'un pare-feu ou d'un serveur proxy, FTP doit être configuré pour opérer en mode passif. Le mode passif ne nécessite pas des connexions en retour depuis le serveur FTP vers le client, pour des transferts de données. Ce mode crée seulement des connexions sortantes depuis votre machine et permet d'avoir un haut niveau de sécurité. Pour engager le mode passif, vous devez positionner une variable dans l'agent (handler) du protocole FTP.


system/schemes/ftp/passive: true

Si vous ignorez si ce mode est nécessaire, essayez d'abord sans. Si cela ne fonctionne pas, paramétrez la variable comme ci-dessus.

URLs FTP

A la base, une URL FTP possède la forme suivante :


ftp://user:pass@host/directory/file

Pour des accès anonymes, le nom d'utilisateur (user) et le mot de passe (password) peuvent être omis :


ftp://host/directory/file

La plupart des exemples dans cette section utilise cette forme simple ; cependant, ils marchent aussi avec un nom d'utilisateur et un mot de passe.

Pour atteindre un répertoire distant, terminez l'URL par le symbole "slash" ( / ), comme avec :


ftp://user:pass@host/directory/

ftp://host/directory/

ftp://host/

Vous trouverez plus loin plus d'informations sur l'accès à des répertoires distants.

Il est commode de placer l'URL dans une variable et d'utiliser les paths pour fournir des noms de fichiers. Ceci permet de faire référence à l'URL avec juste un mot.

Par exemple :


site: ftp://ftp.rebol.com/pub/
read site/readme.txt

Cette technique est mise en oeuvre dans les sections qui suivent.

Transfert de fichiers Texte

Le protocole FTP établit une distinction entre les fichiers texte et les fichiers binaires. Lors du transfert de fichiers texte, FTP convertit les caractères de fin de ligne. Cela n'est pas souhaitable pour les fichiers binaires.

Pour lire un fichier texte, passez à la fonction read une URL FTP :


file: read ftp://ftp.site.com/file.r

Ceci met le contenu du fichier dans une chaîne (ici, file). Pour écrire ce fichier localement, utilisez cette ligne :


write %file.r read ftp://ftp.site.com/file.r

La plupart des raffinements de la fonction read sont également utilisables. Par exemple, vous pouvez utilisez read/lines avec :


data: read/lines ftp://ftp.site.com/file.r

Cet exemple renvoie le fichier sous la forme d'un bloc de lignes. Voir le chapitre sur les Fichiers pour plus d'informations sur les raffinements de la fonction read.

Pour écrire un fichier texte sur le serveur FTP, utilisez la fonction write :


write ftp://ftp.site.com/file.r read %file.r

La fonction write peut prendre aussi des raffinements. Voir le chapitre sur les Fichiers.

Comme normalement avec les transferts de fichiers texte, toutes les fins de lignes seront correctement converties durant le transfert FTP.

Voici un simple script qui met à jour les fichiers de votre site Web :


site: ftp://wwwuser:secret@www.site.dom/pages

files: [%index.html %home.html %info.html]

foreach file files [write site/:file read file]

Ceci ne devrait pas être utilisé pour transférer des images ou des fichiers de son, qui sont binaires. Utilisez la technique montrée dans la section suivante sur le Transfert de fichiers binaires.

En complément des fonctions read et write, vous pouvez aussi utilisez load, save, et do avec FTP.


data: load ftp://ftp.site.com/database.r

save ftp://ftp.site.com/data.r data-block

do ftp://ftp.site.com/scripts/test.r

Transfert de fichiers binaires

Pour évitez la conversion des caractères de fin de ligne, lors du transfert de fichiers binaires (images, archives zippés, fichiers exécutables), utilisez le raffinement /binary.

Par exemple, pour lire un fichier binaire depuis un serveur FTP :


data: read/binary ftp://ftp.site.com/file

Pour faire en local une copie du fichier :


write/binary %file read/binary ftp://ftp.site.com/file

Pour écrire un fichier binaire sur un serveur :


write/binary ftp://ftp.site.com/file read/binary %file

Aucune conversion de fin de ligne n'est réalisée.

Pour transférer un ensemble de fichiers graphiques sur un site Web, utilisez le script :


site: ftp://user:pass@ftp.site.com/www/graphics

files: [%icon.gif %logo.gif %photo.jpg]

foreach file files [
write/binary site/:file read/binary file
]

Ajout à des fichiers

Le protocole FTP vous permet aussi d'ajouter du texte ou des données à un fichier existant. Pour faire cela, utilisez le raffinement write/append comme cela est décrit dans le chapitre sur les Fichiers.


write/append ftp://ftp.site.com/pub/log.txt reform
["Log entry date:" now newline]

Ceci peut aussi être fait avec des fichiers binaires.


write/binary/append ftp://ftp.site.com/pub/log.txt
read/binary %datafile

Consultation de répertoires

Pour lire le contenu d'un répertoire FTP distant, faites suivre le nom du répertoire d'un symbole "/" (slash).


print read ftp://ftp.site.com/
pub-files: read ftp://ftp.site.com/pub/

Le slash terminal (/) indique qu'il s'agit d'un accès à un répertoire et non à un fichier. Le slash n'est pas toujours nécessaire mais il est recommandé dés lors que vous savez que vous accédez à un répertoire.

Le bloc de noms de fichiers qui est renvoyé comprend tous les éléments du répertoire. Au sein du bloc, les noms de répertoires sont signalés avec un slash à la fin de leur nom.

Par exemple :


foreach file read ftp://ftp.site.com/pub/ [
print file
]
readme.txt
rebol.r
rebol.exe
library/docs/

Vous pouvez aussi utilisez la fonction dir ? sur un élément pour déterminer s'il s'agit d'un fichier ou d'un répertoire.

Information concernant les fichiers

Les mêmes fonctions qui fournissent de l'information concernant les fichiers locaux peuvent aussi fournir des informations sur les fichiers distants FTP. Ceci inclut les fonctions modified ?, size ?, exists ?, dir ?, et info ?.

Vous pouvez utilisez la fonction exists ? pour savoir si un fichier existe :


if exists? ftp://ftp.site.com/pub/log.txt [
print "Log file is there"
]

Ceci marche également avec les répertoires, mais pensez à inclure le slash final après le nom du répertoire :


if exists? ftp://ftp.site.com/pub/rebol/ [
print read ftp://ftp.site.com/pub/rebol/
]

Pour connaître la taille ou la date de modification d'un fichier :


print size? ftp://ftp.site.com/pub/log.txt

print modified? ftp://ftp.site.com/pub/log.txt

Pour déterminer si un nom d'élément est celui d'un répertoire :


if dir? ftp://ftp.site.com/pub/text [
print "It's a directory"
]

Vous pouvez obtenir toutes ces informations en une seule requête avec la fonction info ? :


file-info: info? ftp://ftp.site.com/pub/log.txt

probe file-info

print file-info/size

Pour effectuer la même action sur un répertoire :


probe info? ftp://ftp.site.com/pub/

Pour afficher le contenu d'un répertoire :


files: open ftp://ftp.site.com/pub/

forall files [
file: first files
info: info? file
print [file info/date info/size info/type]
]

Créer un répertoire

De nouveaux répertoires FTP peuvent être créés avec la fonction make-dir :


make-dir ftp://user:pass@ftp.site.com/newdir/

Suppression de fichiers

En supposant que vous ayez les permissions appropriées pour cela, des fichiers peuvent être supprimés du serveur FTP en utilisant la fonction delete :


delete ftp://user:pass@ftp.site.com/upload.txt

Vous pouvez aussi effacer des répertoires :


delete ftp://user:pass@ftp.site.com/newdir/

Notez que le répertoire doit être vide pour que sa suppression puisse se faire.

Renommage de fichiers

Vous pouvez renommer un fichier avec la ligne :


rename ftp://user:pass@ftp.site.com/foo.r %bar.r

Le nouveau nom du fichier sera bar.r.

Le protocole FTP permet aussi de déplacer un fichier vers un autre répertoire avec :


rename ftp://user:pass@ftp.site.com/foo.r %pub/bar.r

Pour renommer un répertoire sur un site FTP, là encore n'oubliez pas le slash à la fin du nom du répertoire :


rename ftp://user:pass@ftp.site.com/rebol/ rebol-old/

Au sujet des mots de passe

Les exemples ci-dessus incluent le mot de passe au sein des URLs, mais si vous prévoyez de partager votre script, vous ne voulez probablement pas que cette information soit connue. Voici une manière simple de demander le mot de passe via un interrogation en ligne de commande (prompt) et de construire l'URL adéquate :


pass: ask "Password? "

data: read join ftp://user: [pass "@ftp.site.com/file"]

Ou, vous pouvez demander à la fois le nom de l'utilisateur et le mot de passe :


user: ask "Username? "
pass: ask "Password? "
data: read join ftp:// [
user ":" pass "@ftp.site.com/file"
]

Vous pouvez aussi ouvrir une connexion FTP en spécifiant un port plutôt qu'une URL. Ceci vous permet d'utiliser n'importe quel mot de passe, même ceux pouvant contenir des caractères spéciaux qui ne sont pas facile à écrire dans une URL.

Un exemple de spécification pour un port ouvrant une connexion FTP serait :


ftp-port: open [
scheme: `ftp
host: "ftp.site.com"
user: ask "Username? "
pass: ask "Password? "
]

Voir la partie sur la spécification de ressources réseau ci-dessus pour plus de détail.

Transfert de fichiers volumineux

Le transfert de fichiers volumineux nécessite quelques considérations particulières. Vous souhaitez sans doute transférer un fichier par morceaux pour réduire la quantité de mémoire requise par votre ordinateur, et pour fournir à l'utilisateur un retour sur l'évolution du transfert.

Voici un exemple qui télécharge un très gros fichier par morceaux.


inp: open/binary/direct ftp://ftp.site.com/big-file.bmp
out: open/binary/new/direct %big-file.bmp
buf-size: 200000
buffer: make binary! buf-size + 2

while [not zero? size: read-io inp buffer buf-size][
write-io out buffer size
total: total + size
print ["transferred:" total]
]

Utilisez absolument le raffinement /direct, faute de quoi le fichier entier sera mis en buffer en interne de REBOL. Les fonctions read-io et write-io permettent de réutiliser la mémoire du buffer qui a déjà été allouée. D'autres fonctions comme copy alloue de la mémoire supplémentaire.

Si le transfert s'interrompt, vous pouvez redémarrer le transfert FTP à partir de l'endroit où il s'est arrêté. Pour cela, examinez le fichier résultant (out) ou la taille pour déterminer d'où recommencer le transfert.

Ouvrez à nouveau le fichier avec le raffinement /custom en spécifiant le mot restart et l'endroit d'où redémarrer la lecture.

Voici un exemple avec la fonction open où la variable "total" indique la longueur déjà lue du fichier :


inp: open/binary/direct/custom
ftp://ftp.site.com/big-file.bmp
reduce ['restart total]

Notez que le redémarrage d'un transfert FTP fonctionne seulement avec des transferts binaires. Il ne peut être effectué avec des transferts de fichiers texte parce que les conversions de caractères de fin de ligne induisent des modifications de taille.

NNTP - Network News Transfer Protocol

Le protocole NNTP (Network News Transfer Protocol) est la base pour des dizaines de milliers de newsgroups qui assurent un forum public pour des millions d'utilisateurs d'Internet. REBOL comprend deux niveaux de support pour le protocole NNTP.
Le support interne qui autorise des fonctionnalités et des accès très limités. C'est le scheme NNTP.
Un niveau supérieur de fonctionnalité qui est assuré par le scheme news, implémenté dans le fichier appelé nntp.r.

Lecture d'une liste de newsgroup

NNTP comprend deux composants : une liste de newsgroups supportés par un serveur de newsgroup dédié (typiquement, les newsgroups sont sélectionnés par les fournisseurs d'accès à Internet) ; et une base de données de messages en cours qui se rapportent à des newsgroups particuliers.

Pour retrouver la liste des messages de tous les newsgroups pour un serveur de news spécifique, utilisez la fonction read avec une URL NNTP telle que :


groups: read nntp://news.example.com

Cette opération peut durer un certain temps, selon votre connexion ; il y a des milliers de newsgroups.

Lire tous les messages

Si vous utilisez une connexion rapide, vous pouvez lire tous les messages relatif à un newsgroup avec :


messages: read nntp://news.example.com/alt.test

Cependant, soyez prudents. Certains newsgroups peuvent avoir des milliers de messages. Cela peut prendre un long moment pour télécharger tous les messages, et être très consommateur en mémoire, pour les manipuler.

Lecture de messages particuliers

Pour lire des messages spécifiques, ouvrez NNTP avec un port, et utilisez les fonctions relatives aux séries pour accéder aux messages. C'est assez similaire au fonctionnement vu précédemment pour la lecture de vos emails avec un port POP.

Par exemple :


group: open nntp://news.example.com/alt.test

Vous pouvez utilisez la fonction length ? pour déterminer le nombre de messages valables pour le newsgroup :


print length? group

Pour lire le premier message pour le newsgroup, utilisez la fonction first :


message: first group

Pour sélectionner un message spécifique dans le groupe, via son index, utilisez pick :


message: pick group 37

Pour créer un simple boucle permettant de scanner tous les messages contenant un mot-clé :


forall group [
if find msg: first first group "REBOL" [
print msg
]
]

Rappelez-vous qu'à la fin de la boucle, la série est positionnée sur sa fin (tail). Si vous avez besoin de revenir au début de la série des messages :


group: head group

N'oubliez pas non plus de fermer le port une fois que vous avez terminé de l'utiliser :


close group

Manipulation des en-têtes de News

Les messages des news incluent systématiquement un en-tête. L'en-tête stocke des informations sur l'expéditeur, le résumé, des mot-clés, le sujet, la date, et d'autres champs également.

Les en-têtes sont manipulés sous la forme d'objet REBOL. Pour convertir un message de news, en objet d'en-tête, vous pouvez utilisez la fonction import-email.

Par exemple,


message: first first group
header: import-email message

Vous pouvez à présent accéder aux différents champs du message de news :


print [header/from header/subject header/date]

Les différents newsgroups et les différents clients utilisent différents champs pour leurs en-têtes. Pour voir les champs valables pour un message particulier, affichez le premier item de l'objet d'en-tête, ici appelé header :


print first header

Expédier un message

Avant d'envoyer un message, vous devez créer un en-tête pour lui. Voici un en-tête générique qui peut être utilisé pour les newsgroups :


news-header: make object! [
Path: "not-for-mail"
Sender: Reply-to: From: system/user/email
Subject: "Test message"
Newsgroups: "alt.test"
Message-ID: none
Organization: "Docs For All"
Keywords: "Test"
Summary: "A test message"
]

Avant de l'envoyer, vous devez créer un numéro d'identification global pour lui. Voici une fonction qui réalise cela :


make-id: does [
rejoin [
"<"
system/user/email/user
"."
checksum form now
"."
random 999999
"@"
read dns://
">"
]
]
print news-header/message-id: make-id
<span class="output"><carl.4959961.534798@fred.example.com></span>

A présent, vous pouvez combiner l'en-tête avec le message. Ils doivent être séparés par au moins une ligne blanche. Le contenu du message est lu à partir d'un fichier.


write nntp://news.example.net/alt.test rejoin [
net-utils/export news-header
newline newline
read %message.txt
newline
]

CGI - Common Gateway Interface

Le mode CGI (Common Gateway Interface) est utilisé avec de nombreux serveurs Web pour effectuer des traitements en plus et au delà de l'interface Web normale.

Les requêtes CGI sont soumises par des navigateurs Web à des serveurs Web. Typiquement, lorsque qu'un serveur reçoit une requête CGI, il exécute un script qui traite la requête et renvoie un résultat au navigateur. Ces scripts CGI sont écrits dans de très nombreux langages, et l'un des manières les faciles de manipuler du CGI est d'utiliser REBOL.

Paramétrage du serveur CGI

Le paramètrage d'un accés CGI est différent pour chaque serveur Web. Voir les instructions fournies avec votre serveur.

Typiquement, un serveur possède une option permettant d'activer le mode CGI. Vous devez activer cette option et fournir un chemin vers le répertoire où se trouvent vos scripts CGI. Un répertoire courant pour les scripts CGI s'appelle cgi-bin.

Sur les serveurs Web Apache, l'option ExecCGI active le mode CGI, et vous devez indiquer un répertoire (cgi-bin) pour vos scripts. C'est le mode de fonctionnement par défaut d'Apache.

Pour configurer CGI pour Microsoft IIS, allez dans les propriétés pour cgi-bin, et cliquez sur le bouton pour la configuration. Sur le panneau de configuration, cliquez sur "add" et entrez le chemin vers l'exécutable rebol.exe. La syntaxe pour cela est :


C: ebol ebol.exe -cs %s %s

Les deux symboles %s sont nécessaires pour passer correctement le script et les arguments en ligne de commande à REBOL. Ajoutez l'extension propre aux fichiers REBOL (.r), et mettez le dernier champ sur PUT, DELETE. L'item "script engine" n'a pas besoin d'être sélectionné.

L'option -cs qui est passée à REBOL permet le mode CGI et autorise le script à accéder à tous les fichiers ( !! Voir notes ci-dessous sur comment les scripts peuvent limiter les accès à des fichiers pour des répertoires spécifiques.)

D'autres serveurs Web que ceux décrits au-dessus nécessitent d'être configuré pour pouvoir exécuter l'exécutable REBOL avec des fichiers portant l'extension .r et avec l'option demandée -cs.

Scripts CGI

Avant de pouvoir exécuter un script sur la plupart des serveurs CGI, celui-ci devra disposer des permissions de fichiers adéquates. Sur les systèmes de type Unix ou ceux utilisant un serveur Apache, il sera nécessaire de modifier les permissions pour autoriser le script en lecture et en exécution pour tous les utilisateurs. Cela peut être fait avec la fonction Unix chmod.

Si vous être débutant dans ces concepts, vous devriez lire le manuel de votre système d'exploitation, ou demander à votre administrateur système avant de modifier les permissions du fichier.

Pour Apache, et divers autres serveurs Web qui exécutent des scripts REBOL, vous devez placer un en-tête dédié au début de chaque script. L'en-tête indique le chemin vers l'exécutable REBOL et l'option -cs. Voici un simple script CGI qui affiche la chaîne de caractères "hello !".


#!/path/to/rebol -cs

REBOL [Title: "CGI Test Script"]

print "Content-Type: text/plain"

print "" ; required

print "Hello!"

De nombreuses choses peuvent empêcher un script CGI de fonctionner correctement. Testez d'abord ce simple script avant d'en essayez de plus complexe. Si votre script ne marche pas, voici quelques points à vérifiez :
Vous avez activé l'option CGI sur votre serveur Web.
La première ligne du script commence par # ! et le chemin exact vers REBOL.
L'option -cs est fournie à REBOL.
Le script commence avec l'affichage de "Content-Type :" ( !!voir ci-dessous)
Le script est dans le bon répertoire. (normalement, le répertoire cgi-bin).
Le script a les permissions adéquates (lecture et exécution pour tous).
Le script contient le saut de ligne nécessaire. Certains serveurs n'exécuteront pas le script s'il celui-ci ne contient pas le caractère CR (carriage return) pour les sauts de lignes. Vous devrez convertir le fichier. (Utilisez REBOL pour faire cela en une ligne : write file read file).
Le script ne contient pas d'erreurs. Testez-le hors du mode CGI pour être sûr que le script se charge (n'a pas d'erreurs de syntaxe) et fonctionne proprement. Fournissez lui quelques données en exemple, et testez-le avec.
Tous les fichiers auquel le script doit accéder ont les permissions adéquates.

Souvent l'un ou plusieurs de ces points n'est pas correct et empêche votre script de marcher. Vous aurez une erreur au lieu de voir une page Web. Si cette erreur est du type "Server Error" ou "CGI error", alors typiquement, il y a quelque chose à faire avec les droits ou le paramétrage du script. S'il s'agit d'un message d'erreur REBOL, alors le script est exécuté, mais vous avez une erreur à l'intérieur du script.

Dans le script présenté ci-dessus en exemple, la ligne "Content-Type" est critique. C'est la partie de l'en-tête HTTP qui est renvoyée vers le navigateur et qui l'informe du type de contenu qu'il va recevoir. Cette ligne est suivie d'une ligne vierge, qui la sépare du contenu.

Différents types de contenu peuvent être retourné. L'exemple précédent était en texte, mais vous pouvez aussi retourner du HTML comme montré dans l'exemple suivant. (Voir le manuel de votre serveur Web pour plus d'informations sur les types de contenu).

Le type de contenu et la ligne vierge peuvent être combinées en une seule ligne. L'ajout du symbole (^^/) (accent circonflexe suivi d'un slash) est assimilable à une ligne vierge, qui effectue la séparation d'avec le contenu.


print "Content-Type: text/plain^^/"

C'est une bonne habitude de toujours afficher cette ligne immédiatement au début de votre script. Cela permet le renvoi des messages d'erreur vers le browser si votre script rencontre une erreur.

Voici un simple script CGI qui affiche l'heure :


#!/path/to/rebol -cs

REBOL [Title: "Time Script"]

print "Content-Type: text/plain^^/"

print ["The time is now" now/time]

Générer du contenu HTML

Il y a autant de manières de créer du contenu HTML qu'il y a de façons de créer des chaînes de caractères. Ce code génère une page qui affiche un compteur du nombre de visiteurs :


#!/path/to/rebol -cs

REBOL [Title: "HTML Example"]

print "Content-Type: text/html^^/"

count: either exists? %counter [load %counter][0]
save %counter count: count + 1

print [
^{<HTML><BODY><H2>Web Counter Page</H2>
You are visitor^} count ^{to this page!<P>
</BODY></HTML>^}
]

Le script en exemple ci-dessus charge et sauvegarde le compteur via un fichier texte. Pour rendre accessible ce fichier, il est nécessaire de lui donner les droits appropriés afin de le rendre accessible par tous les utilisateurs.

Environnement et variables CGI

Lorsqu'un script CGI s'exécute, le serveur fournit des informations à REBOL concernant la requête CGI et ses arguments. Toutes ces informations sont placées sous la forme d'un objet dans l'objet system/options. Pour voir les attributs de cet objet, saisissez :


probe system/options/cgi
<span class="output">make object! [
server-software: none
server-name: none
gateway-interface: none
server-protocol: none
server-port: none
request-method: none
path-info: none
path-translated: none
script-name: none
query-string: none
remote-host: none
remote-addr: none
auth-type: none
remote-user: none
remote-ident: none
Content-Type: none
content-length: none
other-headers: []
]</span>

Bien sûr, votre script ignorera la plupart de ces informations, mais certaines d'entre elles peuvent être utiles. Par exemple, vous voudrez créer un fichier log qui enregistre les adresses réseau des machines effectuant les requêtes, ou vérifiant le type de navigateur utilisé.

Pour générer une page CGI qui affiche ces informations dans votre navigateur :


#!/path/to/rebol -cs

REBOL [Title: "Dump CGI Server Variables"]

print "Content-Type: text/plain^^/"

print "Server Variables:"

probe system/options/cgi

Si vous voulez utilisez ces informations dans un fichier log, vous devrez les écrire dans un fichier. Par exemple, pour enregistrer les adresses des visiteurs de votre page CGI, vous devrez écrire :


write/append/lines %cgi.log
system/options/cgi/remote-addr

Les raffinements /append et /lines forcent l'écriture à s'effectuer à la suite des enregistrements précédents et ligne par ligne. Voici une autre approche qui inscrit plusieurs items sur la même ligne :


write/append %cgi.log reform [
system/options/cgi/remote-addr
system/options/cgi/remote-ident
system/options/cgi/content-type
newline
]

Requêtes CGI

Il existe deux méthodes pour fournir des données à votre script CGI : GET et POST. La méthode GET encode les données CGI dans l'URL. Elle est utilisée pour fournir des informations au serveur. Vous aurez remarqué sans doute que certaines URLs ressemblent à celle-ci :


http://www.example.com/cgi-bin/test.r?&data=test

La chaîne de caractères qui suit le point d'interrogation ( ?) fournit les arguments au script CGI. Parfois, ceux-ci peuvent être assez longs. La chaîne est passée à votre script lorsque celui s'exécute. Elle peut être obtenue à partir de l'attribut cgi/query-string.

Par exemple, pour afficher cette chaîne depuis un script :


print system/options/cgi/query-string

Les données contenues dans la chaîne peuvent inclure n'importe quelle data dont vous avez besoin. Cependant, parce que cette chaîne fait partie de l'URL, les données doivent y être encodées. Il y a des restrictions sur les caractères qui y sont autorisés.

De plus, lorsque ces données sont produites par un formulaire HTML, elles sont encodées de façon standard. Ces données peuvent être décodées et mises dans un objet avec le code :


cgi: make object! decode-cgi-query
system/options/cgi/query-string

La fonction decode-cgi-query renvoie un bloc qui contient les noms des variables et leurs valeurs. Voir l'exemple avec le formulaire HTML dans la section suivante.

La méthode POST transmet les données CGI sous forme d'une chaîne. Les données n'ont pas besoin d'être encodées. Elles peuvent être dans n'importe quel format que vous le souhaitez et peuvent même être binaires. Les données sont lues à partir de l'entrée standard. Vous devrez les lire depuis l'entrée standard avec un code comme celui-ci :


data: make string! 2002
read-io system/ports/input data 2000

Ceci devrait sélectionner les 2000 premiers octets de données POST et les mettre dans une chaîne de caractères.

Une bonne pratique pour les données POST est d'utiliser un dialecte REBOL et de créer un petit analyseur (parseur). Les données POST peuvent être chargées et analysées sous forme de bloc. Voir le chapitre sur le Parsing.

Avertissement au sujet des blocs :

Ce n'est pas une bonne idée de passer à REBOL des blocs pour qu'ils soient directement évalués, car cela induit un risque sur la sécurité. Par exemple, quelqu'un pourrait envoyer via POST un bloc qui permettrait de lire ou d'écrire des fichiers sur le serveur. Par ailleurs, passer des blocs qui sont interprétés par votre script (via un dialecte) est sans danger.

Voici un exemple de script qui affiche les datas POST dans votre navigateur :


#!/path/to/rebol -cs

REBOL [Title: "Show POST data"]

print "Content-Type: text/html^^/"
data: make string! 10000
foreach line copy system/ports/input [
repend data [line newline]
]

print [
<HTML><BODY>
^{Here is the posted data.^}
----<PRE>data</PRE>
</BODY></HTML>
]

Traitement des formulaires HTML

Le protocole CGI est utilisé souvent afin de traiter des formulaires HTML. Les formulaires acceptent des champs variés et les soumettent au serveur Web avec la méthode GET ou la méthode POST.

Voici un exemple qui utilise la méthode GET du CGI pour traiter un formulaire et envoyer un email en guise de résultat. Il y a deux parties : la page HTML et le script CGI.

Voici une page HTML qui comprend un formulaire :


<HTML><BODY>

<FORM ACTION="http://example.com/cgi-bin/send.r" METHOD="GET">

<H1>CGI Emailer</H1>----

Enter your email address:<P>

<INPUT TYPE="TEXT" NAME="email" SIZE="30"><P>

<TEXTAREA NAME="message" ROWS="7" COLS="35">
Enter message here.
</TEXTAREA><P>

<INPUT TYPE="SUBMIT" VALUE="Submit">

</FORM>
</BODY></HTML>

Lorsque le formulaire HTML est validé, il est traité par la méthode GET et les datas passées au script send.r. Voici un exemple de script. Ce script décode les données du formulaire et envoie le message électronique. Il retourne une page de confirmation.


#!/path/to/rebol -cs

REBOL [Title: "Send CGI Email"]

print "Content-Type: text/html^^/"

cgi: make object! decode-cgi-query
system/options/cgi/query-string

print ^{<HTML><BODY><H1>Email Status</H1>----<P>^}

failed: error? try [send to-email cgi/email cgi/message]

print either failed [
^{The email could not be sent.^}
][
[^{The email to^} cgi/email ^{was sent.^}]
]

print ^{</BODY><HTML>^}

Ce script doit être nommé send.r et être placé dans le répertoire cgi-bin. Ses droits doivent permettrent qu'il soit lu et exécuté par tous.

Lorsque le formulaire HTML aura été soumis par un navigateur, le script s'exécutera. Il décode la chaîne de caractères de la requête CGI dans l'objet cgi. L'objet a comme variables l'email et le message qui sont utilisés par la fonction send. Avant l'envoi du courrier électronique, le champ "email", de type string, est converti en type de données email. La fonction send est placée à l'intérieur d'un bloc try pour capturer les erreurs pouvant se produire, et le message qui est généré dans ce cas.

D'autres exemples de scripts CGI peuvent être trouvés dans la bibliothèque de scripts REBOL : http://www.rebol.com/library/library.html.

TCP - Transmission Control Protocol

En supplément de tous les protocoles décrits précédemment, vous pouvez créer vos propres serveurs et clients avec le protocole TCP (Transmission Control Protocol).

Créer des clients

Des ports TCP peuvent être ouverts avec REBOL de la même façon qu'avec les autres protocoles, en utilisant une URL TCP. Pour ouvrir une connexion TCP vers un serveur Web (HTTP), sur le port 80 :


http-port: open tcp://www.example.com:80

Une autre manière d'ouvrir une connexion TCP est de fournir les spécifications de port directement. Cela remplace l'ouverture d'une URL et est souvent plus commode :


http-port: open [
scheme: 'tcp
host: "www.example.com"
port-id: 80
]

Puisque les ports sont des séries, vous pouvez utilisez les fonctions relatives aux séries pour émettre et recevoir des données. L'exemple ci-dessous effectue une requête sur le serveur HTTP ouvert dans l'exemple précédent. Il utilise la fonction insert pour placer des datas dans la série, le port http-port qui les envoie au serveur :


insert http-port join "GET / HTTP/1.0^^/^^/"

Les deux caractères de nouvelle ligne (^^/) sont utilisés pour signifier au serveur que l'en-tête HTTP a été émis.

Les caractères (^^/ ou newline) sont automatiquement convertis en séquences CR LF car le port a été ouvert en mode texte. Le serveur traite la requête HTTP et retourne un résultat au port. Pour lire le résultat, utilisez la fonction copy :


while [data: copy http-port] [prin data]

Cette boucle continuera de récupérer les datas jusqu'à ce que none soit retourné par la fonction copy. Ce comportement diffère selon les protocoles. Un "none" est retourné car le serveur ferme la connexion. D'autres protocoles peuvent utiliser un caractère spécial pour marquer la fin du transfert.

A présent que toutes les datas ont été reçues, le port HTTP doit être fermé :


close http-port

Voici un autre exemple qui ouvre un port POP en TCP sur un serveur :


pop: open/lines tcp://fred.example.com:110

Cet exemple utilise le raffinement /lines. La connexion sera à présent orientée lignes. Les données seront lues et écrites sous forme de lignes.

Pour lire la première ligne depuis le serveur :


print first pop
<span class="output">+OK QPOP (version 2.53) at fred.example.com starting.</span>

Pour émettre vers le serveur un nom d'utilisateur pour le login POP :


insert pop "user carl"

Puisque le port est ouvert en mode ligne, un caractère de fin de ligne est émis aprés la chaîne "user carl" insérée.

La réponse du serveur POP peut être lue avec :


print first pop
<span class="output">+OK Password required for carl.</span>

Et le reste de la communication devrait s'effectuer :


insert pop "pass secret"

print first pop
<span class="output">+OK carl has 0 messages (0 octets).</span>
insert pop "quit"

first pop
<span class="output">+OK Pop server at fred.example.com signing off.</span>

La connexion doit enfin être fermée :


close pop

Création de serveurs

Pour créer un serveur, vous devrez attendre des demandes de connexions et y répondre lorsqu'elles se produisent. Pour définir un port sur votre machine qui peut utilisé pour attendre les connexions entrantes :


listen: open tcp://:8001

Remarquez que vous n'indiquez pas de nom de machine, seulement un numéro de port. Ce type de port est appelé un port d'écoute (listen port). Votre système accepte maintenant les connexions sur le port numéro 8001.

Pour attendre une connexion d'une autre machine, vous attendez sur le port d'écoute.


wait listen

Cette fonction ne se terminera pas tant qu'une connexion n'aura pas été réalisée.

NOTE : Il existe diverses options possibles pour wait. Par exemple, vous pouvez attendre sur plusieurs ports ou aussi avec un time-out.

Vous pouvez maintenant ouvrir le port pour la connexion depuis la machine qui a contacté votre système.


connexion: first listen

Ceci renvoie la connexion qui a été faite sur le port d'écoute. C'est un port comme tous les autres, et il peut être utilisé pour émettre et recevoir des données, au moyen des fonctions insert, copy, first, et des autres fonctions relatives aux séries.


insert connexion "you are connected^^/"

while [newline <> char: first connexion] [
print char
]

Lorsque la communication est complète, la connexion doit être fermée.


close connexion

Vous êtes à présent prêt pour la connexion suivante sur le port d'écoute. Vous pouvez attendre encore et utiliser first encore pour la nouvelle connexion.

Lorsque votre serveur en a fini, vous devez fermer le port d'écoute avec :


close listen

Un tout petit serveur

Voici un serveur REBOL assez commode qui nécessite seulement que quelques lignes de code. Ce serveur évalue le code REBOL qui lui est envoyé. Les lignes de REBOL en provenance d'un client sont lues jusqu'à ce qu'une erreur se produise. Chaque ligne doit être une expression REBOL compléte. Elle peut être de n'importe quelle longueur mais doit faire une seule ligne.


server-port: open/lines tcp://:4321

forever [
connexion-port: first server-port
until [
wait connexion-port
error? try [do first connexion-port]
]
close connexion-port
]
close server-port

Si une erreur se produit, la connexion est fermée et le serveur se met en attente de la connexion suivante.

Voici un exemple de script pour un client qui vous permet de rentrer à distance des commandes REBOL :


server: open/lines tcp://localhost:4321
until [error? try [insert server ask "R> "]]
close server

Ici la requête est faite pour déterminer si la connexion a été interrompue du fait d'une erreur.

Test du code TCP

Pour tester le code de votre serveur, connectez-vous depuis votre propre machine, plutôt que d'avoir un serveur et un client. Ceci peut être fait avec deux processus REBOL distincts ou même un seul processus.

Pour vous connecter en local sur votre machine, vous pouvez utilisez une ligne comme celle-ci :


port: open tcp://localhost:8001

Voici un exemple qui crée deux ports connectés entre eux en mode ligne. Il s'agit d'une sorte de port "echo" puisque vous émettez des datas vers vous-mêmes. C'est un bon test pour votre code et l'usage du réseau :


listen: open/lines tcp://:8001
remote: open/lines tcp://localhost:8001
local: first listen
insert local "How are you?"
print first remote ; response
close local
close remote
close listen

UDP - User Datagram Protocol

Le protocole UDP (User Datagram Protocol) est un autre protocole de transport qui fournit une méthode pour communiquer entre machines, mais qui n'est pas orienté connexion, à la différence de TCP.

Il permet d'envoyer des datagrammes, des paquets de données entre des machines. L'utilisation d'UDP est assez différente de celle de TCP. Le protocole UDP est plus simple, mais il est aussi moins sûr. Il n'y a pas de garantie qu'un paquet atteigne toujours sa destination. De plus, UDP ne dispose pas de mécanisme de contrôle de flux. Si vous envoyez des messages trop rapidement, des paquets peuvent être perdus.

Comme pour TCP, la fonction wait peut être utilisée pour attendre qu'un nouveau paquet arrive et la fonction copy peut être utilisée pour renvoyer les données. S'il n'y a pas de données, copy attend jusqu'à ce qu'il y en ait. Notez cependant que la fonction insert n'attend jamais.

Voici un exemple de script pour un petit serveur UDP :


udp: open udp://:9999
wait udp
print copy udp
insert udp "response"
close udp

Les messages insérés dans le port udp ici par le serveur sont expédiés vers le client de qui a été reçu le dernier message. Ceci permet aux réponses d'être émises pour les messages entrants. Cependant, contrairement à TCP, vous n'avez pas de connexion continue entre les machines. Chaque transfert de paquet donne lieu à un échange spécifique.

Le script client pour communiquer avec le serveur ci-dessus pourrait être :


udp: open udp://localhost:9999
insert udp "Test"
wait udp
print copy udp
close udp

Vous devez aussi savoir que la taille maximale d'un paquet UDP dépend du système d'exploitation. 32 Ko et 64 Ko représentent des valeurs courantes. Afin d'envoyer de grandes quantités de données, vous devrez mettre en buffer les datas, et les diviser en paquets plus petits. Par ailleurs, votre programmation doit être particulièrement soignée pour être certain que chaque partie des données est bien reçue. Rappelez-vous qu'avec UDP, il n'y a pas de garantie.

Manuel de l'utilisateur - Chapitre 12 - Fichiers

Historique de la traduction

Date Version Commentaires Auteur Email
27 juin 2005 19:33 1.0.0 Traduction initiale Philippe Le Goff lp—legoff—free—fr

Présentation

Une caractéristique importante de la puissance de REBOL est sa capacité à manipuler les fichiers et les répertoires. REBOL fournit plusieurs fonctions sur mesure permettant des opérations allant de la lecture d'un simple fichier jusqu'à l'accès direct aux fichiers et répertoires. Pour plus d'informations sur l'accès direct aux fichiers et répertoires, voir le chapitre sur les Ports.

Noms et Paths

REBOL fournit une convention de nommage des chemins et des fichiers qui se veut indépendante du type de machines.

Noms des fichiers

Dans les scripts, les noms de fichiers et les chemins sont écrits avec un signe pourcentage (%) suivi par une suite de caractères :


%examples.r
%big-image.jpg
%graphics/amiga.jpg
%/c/plug-in/video.r
%//sound/goldfinger.mp3

Le signe pourcentage (%) est nécessaire pour éviter que les noms de fichiers soient interprétés comme des mots au sein du langage.

Bien que cela ne soit pas une bonne habitude, des espaces peuvent être inclus dans les noms de fichiers en incluant le nom du fichier entre des guillemets (" ").

Les guillemets évitent que le nom du fichiers soit interprété comme une série de plusieurs mots :


%"this file.txt"
%"cool movie clip.mpg"

La convention standard Internet d'utiliser le signe pourcentage (%) et un code hexadécimal est aussi autorisée pour les noms de fichiers. Quand ceci est fait, les guillemets ne sont pas requis.

Les noms de fichiers précédents peuvent encore être écrits sous la forme :


%this%20file.txt
%cool%20movie%20clip.mpg

Notez que le suffixe standard pour les scripts REBOL est ".r". Sur les systèmes où cette convention produit un conflit avec un autre type de fichier, un suffixe ".reb" peut être utilisé à la place.

Chemins

Les chemins vers les fichiers sont décrits par un signe pourcentage (%) suivi par une séquence de noms de répertoires qui sont chacun séparés par le signe (/).


%dir/file.txt
%/file.txt
%dir/
%/dir/
%/dir/subdir/
%../dir/file.txt

Le caractère standard pour séparer les répertoires est le caractère slash (/), pas le backslash (\). Si des caractères "backslash" sont trouvés, ils sont convertis en caractères "slash" :


probe %\some\cool\movie.mpg
%/some/cool/movie.mpg

REBOL fournit une méthode standard, indépendante du système d'exploitation pour spécifier les chemins vers les répertoires. Les chemins peuvent être relatifs au répertoire courant ou absolus à partir du plus haut niveau de l'arborescence du système d'exploitation.

Les chemins vers les fichiers qui ne commencent pas par un symbole slash (/) sont des chemins relatifs.


%docs/intro.txt
%docs/new/notes.txt
%"new mail/inbox.mbx"

La convention standard qui utilise deux points successifs (..) pour indiquer un répertoire parent ou un point unique (.) pour faire référence au répertoire courant est aussi supportée. Par exemple :


%.
%./
%./file.txt
%..
%../
%../script.r
%../../plans/schedule.r

Les chemins vers les fichiers utilisent la convention Internet qui fait commencer un chemin absolu avec un slash (/). Le slash indique le point de départ depuis le plus haut niveau de l'arborescence du système. (Généralement, les chemins absolus devraient être évités pour rendre les scripts indépendants du contexte de la machine.

L'exemple :


%/home/file.txt

devrait référer à un volume disque ou une partition nommée "home".

Voici d'autres exemples :


%/ram/temp/test.r
%/cd0/scripts/test/files.r

Pour faire référence à un disque C comme cela est souvent le cas pour Windows, la notation est :


%/C/docs/file.txt
%"/c/program files/qualcomm/eudora mail/out.mbx"

Notez que dans les lignes précédentes, le disque C n'est pas écrit avec :


%c:/docs/file.txt

L'exemple précédent n'est pas indépendant du format utilisé pour la machine et provoque une erreur.

Si le premier nom de répertoire est absent, et que le chemin commence avec deux slashs consécutifs, (//), alors le chemin du fichier est relatif au volume courant :


%//docs/notes

Sensibilité à la casse

Par défaut, en REBOL, les noms de fichiers ne sont pas sensibles à la casse des caractères. Malgré tout, lorsque de nouveaux fichiers sont créés via le langage, leurs noms conservent la casse avec lesquels ils sont créés :


write %Script-File.r file-data

L'exemple précédent crée un nom de fichier avec un S et un F majuscules.

De plus, lorsque des noms de fichiers sont issus de répertoires, leur casse est conservée :


print read %/home

Pour les systèmes sensibles à la casse, comme UNIX, REBOL trouve la correspondance la plus proche pour le nom de fichier.

Par exemple, si un script demande à lire %test.r, mais trouve seulement %TEST.r, ce fichier %TEST.r sera lu. Ce comportement est nécessaire pour permettre de conserver des scripts indépendants du contexte machine.

Fonctions de noms de fichiers

Diverses fonctions sont fournies pour vous aider à créer des noms de fichiers et des chemins (paths). Elles sont listées ci-dessous :

to-file : Convertit des chaînes de caractères et des blocs en noms de fichiers ou en chemin vers un fichier.

split-path : Scinde un chemin en deux parties : celle relative au répertoire et celle relative au nom de fichier .

clean-path : Renvoie un chemin absolu qui est équivalent à n'importe quel chemin fourni contenant (..) ou (.).

what-dir : Renvoie le chemin absolu du répertoire courant.

Lecture des fichiers

Les fichiers sont lus comme des séries de caractères (mode texte) ou d'octets (mode binaire). La source pour le fichier est soit un fichier local sur votre système, ou un fichier à partir du réseau.

Lecture de fichiers texte

Pour lire un fichier texte local, utilisez la fonction read :


text: read %file.txt

La fonction read renvoie une chaîne qui contient le texte entier du fichier. Dans l'exemple ci-dessus, la variable text fait référence à cette chaîne.

Au sein de cette chaîne renvoyée par read, les fins de lignes sont convertis en caractères newline, indifféremment du genre de fin de ligne qu'utilise votre système d'exploitation. Ceci permet d'écrire des scripts qui recherche des sauts de lignes, sans se soucier des caractères particuliers qui constitue une fin de ligne.


next-line: next find text newline

Un fichier peut aussi être lu en séparant les lignes, qui sont stockées dans un bloc :


lines: read/lines %file.txt

Voir le paragraphe "Conversion de Lignes" pour plus d'informations concernant newline et la lecture ligne par ligne.

Pour lire un fichier par morceaux, utilisez la fonction open qui est décrite dans le chapitre sur les Ports.

Pour voir le contenu d'un fichier texte, vous pouvez le lire en utilisant read et l'afficher en utilisant print :


print read %service.txt
<span class="output">I wanted the gold, and I sought it,I scrabbled and mucked like
a slave.</span>

Lecture de fichiers binaire

Pour lire un fichier binaire comme une image, un programme ou un son, utilisez read/binary :


data: read/binary %file.bin

La fonction read/binary renvoie une série binaire qui comprend le contenu entier du fichier. Dans l'exemple ci-dessus, la variable data fait référence à la série binaire. Aucune conversion d'aucun type n'est réalisée pour ce fichier.

Pour lire un fichier binaire par morceaux, utilisez la fonction open comme décrite dans le chapitre sur les Ports .

Lecture au travers du réseau

Les fichiers peuvent être lus à partir du réseau. Par exemple, pour voir un fichier texte à partir du réseau en utilisant le protocole HTTP :


print read http://www.rebol.com/test.txt
<span class="output">Hellotherenewuser!</span>

Le fichier peut être écrit localement en une ligne de code :


write %test.txt read http:/www.rebol.com/test.txt

Dans le processus d'écriture, le fichier aura ses terminaisons de ligne converties en ce qui est utilisé pour cela sur votre système d'exploitation.

Pour lire et sauver un fichier binaire, comme une image, utilisez la ligne suivante :


write %image.jpg read/binary http:/www.rebol.com/image.jpg

Voyez le chapitre sur les protocoles Réseau pour plus d'information et d'exemples sur les moyens d'accéder à des fichiers au travers le réseau.

Ecriture de fichiers

Vous pouvez écrire un fichier de caractères (texte) ou d'octets (binaire). L'emplacement du fichier peut soit être local sur votre système, soit sur le réseau.

Ecriture de fichiers texte

Pour écrire un fichier texte localement, utilisez la ligne de code suivante :


write %file.txt "sample text here"

Celle-ci écrit le texte entier dans le fichier. Si un fichier contient des caractères newline, ils seront convertis en ceux que votre système d'exploitation utilise. Ceci permet de manipuler les fichiers d'une manière homogène, mais de les écrire en utilisant la convention en vigueur sur votre système.

Par exemple, la ligne de code suivante transforme n'importe quel texte ayant un style de terminaison de ligne (UNIX, Macintosh, PC, Amiga) en celui utilisé localement par votre système :


write %newfile.txt read %file.txt

La ligne précédente lit le fichier en convertissant les fins de ligne vers le standard REBOL, puis à l'écriture du fichier, en convertissant celui-ci au format propre au système d'exploitation local.

Pour ajouter quelque chose à la fin d'un fichier, utilisez le raffinement /append :


write/append %file.txt "encore du texte"

Un fichier peut aussi être écrit à partir de lignes distinctes stockées dans un bloc.


write/lines %file.txt lines

Pour écrire un fichier texte morceaux par morceaux, utilisez la fonction open décrite dans le chapitre sur les Ports.

Ecriture de fichiers binaires

Pour écrire des fichiers binaires comme une image, un programme, un son, utilisez write/binary :


write/binary %file.bin data

La fonction write/binary crée le fichier si celui-ci n'existe pas ou l'écrase s'il existe. Aucune conversion n'est réalisée pour le fichier.

Pour écrire un fichier binaire morceaux par morceaux, utilisez la fonction open décrite dans le chapitre sur les Ports.

Ecriture de fichiers sur le réseau

Les fichiers peuvent aussi être écrits sur le réseau. Par exemple, pour écrire un fichier texte en utilisant le protocole FTP, utilisez :


write ftp://ftp.domain.com/file.txt "save this text"

Le fichier peut être lu localement et écrit sur un emplacement en réseau via une ligne comme celle-ci


write ftp://ftp.domain.com/file.txt read %file.txt

Dans le processus, le fichier a ses fins de lignes convertis au format standard CRLF. Pour écrire un fichier binaire comme une image, via le réseau, utilisez le code suivant :


write/binary ftp://ftp.domain.com/file.txt/image.jpg read/binary %image.jpg

Voyez le chapitre sur les protocoles Réseau pour plus d'information et d'exemples sur les moyens d'accéder à des fichiers via le réseau.

Conversion de Ligne

Quand un fichier est lu en tant que texte, toutes les fins de lignes sont converties en caractères newline (line feed). Les caractères LF (utilisés comme caractères de fin de lignes pour Amiga, Linux, et les systèmes UNIX), les retours chariots CR (utilisés sur Macintosh) ou la combinaison CR/LF (PC et Internet) sont tous transformés en leurs équivalents newline.

L'usage d'un caractère standard au sein d'un script permet de le faire marcher indépendamment du contexte machine. Par exemple, pour chercher et compter tous les caractères newline à l'intérieur d'un fichier texte :


text: read %file.txt
count: 0
while [spot: find text newline][
count: count + 1
text: next spot
]

La conversion de ligne est aussi pratique pour la lecture de fichiers distants :


text: read ftp://ftp.rebol.com/test.txt

Quand un fichier est écrit, le caractère newline est converti dans le type de fin de ligne pour le système d'exploitation cible. Par exemple, le caractère newline est transformé en CRLF pour les PCs, LF sur UNIX ou AMIGA, ou CR pour un Macintosh. Les fichiers sur le réseau sont écrits avec CRLF.

La fonction suivante transforme n'importe quel texte, quel que soit le style de fin de ligne en celui qu'utilise le système d'exploitation local :


convert-lines: func [file] [write file read file]

Le fichier est lu et tous les caractères de fin de ligne sont transformés en caractère newline, puis le fichier est écrit et les caractères newline sont convertis dans le type nécessaire pour le système d'exploitation local.

La conversion de ligne peut être désactivée en lisant le fichier texte en mode binaire.

Par exemple, la ligne suivante :


write/binary %newfile.txt read/binary %oldfile.txt

préserve les fins de lignes du fichier texte original (%oldfile.txt).

Blocs de Lignes

Les fichiers textes peuvent facilement être atteints et gérés sous forme de lignes individuelles, plutôt que comme une seule série de caractères. Par exemple, pour lire un fichier sous la forme d'un bloc de lignes :


lines: read/lines %service.txt

L'exemple précédent renvoie un bloc contenant une série (au sens REBOL) de chaînes de caractères (une pour chaque ligne), sans caractères de fin de ligne. Les lignes vierges sont représentées par des chaînes vides.

Pour afficher une ligne spécifique, vous pouvez utiliser le code suivant :


print first lines
print last lines
print pick lines 100
print lines/500

Pour afficher toutes les lignes d'un fichier, utilisez l'exemple de code suivant.


foreach line lines [print line]
<span class="output">I wanted the gold, and I sought it,
I scrabbled and mucked like a slave.
Was it famine or scurvy -- I fought it;
I hurled my youth into a grave.
I wanted the gold, and I got it --
Came out with a fortune last fall, --
Yet somehow life's not what I thought it,
And somehow the gold isn't all.</span>

Pour afficher toutes les lignes qui contiennent la chaîne "gold", utilisez la ligne de code suivante :


foreach line lines [
if find line "gold" [print line]
]
<span class="output">I wanted the gold, and I sought it,
I wanted the gold, and I got it --
And somehow the gold isn't all.</span>

Vous pouvez écrire un fichier texte ligne par ligne en utilisant la fonction write avec le raffinement /lines :


write/lines %output.txt lines

Pour écrire un fichier à partir de lignes spécifiques d'un bloc, utilisez :


write/lines %output.txt [
"line one"
"line two"
"line three"
]

En fait, les fonctions read/lines et write/lines peuvent être combinées pour traiter des fichiers ligne par ligne. Par exemple, le code suivant efface tous les commentaires d'un script REBOL :


script: read/lines %script.r
foreach line script [
where: find line ";"
if where [clear where]
]
write/lines %script1.r script

Le bout de script précédent est indiqué à des fins de démonstration. En effet, en plus d'effacer les commentaires, le code effacerait aussi les points virgules valides présents dans les chaînes de caractères entre apostrophes.

Les fichiers peuvent également être lus ligne par ligne depuis le réseau :


data: read/lines http://www.rebol.com

print pick (read/lines ftp://ftp.rebol.com/test.txt) 3

new

Le raffinement /lines peut aussi être utilisé avec la fonction open pour lire une ligne à la fois à partir d'une saisie à la console. Voir le chapitre sur les Ports pour plus d'information.

De surcroît, /lines peut servir, avec le raffinement /append, à ajouter des lignes à un fichier, depuis un bloc.

Information sur les fichiers et les répertoires

Il existe de nombreuses fonctions permettant d'avoir des informations utiles sur un fichier comme : s'il existe, sa taille en octets, lorsqu'il a été modifié, ou s'il s'agit d'un répertoire.

Contrôle de Répertoire

Pour déterminer si un nom de fichier est celui d'un répertoire, utilisez la fonction dir ?.


print dir? %file.txt
<span class="output">false</span>
print dir? %.
<span class="output">true</span>

La fonction dir ? fonctionne également avec la plupart des protocoles réseau :


print dir? ftp://www.rebol.com/pub/
<span class="output">true</span>

Existence de fichier

Pour déterminer si un fichier existe, utilisez la fonction exists ? :


print exists? %file.txt

Pour savoir si un fichier existe avant d'essayer de le lire :


if exists? file [text: read file]

Pour éviter d'écraser un fichier, vous pouvez contrôler sa présence :


if not exists? file [write file data]

La fonction exists ? fonctionne aussi avec la plupart des protocoles réseau :


print exists? ftp://www.rebol.com/file.txt

Taille de fichier

Pour obtenir la taille en octets d'un fichier, utilisez la fonction size ? :


print size? %file.txt

La fonction size ? est utilisable avec la plupart des protocoles réseau :


print size? ftp://www.rebol.com/file.txt

Date de modification d'un fichier

Pour obtenir la date à laquelle un fichier a été modifié, utilisez la fonction modified ? :


print modified? %file.txt
30-Jun-2000/14:41:55-7:00

Tous les systèmes d'exploitation ne conservent pas la date de création d'un fichier, donc pour gardez les scripts REBOL indépendants du système d'exploitation, utilisez modified ? juste lorsque la date de dernière modification est accessible.

La fonction modified ? fonctionne aussi avec la plupart des protocoles réseaux :


print modified? ftp://www.rebol.com/file.txt

Information relative à un fichier

La fonction info ? récupère toutes les informations sur les fichiers et les répertoires en même temps. Ces informations sont retournées sous la forme d'un objet :


probe info? %file.txt
<span class="output">make object! [
size: 306
date: 30-Jun-2000/14:41:55-7:00
type: 'file
]</span>

Pour afficher des informations concernant tous les fichiers du répertoire courant, utilisez :


foreach file read %. [
info: info? file
print [file info/size info/date info/type]
]
<span class="output">build-guide.r 22334 30-Jun-2000/14:24:43-7:00 file
code/ 11 11-Oct-1999/18:37:04-7:00 directory
data.r 41 30-Jun-2000/14:41:36-7:00 file
file.txt 306 30-Jun-2000/14:41:55-7:00 file</span>

La fonction info ? est utilisable avec beaucoup de protocoles réseau :


probe info? ftp://www.rebol.com/file.txt

Répertoires

Il y a plusieurs fonctions prêtes à l'emploi pour lire des répertoires, gérer des sous-répertoires, créer de nouveaux répertoires, renommer et effacer des fichiers.

De plus, il existe les fonctions standards, pour connaître, modifier et lister le répertoire courant.

Pour plus d'informations concernant l'accès aux répertoires, voir le chapitre relatif aux Ports.

Lire un répertoire

Les répertoires sont lus de la même manière que les fichiers. La fonction read renvoie un bloc de noms de fichiers au lieu de données texte ou binaires.

Pour connaître tous les noms de fichiers du répertoire courant, utilisez la ligne suivante de code :


read %.

L'exemple précédent lit le répertoire entier et renvoie un bloc composé des noms des fichiers.

Pour afficher les noms de tous les fichiers dans un répertoire, utilisez la ligne de code suivante :


print read %intro/
<span class="output">CVS/ history.t intro.t overview.t quick.t</span>

A l'intérieur du bloc renvoyé, les noms des répertoires sont spécifiés avec un slash final. Pour afficher chaque nom de fichier sur un ligne différente, saisissez :


foreach file read %intro/ [print file]
<span class="output">CVS/
history.t
intro.t
overview.t
quick.t</span>

Voici une manière facile d'afficher seulement les répertoires qui ont été trouvés :


foreach file read %intro/ [
if #"/" = last file [print file]
]
<span class="output">CVS/</span>

Si vous voulez lire un répertoire présent sur le réseau, n'oubliez pas d'inclure le symbole "slash" à la fin de l'URL pour indiquer au protocole que vous faites référence à un répertoire :


print read ftp://ftp.rebol.com/

Créer un répertoire

La fonction make-dir permet de créer un nouveau répertoire.

Le nom du nouveau répertoire doit être relatif au répertoire courant ou à un chemin absolu.


make-dir %new-dir
make-dir %local-dir/
make-dir %/work/docs/old-docs/

Le slash final est optionnel pour cette fonction. En interne, la fonction make-dir appelle la fonction open avec le raffinement /new.

La ligne :


close open/new %local-dir/

crée également un nouveau répertoire. Le slash final est par contre important dans cet exemple, car il indique qu'un répertoire doit être créé plutôt qu'un fichier.

Si vous utilisez la fonction make-dir pour créer un répertoire déjà existant, une erreur sera générée. L'erreur peut être capturée avec la fonction try. L'existence du répertoire doit être contrôlée auparavant avec la fonction exists ?.

Renommage des répertoires et des fichiers

Pour renommer un fichier, utilisez la fonction rename :


rename %old-file %new-file

L'ancien nom de fichier doit inclure le chemin d'accès complet au fichier, mais ceci n'est pas nécessaire pour le nouveau nom de fichier. En effet, la fonction rename n'est pas destinée à déplacer des fichiers entre différents répertoires.(Beaucoup de systèmes d'exploitation ne permettent pas cette fonctionnalité.)


rename %../docs/intro.txt %conclusion.txt

Si l'ancien nom de fichier est un répertoire (indiqué par un slash final), la fonction rename renommera le répertoire :


rename %../docs/ %manual/

Si le fichier ne peut être renommé, une erreur se produira. L'erreur peut être capturée avec la fonction try.

Effacer des répertoires et des fichiers

Les fichiers peuvent être effacés avec la fonction delete :


delete %file

Le fichier à supprimer doit avoir un chemin d'accès complet :


delete %source/docs/file.txt

Un bloc de plusieurs fichiers au sein d'un même répertoire peut aussi être supprimé en une fois :


delete [%file1 %file2 %file3]

Un ensemble de fichiers peut être supprimé en utilisant un caractère joker et le raffinement /any :


delete/any %file*
delete/any %secret.?

Le caractère joker "astérisque" (*) est équivalent à "tous les caractères", et le caractère joker "point d'interrogation" ( ?) équivaut à remplacer un unique caractère.

Pour supprimer un répertoire, mettez à son nom le slash final :


delete %dir/
delete %../docs/old/

Si le fichier ne peut être supprimé, une erreur sera générée. Il est possible de capturer cette erreur avec la fonction try.

Répertoire courant

Utilisez la fonction what-dir pour déterminer le répertoire courant :


print what-dir
/work/REBOL/

La fonction what-dir fait référence au répertoire courant relatif au script en oeuvre comme indiqué dans la variable system/script/path.

Modifier le répertoire courant

Pour modifier le répertoire courant, utilisez la fonction change-dir :


change-dir %new-path/to-dir/

Si le slash final n'est pas inclus, la fonction l'ajoute.

Listing du Répertoire courant

Pour lister le contenu du répertoire courant, utilisez :


list-dir

Le nombre de colonnes utilisées pour afficher le contenu du répertoire dépend de la taille de fenêtre de la console, et de la longueur maximale des noms de fichiers.

jeudi 22 septembre 2005

Manuel de l'utilisateur - Chapitre 11 - Maths

Historique de la traduction

Date Version Commentaires Auteur Email
1er juin 2005 19:33 1.0.0 Traduction initiale Philippe Le Goff lp—legoff—free—fr

Présentation

REBOL permet d'assurer un ensemble complet d'opérations mathématiques et trigonométriques. La plupart de ces opérateurs peuvent manipuler plusieurs types de données, comme les nombres entiers et décimaux, les tuples, des valeurs de type temps et date. Certains de ces types de données peuvent même être mélangés ou forcés.

Types de données scalaires

Les fonctions mathématiques de REBOL agissent de façon régulière sur une grande variété de types de données scalaires (numériques).

Ces types de données incluent :

| Type de données | Description | | Integer ! | nombres sur 32 bits sans décimales | | Decimal ! | nombres sur 64 bits avec décimales | | Money ! | valeurs monétaires sur 64 bits avec décimales | | Time ! | heures, minutes, secondes, dixièmes jusqu'au millième de secondes | | Date ! | jour, mois, année, heure, fuseau horaire | | Pair ! | coordonnées graphiques ou taille | | Tuple ! | versions, couleurs, adresses réseau |

Voici ci-dessous quelques exemples pour illustrer un certain nombre d'opération sur les types de donnée scalaires. Notez que les opérateurs renvoient les résultats adéquats pour chaque type de données.

Les types de données integer ! et decimal ! :


print 2 + 1
3
print 2 - 1
1
print 2 * 10
20
print 20 / 10
2
print 21 // 10
1
print 2.2 + 1
3.2
print 2.2 - 1
1.2
print 2.2 * 10
22
print 2.2 / 10
0.22
print random 10
5

Le type de données time ! :


print 2:20 + 1:40
4:00
print 2:20 + 5
2:20:05
print 2:20 + 60
2:21
print 2:20 + 2.2
2:20:02.2
print 2:20 - 1:20
1:00
print 2:20 - 5
2:19:55
print 2:20 - 120
2:18
print 2:20 * 2
4:40
print 2:20 / 2
1:10
print 2:20:01 / 2
1:10:00.5
print 2:21 // 2
0:00
print - 2:20
-2:20
print random 10:00
5:30:52

Le type de données date ! :


print 1-Jan-2000 + 1
2-Jan-2000
print 1-Jan-2000 - 1
31-Dec-1999
print 1-Jan-2000 + 31
1-Feb-2000
print 1-Jan-2000 + 366
1-Jan-2001
birthday: 7-Dec-1944
print ["I've lived" (now/date - birthday) "days."]
I've lived 20305 days.
print random 1-1-2000
29-Apr-1695

Le type de données money ! :


print $2.20 + $1
$3.20
print $2.20 + 1
$3.20
print $2.20 + 1.1
$3.30
print $2.20 - $1
$1.20
print $2.20 * 3
$6.60
print $2.20 / 2
$1.10
print $2.20 / $1.10
2
print $2.21 // 2
$0.21
print random $10.00
$6.00

Le type de données pair ! :


print 100x200 + 10x20
110x220
print 10x10 + 3
13x13
print 10x20 * 2x4
20x80
print 100x100 * 3
300x300
print 100x30 / 10x3
10x10
print 100x30 / 10
10x3
print 101x32 // 10x3
1x2
print 101x32 // 10
1x2
print random 100x20
67x12

Le type de données tuple ! :


print 1.2.3 + 3.2.1
4.4.4
print 1.2.3 - 1.0.1
0.2.2
print 1.2.3 * 3
3.6.9
print 10.20.30 / 10
1.2.3
print 11.22.33 // 10
1.2.3
print 1.2.3 * 1.2.3
1.4.9
print 10.20.30 / 10.20.30
1.1.1
print 1.2.3 + 7
8.9.10
print 1.2.3 - 1
0.1.2
print random 10.20.30
8.18.12

Ordre de l'évaluation

Il y a deux règles à se rappeler pour l'évaluation d'expressions mathématiques :

Les expressions sont évaluées de gauche à droite.
Les opérateurs ont priorité sur les fonctions

L'évaluation des expressions de gauche à droite est indépendante du type d'opérateur utilisé. Par exemple :


print 1 + 2 * 3
9

Dans l'exemple ci-dessus, notez que le résultat n'est pas sept, comme cela le serait si la multiplication avait priorité sur l'addition.

Remarque importante

Le fait que les expressions mathématiques soient évaluées de la gauche vers la droite sans se soucier des opérateurs donne un comportement différent de la plupart des autres langages de programmation. Beaucoup de langages possèdent des règles de priorité où vous devez vous rappeler ce qui détermine l'ordre dans lequel les opérateurs seront évalués. Par exemple, une multiplication est faite avant une addition. Certains langages possèdent plus d'une dizaine de règles de ce genre.

En REBOL, plutôt que d'imposer à l'utilisateur de se remémorer les priorités des opérateurs, vous avez seulement à vous rappeler la règle "de-gauche-à-droite".

Encore plus important, pour un code poussé, perfectionné, comme des expressions qui manipulent d'autres expressions (de la réflectivité, par exemple), vous n'avez pas besoin de réordonner les termes sur la base d'une priorité. L'ordre d'évaluation demeure simple.

Pour la plupart des expressions mathématiques, l'évaluation de gauche à droite fonctionne assez bien et est simple à se rappeler. D'un autre côté, comme cette règle est différente d'autres langages de programmation, elle peut être la cause d'erreurs de programmation, donc soyez vigilants.

La meilleure solution est de vérifier votre travail. Vous pouvez aussi utiliser des parenthèses si nécessaire, afin de clarifier vos expressions (voir ci-dessous), et vous pouvez toujours saisir votre expression dans la console, pour vérifier le résultat.

S'il est nécessaire d'évaluer une expression dans un autre ordre, réordonnez-la ou utilisez des parenthèses :


print 2 * 3 + 1
7
print 1 + (2 * 3)
7

Quand des fonctions sont mélangées avec des opérateurs, les opérateurs sont évalués en premier, puis les fonctions :


print absolute -10 + 5
5

Dans l'exemple ci-dessus, l'addition est d'abord réalisée, et son résultat passé à la fonction "valeur absolue".

Dans l'exemple suivant :


print 10 + sine 30 + 60
11

l'expression est évaluée dans cet ordre :


30 + 60 => 90
sine 90 => 1
10 + 1 => 11
print

Pour changer l'ordre afin que le sinus de 30 soit calculé en premier, utilisez des parenthèses :


print 10 + (sine 30) + 60
70.5

ou réorganisez l'expression :


print 10 + 60 + sine 30
70.5

Fonctions et Opérateur standards

Cette section décrit les fonctions et opérateurs mathématiques standards utilisés en REBOL.

absolute

Les expressions :


absolute value

abs value

renvoient la valeur absolue de l'argument value. Les types de données possibles sont : integer, decimal, money, time, pair.


print absolute -10
10
print absolute -1.2
1.2
print absolute -$1.2
$1.20
print absolute -10:20
10:20
print absolute -10x-20
10x20

add

Les expressions :


value1 + value2

add value1 value2

renvoient la somme des valeurs value1 et value2. S'utilise avec les types de données integer, decimal, money, time, tuple, pair, date, char.


print 1 + 2
3
print 1.2 + 3.4
4.6
print 1.2.3 + 3.4.5
4.6.8
print $1 + $2
$3.00
print 1:20 + 3:40
5:00
print 10x20 + 30x40
40x60
print #"A" + 10
K
print add 1 2
3

NdT : remarquez que l'expression


+ 1 2
3

est aussi valable, quoique moins "naturelle". Il en est ainsi avec plusieurs opérateurs.

complement

L'expression :


complement value

renvoie le complément numérique (bitwise complement) d'une valeur. Pour types de données integer, decimal, tuple, logic, char, binary, string, bitset, image.


print complement 10
-11
print complement 10.5
-11
print complement 100.100.100
155.155.155

Ndt : il est possible d'utiliser complement sur des caractères :


complement "I"
"¶" (le symbole de saut de ligne de Ms-Word)
complement "V"
"©" (le symbole Copyright)

divide

Les expressions :


value1 / value2

divide value1 value2

retournent le résultat de la division de value1 par value2. S'utilise sur les types de données integer, decimal, money, time, tuple, pair, char .


print 10 / 2
5
print 1.2 / 3
0.4
print 11.22.33 / 10
1.2.3
print $12.34 / 2
$6.17
print 1:20 / 2
0:40
print 10x20 / 2
5x10
print divide 10 2
5

NdT : l'expression


/ 1 2
0.5

marche également.

multiply

Les expressions :


value1 * value2

multiply value1 value2

renvoient le résultat de la multiplication de value1 par value2. Fonctionne avec les datatypes integer, decimal, money, time, tuple, pair, char.


print 10 * 2
20
print 1.2 * 3.4
4.08
print 1.2.3 * 3.4.5
3.8.15
print $10 * 2
$20.00
print 1:20 * 3
4:00
print 10x20 * 3
30x60
print multiply 10 2
20

Ndt : l'expression


* $10 2
$20.00

est également valable.

negate

Les expressions :


- value

negate value

changent le signe de la valeur. Les types de données possibles sont : integer, decimal, money, time, pair, char.


print - 10
-10
print - 1.2
-1.2
print - $10
-$10.00
print - 1:20
-1:20
print - 10x20
-10x-20
print negate 10
-10

random

L'expression :


random value

renvoie une valeur aléatoire qui est inférieure ou égale à la valeur de l'argument.

Notez que pour les nombres entiers, random commence à 1, pas à 0, et va inclure la valeur de l'argument fourni. Ceci permet à random d'être utilisé directement dans des fonctions comme pick.

Quand un nombre décimal est utilisé, le résultat est du type décimal, arrondi à un entier.

Le raffinement /seed réinitialise le générateur de nombres aléatoires. Utilisez d'abord le raffinement /seed avec random si vous voulez générer un nombre unique aléatoire. Vous pouvez utiliser la date et l'heure courante pour fabriquer une base unique :


random/seed now

S'utilise avec les types de données integer, decimal, money, time, tuple, pair, date, char, string, et block.


print random 10
5
print random 10.5
2
print random 100.100.100
79.95.66
print random $100
$32.00
print random 10:30
6:37:33
print random 10x20
2x4
print random 30-Jun-2000
27-Dec-1171

remainder

Les expressions :


value1 // value2

remainder value1 value2

renvoient le reste de la division de value1 par value2. Fonctionne avec les datatypes integer, decimal, money, time, tuple, pair .


print 11 // 2
1
print 11.22.33 // 10
1.2.3
print 11x22 // 2
1x0
print remainder 11 2
1

subtract

Les expressions :


value1 - value2

subtract value1 value2

renvoient le résultat de la soustraction entre value2 et value1. S'utilise avec les types de données integer, decimal, money, time, tuple, pair, date, char.


print 2 - 1
1
print 3.4 - 1.2
2.2
print 3.4.5 - 1.2.3
2.2.2
print $2 - $1
$1.00
print 3:40 - 1:20
2:20
print 30x40 - 10x20
20x20
print #"Z" - 1
Y
print subtract 2 1
1

Conversion de type

Lorsque des opérations mathématiques sont réalisées entre des types de données différents, normalement, le type de données non entier ou non décimal est retourné. Quand des entiers sont combinés avec des nombres décimaux, c'est le datatype décimal qui est retourné.

Fonctions de comparaison

Toutes les fonctions de comparaison renvoient une valeur logique : true ou false.

equal

Les expressions :


value1 = value2

equal? value1 value2

renvoient true si la première et la seconde valeur sont égales. Fonctionne avec les types de données : integer, decimal, money, time, date, tuple, char et series.


print 11-11-99 = 11-11-99
true
print equal? 111.112.111.111 111.112.111.111
true
print #"B" = #"B"
true
print equal? "a b c d" "A B C D"
true

greater

Les expressions :


value1 > value2

greater? value1 value2

retournent true si la première valeur est supérieure à la seconde valeur. S'utilise avec les types de données integer, decimal, money, time, date, tuple, char et series.


print 13-11-99 > 12-11-99
true
print greater? 113.111.111.111 111.112.111.111
true
print #"C" > #"B"
true
print greater? [12 23 34] [12 23 33]
true

greater-or-equal

Les expressions :


value1 >= value2

greater-or-equal? value1 value2

retournent true si la première valeur est supérieure ou égale à la seconde valeur. S'utilise avec les types de données integer, decimal, money, time, date, tuple, char et series.


print 11-12-99 >= 11-11-99
true
print greater-or-equal? 111.112.111.111 111.111.111.111
true
print #"B" >= #"A"
true
print greater-or-equal? [b c d e] [a b c d]
true

lesser

Les expressions :


value1 < value2

lesser? value1 value2

retournent true si la première valeur est inférieure à la seconde valeur. S'utilise avec les types de données integer, decimal, money, time, date, tuple, char et series.


print 25 <; 50
true
print lesser? 25.3 25.5
true
print $2.00 < $2.30
true
print lesser? 00:10:11 00:11:11
true

lesser-or-equal

Les expressions :


value1 <= value2

lesser-or-equal? value1 value2

retournent true si la première valeur est inférieure ou égale à la seconde valeur. S'utilise avec les types de données integer, decimal, money, time, date, tuple, char et series.


print 25 <= 25
true
print lesser-or-equal? 25.3 25.5
true
print $2.29 <= $2.30
true
print lesser-or-equal? 11:11:10 11:11:11
true

not equal to

Les expressions :


value1 <> value2

not-equal? value1 value2

retournent true si la première valeur n'est pas égale à la seconde valeur. S'utilise avec les types de données integer, decimal, money, time, date, tuple, char et series.


print 26 v 25
true
print not-equal? 25.3 25.5
true
print $2.29 <> $2.30
true
print not-equal? 11:11:10 11:11:11
true

same

Les expressions :


value1 =? value2

same? value1 value2

renvoient true si les deux mots font référence à la même valeur. Par exemple, lorsque vous voulez savoir si deux mots font référence à la même valeur d'index dans une série. Fonctionne avec tous les types de données.


reference-one: "abcdef"
reference-two: reference-one
print same? reference-one reference-two
true
reference-one: next reference-one
print same? reference-one reference-two
false
reference-two: next reference-two
print same? reference-one reference-two
true
reference-two: copy reference-one
print same? reference-one reference-two
false

strict-equal

Les expressions :


value1 == value2

strict-equal? value1 value2

retournent true si la première et la seconde valeurs sont strictement identiques. Strict-equal peut être utilisée comme la version sensible à la casse de equal ? ( = ) pour les chaînes de caractères et pour différencier les entiers des décimaux lorsque les valeurs sont identiques. Fonctionne avec tous les types de données.


print strict-equal? "abc" "ABC"
false
print equal? "abc" "ABC"
true
print strict-equal? "abc" "abc"
true
print strict-equal? 1 1.0
false
print equal? 1 1.0
true
print strict-equal? 1.0 1.0
true

strict-not-equal

L'expression :


strict-not-equal? value1 value2

renvoie true si la première et la seconde valeurs ne sont pas strictement égales. strict-not-equal peut être utilisée comme la version sensible à la casse de not-equal ? ( <> ) pour les chaînes de caractères et pour différencier les entiers des décimaux lorsque leurs valeurs sont identiques. Fonctionne avec tous les types de données.


print strict-not-equal? "abc" "ABC"
true
print not-equal? "abc" "ABC"
false
print strict-not-equal? "abc" "abc"
false
print strict-not-equal? 1 1.0
true
print not-equal? 1 1.0
false
print strict-not-equal? 1.0 1.0
false

Fonctions Logarithmiques

exp

L'expression :


exp value

calcule E (nombre naturel) à la puissance de l'argument.

log-10

L'expression :


log-10 value

renvoie le logarithme de base 10 de l'argument.

log-2

L'expression :


log-2 value

renvoie le logarithme de base 2 de l'argument.

log-e

L'expression :


log-e value

renvoie le logarithme naturel (base E) de l'argument.

power

Les expressions :


value1 ** value2

power value1 value2

renvoient le résultat du calcul de value1 à la puissance value2.

square-root

L'expression :


square-root value

renvoie la racine carrée de l'argument value.

Fonctions Trigonométriques

Les fonctions trigonométriques travaillent normalement en degrés. Il faut utiliser le raffinement /radians avec l'une ou l'autre des fonctions trigonométriques pour travailler en radians.

arccosine

L'expression :


arccosine value

renvoie la fonction cosinus inverse pour l'argument.

arcsine

L'expression :


arcsine value

renvoie la fonction sinus inverse pour l'argument.

arctangent

L'expression :


arctangent value

renvoie la fonction tangente inverse pour l'argument.

cosine

L'expression :


cosine value

renvoie le cosinus de l'argument.

sine

L'expression :


sine value

renvoie le sinus de l'argument.

tangent

L'expression :


tangent value

renvoie la tangente de l'argument.

Fonctions logiques

Les fonctions logiques peuvent être effectuées sur des valeurs logiques et sur des valeurs scalaires incluant les types de données integer, char, tuple, et bitset.

Avec des valeurs logiques, les fonctions logiques renvoient des valeurs booléennes. Quand elles utilisent d'autres types de valeurs, les fonctions logiques travaillent au niveau des bits.

and

La fonction and compare deux valeurs logiques et renvoie true seulement si les deux valeurs sont elles aussi true :


print (1 < 2) and (2 < 3)
true
print (1 < 2) and (4 < 3)
false

Quand elle est utilisée avec des nombres entiers, la fonction and effectue une comparaison bit à bit, et renvoie 1 si chacun des bits est à 1, ou 0 si ni l'un ni l'autre n'est 1 :


print 3 and 5
1

or

La fonction or compare deux valeurs logiques et renvoie true si l'une ou l'autre des deux est true, ou renvoie false si les deux sont false.


print (1 < 2) or (2 < 3)
true
print (1 < 2) or (4 < 3)
true
print (3 < 2) or (4 < 3)
false

Quand elle est utilisée avec des nombres entiers, la fonction or effectue une comparaison bit à bit, et renvoie 1 si l'un des bits est 1, ou 0 si l'un et l'autre bit sont à 0 :


print 3 or 5
7

xor

La fonction xor compare deux valeurs logiques et retourne true si et seulement si l'une des valeurs est true et l'autre false.


print (1 < 2) xor (2 < 3)
false
print (1 < 2) xor (4 < 3)
true
print (3 < 2) xor (4 < 3)
false

Utilisée avec des nombres entiers, xor compare bit à bit ces nombres et renvoie 1 si et seulement si un bit est à 1 tandis que l'autre est à 0. Sinon, elle renvoie 0 :


print 3 xor 5
6

complement

La fonction complement renvoie le complément logique ou binaire d'une valeur. Elle est utilisée pour avoir l'inverse binaire de nombres entiers ou inverser un ensemble de bits (bitsets).


print complement true
false
print complement 3
-4

not

Pour une valeur logique, la fonction not renverra true si l'argument est false et false si, au contraire, l'argument est true. Elle n'effectue pas d'opérations numériques binaires.


print not true
false
print not false
true

Erreurs

Les erreurs mathématiques sont émises quand des opérations illégales sont réalisées, ou quand un débordement de calcul (overflow) se produit.

Les erreurs suivantes peuvent être rencontrées dans les opérations mathématiques.

Tentative de division par zéro

Une tentative a été faite de diviser un nombre par 0.


1 / 0
** Math Error: Attempt to divide by zero
** Where: connect-to-link
** Near: 1 / 0

Débordement de calcul

Une tentative de calcul d'un nombre trop grand pour REBOL a été faite.


1E+300 + 1E+400
** Math Error: Math or number overflow
** Where: connect-to-link
** Near: 1 / 0

Nombre positif requis

Une tentative de calcul a été faite avec un nombre négatif sur un opérateur mathématique qui accepte juste des nombres positifs.


log-10 -1
** Math Error: Positive number required
** Where: connect-to-link
** Near: log-10 -1

Impossible d'utiliser l'opérateur avec un type de données

Une tentative de calcul entre des types de données incompatibles. Le type de données du second argument dans l'opération est retourné tel quel.


10:30 + 1.2.3
** Script Error: Cannot use add on time! value
** Where: connect-to-link
** Near: 10:30 + 1.2.3

mercredi 14 septembre 2005

Manuel de l'utilisateur - Chapitre 5 - Les scripts

Historique de la traduction

Date Version Commentaires Auteur Email
20 mai 2005 - 21:31 1.0.0 Traduction initiale Philippe Le Goff lp—legoff—free—fr

Présentation générale

Le terme "script" fait référence non seulement à de simples fichiers à évaluer mais aussi à du code incorporé dans d'autres types de fichiers (comme des pages Web), ou à des morceaux de code source sauvegardés en tant que fichiers de données ou transmis comme messages.

Suffixe des scripts

Typiquement, les scripts REBOL prennent un suffixe .r à leur noms de fichiers. Cependant, cette convention n'est pas obligatoire. L'interpréteur lit les fichiers quelque soit leur suffixe et recherche dans leur contenu un en-tête (header) valide de script REBOL.

Structure

La structure d'un script est libre. L'indentation et l'usage d'espaces peuvent être utilisés pour clarifier la structure et le contenu d'un script. De plus, vous êtes encouragés à utiliser les conventions standard de style REBOL pour rendre vos scripts universellement lisibles. Voir le Guide de Style pour plus d'informations, à la fin de ce chapitre.

En-têtes

En-tête

Précédant directement le corps du script, chaque script doit posséder un en-tête qui identifie son propos, ainsi que d'autres attributs du script.

Un en-tête de script (le "header") peut contenir le nom du script, de l'auteur, la date, le numéro de version, le nom du fichier, et des informations supplémentaires.

Les fichiers de données REBOL qui ne sont pas destinés à une évaluation directe ne nécessitent pas un en-tête.

Les en-têtes sont pratiques pour plusieurs raisons.

Ils identifient un script comme étant du texte source valide pour l'interpréteur REBOL. L'interpréteur utilise l'en-tête pour afficher le titre du script, et déterminer quelles ressources et quelles versions sont nécessaires avant d'évaluer le script. Les en-têtes fournissent un moyen normalisé de communiquer le titre, le sujet, l'auteur et d'autres détails du script.

Vous pouvez souvent déterminer à partir d'un en-tête de script si celui-ci vous intéressera.

Les bibliothèques de scripts et les sites web utilisent les en-têtes pour générer automatiquement les répertoires, les catégories de scripts, et les références croisées.

Certains éditeurs de texte permettent de consulter et de mettre à jour les en-têtes de scripts, afin d'historer les informations comme l'auteur, la date, la version, et l'historique.

La forme générale d'un en-tête de script est :


REBOL [block]

Pour que l'interpréteur reconnaisse l'en-tête, le bloc doit immédiatement suivre le mot REBOL. Seuls des espaces blancs (espaces, tabulations, et lignes) sont autorisés entre le mot REBOL et le bloc.

Le bloc qui suit le mot REBOL va présenter le script. Il est souhaitable d'avoir au minimum un en-tête du type :


REBOL [
Title: "Scan Web Sites"
Date: 2-Feb-2000
File: %webscan.r
Author: "Jane Doer"
Version: 1.2.3
]

Lorsqu'un script est chargé, le bloc d'en-tête est évalué et les valeurs sont attribuées aux mots leur faisant référence. Ces valeurs sont utilisées par l'interpréteur (pour construire un objet REBOL system/script/header) et peuvent aussi être utilisées par le script lui-même.

Notez que les mots définis avec des valeurs uniques peuvent aussi être définis avec des valeurs multiples, il suffit de fournir ces valeurs dans un bloc :


REBOL [
Title: "Scan Web Sites"
Date: 12-Nov-1997
Author: ["Ema User" "Wasa Writer"]
]

Les en-têtes peuvent être plus complexes, avec des informations sur l'auteur, la license, le formatage, les versions requises, l'historique des révisions, et plus encore.

Puisque le bloc est utilisé pour construire l'objet "header" (system/script/header), il peut aussi être étendu avec de nouvelles informations.

Cela signifie qu'un en-tête de script peut être adapté selon le besoin, mais ceci devrait être fait avec précaution pour éviter les ambiguïtés ou la redondance d'informations.

Un en-tête complet pourrait ressembler à quelque chose comme cela :


REBOL [
Title: "Full REBOL Header Example"
Date: 8-Sep-1999
Name: 'Full-Header ; Pour le titre de la fenêtre

Version: 1.1.1
File: %headfull.r
Home: http://www.rebol.com/rebex/

Author: "Carl Sassenrath"
Owner: "REBOL Headquarters"
Rights: "Copyright (C) Carl Sassenrath 1999"

Needs: [2.0 ODBC]
Tabs: 4

Purpose: ^{
The purpose or general reason for the program
should go here.
^}

Note: ^{
An important comment or notes about the program
can go here.
^}

History: [
0.1.0 [5-Sep-1999 "Created this example" "Carl"]
0.1.1 [8-Sep-1999 ^{Moved the header up, changed
comment on extending the header, added
advanced user comment.^} "Carl"]
]

Language: 'English
]

Scripts avec préambules

L'écriture des scripts n'impose pas de commencer avec un en-tête. Les scripts peuvent commencer avec n'importe quel texte, ce qui leur permettrait d'être inclus dans des messages emails, des pages web, et d'autres fichiers.

Cependant, l'en-tête marque pour REBOL le début du script, et le texte qui le suit est le corps du script. Le texte qui apparait avant un en-tête est appelé le préambule ("preface") et ce texte est ignoré pendant l'évaluation.

Le texte qui apparaît avant les en-têtes est ignoré par REBOL et peut donc être utilisé pour des commentaires, des en-têtes d'email, des balises HTML, etc.


un essai de script
REBOL [
Title: "Exemple de préambule"
Date: 8-Jul-1999
]

print "Ce fichier a un préambule avant son en-tête"

Inclusion de scripts

Si un script doit être suivi par du texte sans lien avec le script lui-même, le script doit être placé entre deux crochets [ ] :


Un peu de texte avant le script.

[
REBOL [
Title: "Embedded Example"
Date: 8-Nov-1997
]
print "done"
]

Ici du texte après le script.

Seul un espace blanc est compris entre le premier crochet et le mot REBOL.

Arguments des scripts

Quand un script est évalué, il peut accéder aux informations le concernant.

Celles-ci se trouvent dans l'objet REBOL system/script. Cet objet contient les champs pour le titre du script (system/script/title), les informations mises dans l'en-tête (system/script/header), et plus encore.

Item Description
Title Le libellé décrivant le script
Header L'en-tête du script, sous la forme d'un objet. Peut être utilisé pour accéder au titre du script, au nom de l'auteur, sa version, la date, et d'autres champs.
Parent Si le script a été évalué à partir d'un autre script, cet objet donne des informations pour ce script parent.
Path La localisation (path) du fichier dans l'arborescence des fichiers, ou l'URL à partir de laquelle le script a été évalué.
Args Les arguments du script. Ils sont passés depuis la ligne de commande, ou à partir de la fonction do qui a été utilisée pour évaluer le script.

Quelques exemples illustrant l'usage de l'objet system/script :


print system/script/title

print system/script/header/date

do system/script/args

do system/script/path/script.r

Le dernier exemple évalue un script appelé script.r, se trouvant dans le même répertoire (system/script/path) que le script en cours d'évaluation.

Options de programme

Les scripts peuvent aussi accéder aux options fournies à l'interpréteur REBOL quand il a été démarré. Elles peuvent être trouvées dans l'objet system/option.

Cet objet contient les champs suivants :

Item Description
Home Le chemin vers l'interpréteur, dans l'environnement de votre système d'exploitation. Il s'agit du chemin indiqué dans la variable HOME de votre environnement, ou de la base de registre si votre système l'exploite. C'est le chemin utilisé aussi pour trouver les fichiers rebol.r et user.r.
Script Le nom du fichier de script intialement fourni quand l'interpréteur a été lancé.
Path Le chemin vers le répertoire courant.
Args Les arguments initiaux fournis à l'interpréteur en ligne de commande.
Do-arg La chaîne fournie en argument à l'option —do en ligne de commande.

L'objet system/options peut aussi contenir des options supplémentaires qui ont été fournies en ligne de commande.

Saisissez :


probe system/options

pour étudier le contenu de l'objet system/options.

Exemples :


print system/options/script

probe system/options/args

print read system/options/home/user.r

Exécution des scripts

Il y a deux manières d'exécuter un script : en tant que script initial, quand REBOL est démarré, ou à partir de la fonction do.

Pour exécuter un script au lancement de l'interpréteur, donnez le nom du script en ligne de commande juste après le nom de l'interpréteur (rebol ou rebol.exe) :


rebol script.r

Lors de l'initialisation de l'interpréteur, le script sera évalué.

A la fonction do, fournissez le nom de fichier du script en argument. Le fichier sera chargé dans l'interpréteur et évalué :


do %script.r

do http://www.rebol.com/script.r

La fonction do renvoie le résultat du script quand l'évaluation est terminée. Notez que le script doit inclure en en-tête (header) REBOL valide.

Chargement des scripts

Les scripts peuvent être chargés comme des données, avec la fonction load.

Cette fonction lit le script, et traduit le script en valeurs, mots et blocs, mais sans évaluer le script. Le résultat de la fonction load est un bloc, sauf si une seule valeur a été chargée, auquel cas cette valeur est retournée.

L'argument de la fonction load est un nom de fichier, une URL, ou une chaîne :


load %script.r
load %datafile.txt
load http://www.rebol.org/script.r
load "print now"

La fonction load réalise les étapes suivantes.

Elle
lit le texte du fichier, de l'URL, ou de la chaîne de caractères.
recherche un en-tête de script, s'il est présent.
traduit les données trouvées après l'en-tête, s'il y en a.
renvoie un bloc contenant les valeurs traduites.

Par exemple, si un script appelé buy.r contient le texte :


Buy 100 shares at $20.00 per share

il pourra être chargé avec la ligne :


data: load %buy.r

et il renverra dans un bloc :


probe data
[Buy 100 shares at $20.00 per share]

Remarquez que l'exemple "Buy" précédent est un dialecte de REBOL et non du code directement exécutable. Voir le chapitre 4 sur les Expressions pour plus d'information.

A noter aussi qu'un fichier ne nécessite pas un en-tête pour être chargé. L'en-tête est nécessaire seulement si le fichier doit être exécuté en tant que script.

La fonction load possède quelques raffinements dont voici la description :

Item Description
/header Inclue l'en-tête (header) s'il est présent
/next Charge seulement la valeur suivante, une valeur à la fois. Ceci est pratique pour parser, analyser des scripts REBOL.
/markup Traite le fichier comme un fichier HTML ou XHTML et renvoie un bloc permettant de manipuler les balises et le texte.

En principe, load ne renvoie pas l'en-tête du script. Mais, si le raffinement /header est utilisé, l'en-tête est le premier item du bloc renvoyé par load.

Le raffinement /next charge la valeur suivante et renvoie un bloc contenant deux valeurs. La première est la valeur suivante dans la série. La seconde valeur retournée est la position dans la chaîne suivant immédiatement le dernier item chargé.

Le raffinement /markup charge des données XML et HTML sous la forme d'un bloc de balises et de chaînes de caractères. Toutes les balises sont du type tag !. Les autres données sont traitées comme des chaînes de caractères.

Si le contenu du fichier suivant est chargé avec load/markup :


<title>This is an example</title>

un bloc sera créé :


probe data
[<title> "This is an example" </title>]

Sauvegarde des scripts

Des données peuvent être sauvegardées dans un fichier de script selon un format facilement récupérable sous REBOL avec la fonction load.

C'est une manière pratique de sauver des données et des blocs de données. Par ce moyen, il est possible de créer une mini base de données.

La fonction save attend deux arguments : un nom de fichier et, soit le bloc, soit la valeur à sauvegarder.


data: [Buy 100 shares at $20.00 per share]

save %data.r data

Les données data sont écrites au format texte pour REBOL, ce qui permet de les charger ultérieurement avec :


data: load %data.r

De simples valeurs peuvent aussi être sauvées et chargées. Par exemple, un horodatage peut être sauvé avec :


save %date.r now

et plus tard rechargé avec :


stamp: load %date.r

Dans l'exemple précédent, comme stamp est une valeur unique, elle n'est pas mise dans un bloc lorsqu'elle est chargée.

Pour sauvegarder un fichier script avec un en-tête, celui-ci doit être fourni en argument, à load avec le raffinement /header, soit sous la forme d'un objet ou sinon d'un bloc :


header: [Title: "This is an example"]

save/header %data.r data header

Commentaires dans les scripts

L'usage de commentaires est pratique pour clarifier l'objet de certains paragraphes de scripts. L'en-tête d'un script fournit la description générale du script et les commentaires une description plus courte des fonctions. C'est également une bonne idée de mettre également des commentaires pour d'autres parties de votre code.

Un commentaire mono-ligne est précédé d'un point-virgule ( ; ). Tout ce qui suit le point-virgule, et jusqu'à la fin de la ligne, est pris comme un commentaire :


zertplex: 10 ; set to the highest quality

Vous pouvez aussi utiliser des chaînes de caractères pour les commentaires. Par exemple, vous pouvez créer des commentaires sur plusieurs lignes avec une chaîne de caractères placée entre accolades.


^{
This is a long multilined comment.
^}

Cette façon de commenter fonctionne uniquement si la chaîne n'est pas interprétée comme un argument d'une fonction. Si vous voulez être sûr qu'un commentaire multi-lignes soit reconnu comme tel et non interprété comme du code, faites-le précéder du mot comment :


comment ^{
This is a long multilined comment.
^}

La fonction comment indique à REBOL qu'il faut ignorer le bloc ou la chaîne qui le suit. Notez que les commentaires sous forme de blocs ou de chaînes font actuellement partie du bloc global du script. Faites attention de ne pas mettre ces commentaires dans des blocs de données, car ils pourraient être évalués comme des parties de données.

Guide de Style

Les scripts REBOL n'ont pas de formalisme particulier. Vous pouvez écrire un script en utilisant l'indentation, la longueur de ligne ou les marqueurs de fin de ligne que vous voulez. Vous pouvez mettre chaque mot sur une ligne séparée ou les joindre ensemble sur une seule grande ligne.

Bien que le formatage de votre script n'affecte pas l'interpréteur, la présentation affecte, elle, la lisibilité. A cause de cela, REBOL Technologies suggère de suivre un certain style pour écrire vos scripts, qui va être décrit dans cette section.

Bien sûr, vous n'êtes pas obligés de suivre l'une ou l'autre de ses suggestions. Pourtant, le style du code est plus important qu'il ne paraît à première vue. La lisibilité et la réutilisation des scripts peuvent en être facilitées. Les utilisateurs peuvent juger la qualité de vos scripts par la clarté de votre style. Un script alambiqué va souvent de pair avec un code alambiqué. Les codeurs expérimentés trouvent d'habitude qu'un style clair et cohérent rend leur code plus facile à produire, à maintenir et à contrôler.

Formatage

Utilisez les indications de style suivantes pour clarifier la présentation de vos scripts :

Indentez le contenu pour le clarifier

Le contenu d'un bloc est indenté, mais pas les crochets [ ] encadrant le bloc. C'est parce que les crochets ont un niveau de priorité plus important pour la syntaxe, et parce qu'ils définissent le bloc mais ne sont pas le contenu du bloc. De plus, il est plus facile de se focaliser sur les ruptures entre des blocs adjacents quand les crochets sont repérables.

Lorsque cela est possible, un crochet ouvrant [ demeure sur la ligne avec l'expression qui lui est associée. Le crochet fermant ] peut être suivi de plusieurs expressions au même niveau. Des régles identiques s'appliquent pour les parenthèses ( ) et les accolades .


if check [do this and that]

if check [
do this and do that
do another thing
do a few more things
]

either check [do something short][
do something else]

either check [
when an expression extends
past the end of a block...
][
this helps keep things
straight
]

while [
do a longer expression
to see if it's true
][
the end of the last block
and start of the new one
are at the WHILE level
]

adder: func [
"This is an example function"
arg1 "this is the first arg"
arg2 "this is the second arg"
][
arg1 + arg2
]

Une exception est faite pour les expressions qui appartiennent normalement à une ligne simple, mais se prolongent sur plusieurs lignes :


if (this is a long conditional expression that
breaks over a line and is indented
)[
so this looks a bit odd
]

Ceci s'applique aussi à des valeurs qui sont normalement groupées ensemble, mais qui doivent être adaptées à la ligne.


[
"Hitachi Precision Focus" $1000 10-Jul-1999
"Computers Are Us"

"Nuform Natural Keyboard" $70 20-Jul-1999
"The Keyboard Store"
]

Taille standard pour les tabulations

La taille standard de tabulation pour REBOL est de quatre espaces. Comme les programmeurs utilisent différents éditeurs de texte pour les scripts, il est suggéré d'employer les espaces plutôt que les tabulations.

Détabuler avant de publier

Dans beaucoup de navigateurs, ou shells, ou lecteurs, le caractère de tabulation (ASCII 9) ne correspond pas à quatre espaces, donc utilisez votre éditeur ou REBOL pour ôter les tabulations d'un script avant de le publier sur le Net. La fonction suivante transforme chaque tabulation d'un fichier en un bloc de quatre espaces.


detab-file: func [file-name [file!]] [
write file-name detab read file-name
]
detab-file %script.r

La fonction suivante convertit des tabulations à huit espaces en tabulations à quatre espaces :


detab-file: func [file-name [file!]] [
write file-name detab entab/size read file-name 8
]

Limitez les longueurs de ligne à 80 caractères

Pour faciliter la lecture et la portabilité entre éditeurs de texte et clients email, limitez les lignes à 80 caractères. Les longues lignes qui sont mal formatées dans les clients email sont difficiles à lire et posent des porblèmes de chargement.

Libellés des mots

Les mots de votre code sont en premier lieu ce qui est exposé à un utilisateur, de sorte qu'il vous faut les choisir soigneusement. Un script doit être clair et concis. Lorsque c'est possible, les mots doivent être parlants. Voici les convention de nommage pour REBOL.

Utilisez les mots les plus courts ayant le sens le plus fort

Quand c'est possible, les mots directs donnent plus de sens :


size time send wait make quit

Un mot à portée locale peut souvent être réduit à un mot simple. D'un autre côté, des mots plus descriptifs sont préférables pour les mots à portée globale.

Employez des mots entiers si possible

Ce que vous conservez en abrégeant un mot est rarement le meilleur.

Saisissez date et non pas dt, ou image-file et non pas imgfl.

Mettez un trait d'union aux mots ayant des libellés complexes

Le style standard est d'utiliser un trait d'union, et non la casse des caractères, pour distinguer des mots.


group-name image-file clear-screen bake-cake

Débutez les noms de fonction par un verbe

Les noms de fonction commencent avec un verbe et sont suivis par un nom, un adverbe, et un adjectif. Certains noms peuvent aussi être utilisés comme verbes.


make print scan find show hide take
rake-coals find-age clear-screen

Eviter autant que possible les mots inutiles. Par exemple, quit est aussi clair que quit-system.

Quand un nom est utilisé comme verbe, utilisez des caractères spéciaux comme le caractère ( ? ) là où cela est possible. Par exemple, la fonction donnant la longueur d'une série est length ?.

Voici d'autres fonctions REBOL utilisant cette convention de nommage :


size? dir? time? modified?

Commencez les variables avec des noms

Les mots représentant des objets ou des variables qui manipulent des données devraient commencer par un nom. Ils peuvent aussi comprendre un adjectif si nécessaire :


image sound big-file image-files start-time

Utilisez des mots standards

Il y a des noms standards en REBOL qui devraient être utilisés pour des types d'opérations similaires. Par exemple :


make-blub ; créer quelque chose de nouveau (make)
free-blub ; libérer les ressources (free)
copy-blub ; copier un contenu (copy)
to-blub ; transformer en quelque chose (to-...)
insert-blub ; insérer quelque chose (insert)
remove-blub ; enlever (remove)
clear-blub ; remettre à zéro

En-têtes de script

L'intérêt des en-têtes est clair. Les en-têtes donnent aux utilisateurs un résumé du script et permettent à d'autres scripts de traiter cette information ( comme pour cataloguer de script). Un en-tête minimum de script fournit le titre, la date, le nom du fichier, et le sujet du script. D'autres champs peuvent aussi être fournis comme les auteurs, des notes, l'usage et les pré-requis.


REBOL [
Title: "Local Area Defringer"
Date: 1-Jun-1957
File: %defringe.r
Purpose: ^{
Stabilize the wide area ignition transcriber
using a double ganged defringing algorithm.
^}
]

En-tête de fonctions

Il est commode d'avoir une description dans le bloc de spécification d'une fonction. Limitez ce texte à une ligne de 70 caractères ou moins.

Au sein de cette description, mentionnez quel type de valeur est attendu normalement par la fonction.


defringe: func [
"Return the defringed localization radius."
area "Topo area to defringe"
time "Time allotted for operation"
/cost num "Maximum cost permitted"
/compound "Compound the calculation"
][
...code...
]

Nom des fichiers de script

La meilleure manière de nommer un fichier est de penser à la façon dont vous pourriez le retrouver dans quelques mois. Les noms courts et clairs sont assez souvent les meilleurs. Les noms complexes devraient être évités, à moins d'être signicatifs.

De plus, en nommant le script, pensez à la manière dont le nom ressortira dans le listing d' un répertoire. Par exemple, conservez les fichiers ayant un lien entre eux en faisant débuter leur nom par un mot commun.


%net-start.r
%net-stop.r
%net-run.r

Insertion d'exemples

Le cas échéant, fournissez des exemples dans votre script pour présenter son fonctionnement et pour permettre aux utilisateurs de vérifier rapidement s'il fonctionne correctement sur leur système.

Déboggage incorporé

Il est souvent utile de construire des fonctions de déboggage intégrées au script. C'est particulièrement vrai pour les scripts utilisant le réseau et manipulant des fichiers, et pour lesquels où il n'est pas souhaitable d'émettre et d'écrire des fichiers tant qu'on est en mode de test. De tels tests peuvent être gérés avec une variable de contrôle au début du script.


verbose: on
check-data: off

Minimiser le nombre de variables globales

Dans les longs scripts, et autant que possible, évitez d'utiliser des variables globales qui portent leur état interne d'une partie ou d'une fonction à l'autre.

Pour les petits scripts, ce n'est pas toujours pratique. Mais reconnaissez que ces scripts courts peuvent devenir au fil du temps de plus en plus grands.

Si vous avez un ensemble de variables globales fortement reliées entre elles, pensez à utiliser un objet pour les regrouper :


user: make object! [
name: "Fred Dref"
age: 94
phone: 707-555-1234
email: dref@fred.dom
]

Clarification du format d'un script

Voici un court script qui peut être utilisé pour nettoyer l'indentation d'un script. Il fonctionne en analysant la syntaxe REBOL et en reconstruisant chaque ligne du script. Cet exemple peut être trouvé dans la bibliothèque de scripts sur www.REBOL.com.


out: none ; output text
spaced: off ; add extra bracket spacing
indent: "" ; holds indentation tabs

emit-line: func [] [append out newline]

emit-space: func [pos] [
append out either newline = last out [indent] [
pick [#" " ""] found? any [
spaced
not any [find "[(" last out
find ")]" first pos]
]
]
]

emit: func [from to] [
emit-space from append out copy/part from to
]

clean-script: func [
"Returns new script text with standard spacing."
script "Original Script text"
/spacey "Optional spaces near brackets/parens"
/local str new
] [
spaced: found? spacey
out: append clear copy script newline
parse script blk-rule: [
some [
str:
newline (emit-line) |
#";" [thru newline | to end] new:
(emit str new) |
[#"[" | #"("]
(emit str 1 append indent tab)
blk-rule |
[#"]" | #")"]
(remove indent emit str 1) |
skip (set [value new]
load/next str emit str new) :new
]
]
remove out ; remove first char
]

script: clean-script read %script.r

write %new-script.r script

Manuel de l'utilisateur - Chapitre 3 - Présentation rapide

Historique de la traduction

Date Version Commentaires Auteur Email
18 mai 2005 - 19:31 1.0.0 Traduction initiale Philippe Le Goff lp—legoff—free—fr

Présentation générale

Ce chapitre a pour objectif de vous familiariser rapidement avec le langage REBOL. A l'aide d'exemples, ce chapitre présente les concepts de base et la structure du langage, et ceci, depuis le concept concernant les valeurs des données jusqu'à la maîtrise des opérations liées au réseau.

Valeurs

Un script est écrit avec un ensemble de valeurs. De nombreux types de valeurs existent et vous êtes confrontés à beaucoup d'entre eux dans le quotidien de vos journées. Lorsque cela est possible, REBOL permet aussi d'utiliser des formats internationaux pour des valeurs telles que les nombres décimaux, les données monétaires, les dates et les heures.

Nombres

Les nombres sont écrits sous forme d'entiers, de décimaux ou en notation scientifique. Par exemple :


1234 -432 3.1415 1.23E12

Et vous pouvez aussi écrire au format Européen :


123,4 0,01 1,2E12

Heures

Les données horaires sont écrites en heures et en minutes, avec les secondes en option, chacunes étant séparées par le symbole " :".

Par exemple :


12:34 20:05:32 0:25.345 0:25,345

Les secondes peuvent inclure les fractions de secondes (milliseconde). Les heures peuvent aussi être indiquées au format anglo-saxon AM et PM (sans espace) :


12:35PM 9:15AM

Dates

Les dates sont écrites dans l'un ou l'autre des formats internationaux : jour-mois-année ou année-mois-jour. Une date peut aussi inclure une heure et une indication de fuseau horaire. Le nom ou l'abréviation du mois peuvent être utilisés de façon à rendre le format plus semblable à celui en usage aux Etats-Unis. Par exemple :


20-Apr-1998 20/Apr/1998 (USA)

20-4-1998 1998-4-20 (international)

1980-4-20/12:32 (date et heure)

1998-3-20/8:32-8:00 (avec fuseau horaire)

Données monétaires

Les données monétaires sont écrites avec un symbole optionnel de trois lettres représentant la devise, suivies d'une grandeur numérique. Par exemple :


$12.34 USD$12.34 CAD$123.45 DEM$1234,56

Tuples

Les "tuples" sont utilisés pour des numéros de version, des valeurs RGB (Rouge-Vert-Bleu) de couleur, et des adresses réseau. Ils sont écrits sous la forme de nombres entiers compris entre 0 et 255 et séparés par des points.

Par exemple :


2.3.0.3.1 255.255.0 199.4.80.7

Au moins deux points sont requis (sinon, le nombre sera interprété comme une valeur décimale, pas un tuple). Exemple :


2.3.0 ; tuple
2.3. ; tuple
2.3 ; decimal

Chaînes de caractères

Les chaînes de caractères sont écrites en une seule ou plusieurs lignes. Les chaînes monolignes sont incluses entre des guillemets ("). Les chaînes s'étendant sur plusieurs lignes sont incluses entre des accolades .

Les chaînes qui comprennent des apostrophes, des marques de tabulations ou des sauts de lignes doivent être incluses entre des accolades comme pour le format multi-lignes. Par exemple :


"Here is a single-line string"

^{Here is a multiline string that
contains a "quoted" string.^}

Les caractères spéciaux (échappements) à l'intérieur de chaînes sont spécifiés avec le caractère (^^). Voir le paragraphe relatif aux chaînes de caractères dans le chapitre sur les Valeurs, pour la table des caractères spéciaux.

Balises

Les balises sont utilisées dans les langages comme XML et HTML. Les balises sont incluses entre les caratères "<" et ">". Par exemple :


<title> </body>

<font size="2" color="blue">

Adresses email

Les adresses email sont écrites directement en REBOL. Elles doivent inclure le symbole "@".

Par exemple :


info@rebol.com

pres-bill@oval.whitehouse.gov

URLs

La plupart des types d'URLs Internet est accepté directement sous REBOL. Celles-ci doivent commencer par un nom de protocole (HTTP par exemple) suivi d'un chemin (path).

Par exemple :


http://www.rebol.com

ftp://ftp.rebol.com/sendmail.r

ftp://freda:grid@da.site.dom/dir/files/

mailto:info@rebol.com

Noms de fichiers

Les noms de fichiers sont précédés par le symbole "%" (pourcentage), qui permet de faire la distinction avec les autres mots. Par exemple :


%data.txt

%images/photo.jpg

%../scripts/*.r

Paires

Les paires sont utilisées pour indiquer des coordonnées spatiales, comme des positions sur un écran. Elle sont utilisées pour indiquer aussi bien des positions ou des tailles. Les coordonnées sont séparées par un "x".

Par exemple :


100x50

1024x800

-50x200

Issues

Les "issues" sont des numéros d'identification, des séquences particulières de caractères, comme des numéros de téléphone, des numéros de séries, ou de carte de crédit.

Par exemple :


#707-467-8000

#0000-1234-5678-9999

#MFG-932-741-A

Binaires

Les binaires sont des chaînes d'octets de n'importe quelle longueur. Ils peuvent être encodés directement en hexadécimal ou en base-64.

Par exemple :


#^{42652061205245424F4C^}

64#^{UkVCT0wgUm9ja3Mh^}

Mots

Les mots sont les symboles qu'utilise REBOL. Un mot peut être ou non une variable, selon l'usage qui en est fait. Les mots peuvent aussi être directement utilisés comme symboles.


show next image

Install all files here

Country State City Street Zipcode

on off true false one none

REBOL n'a pas de mots-clés ; il n'existe pas de restriction sur les mots utilisés, et sur la façon dont ils sont utilisés. Par exemple, vous pouvez définir votre propre fonction, appelée print, et l'utiliser au lieu de celle prédéfinie dans le langage pour l'affichage de valeurs.

Les mots sont insensibles à la casse, et peuvent inclure des traits d'union et d'autres caractères spéciaux, comme :


+ - ` * ! ~ & ? |

Les exemples suivants présentent quelques mots valides :


number? time? date!
image-files l'image
++ -- == +-
***** *new-line*
left&right left|right

La fin d'un mot est indiqué par un espace, un saut de ligne, ou l'un des caractères suivants :


[ ] ( ) ^{ ^} " : ; /

Les caractères suivants, par contre, ne sont pas autorisés dans les mots :


@ # $ % ^^ ,

Blocs

REBOL se compose de groupes de valeurs et de mots placés dans des blocs. Les blocs sont utilisés pour le code, les listes, les matrices, les tableaux, les répertoires, les associations et autres formes ordonnées. Un bloc est une sorte de série, dans laquelle les valeurs sont organisées dans un ordre spécifique.

Un bloc est inclus entre deux crochets [ ]. A l'intérieur du bloc, les valeurs et les mots peuvent être organisés selon n'importe quel ordre. Les exemples suivants illustrent différentes formes de blocs valides :


[white red green blue yellow orange black]

["Spielberg" "Back to the Future" 1:56:20 MCA]

[
Ted ted@gw2.dom #213-555-1010
Bill billg@ms.dom #315-555-1234
Steve jobs@apl.dom #408-555-4321
]

[
"Elton John" 6894 0:55:68
"Celine Dion" 68861 0:61:35
"Pink Floyd" 46001 0:50:12
]

Les blocs sont utilisés pour du code aussi bien que pour des données, comme le montrent les exemples suivants :


loop 10 [print "hello"]

if time > 10:30 [send jim news]

sites: [
http://www.rebol.com [save %reb.html data]
http://www.cnn.com [print data]
ftp://www.amiga.com [send cs@org.foo data]
]

foreach [site action] sites [
data: read site
do action
]

Un fichier script est aussi un bloc.

Bien qu'il n'inclut pas de crochets, le bloc est implicite. Par exemple, si les lignes ci-dessous sont mises dans un fichier script :


red
green
blue
yellow

Lorsque le fichier sera évalué, ce sera sous la forme d'un bloc contenant les mots red, green, blue, et yellow. Cela revient à écrire :


[red green blue yellow]

Variables

Les mots peuvent être utilisés comme variables faisant référence à des valeurs. Pour définir un mot en tant que variable, faites-le suivre de deux points ( :), puis de la valeur attribuée à la variable, comme indiqué dans les exemples suivants :


age: 22
snack-time: 12:32
birthday: 20-Mar-1997
friends: ["John" "Paula" "Georgia"]

Une variable peut faire référence à n'importe quel type de valeur, notamment des fonctions (voir chapitre sur les Fonctions) ou des objets (voir celui sur les Objets).

Une variable fait référence à une valeur, spécifique à un contexte donné qui peut être un bloc, une fonction, ou un programme complet.

En dehors de ce contexte, la variable peut faire référence à d'autres valeurs, ou à aucune. Le contexte d'une variable peut s'étendre sur le programme entier (portée globale) ou être restreint à un bloc particulier, une fonction, ou un objet. Dans d'autres langages, le contexte d'une variable est souvent identifié comme "la portée d'une variable".

Evaluation

Les blocs sont évalués pour renvoyer leurs résultats. Quand un bloc est évalué, les valeurs de ses variables sont obtenues. Les exemples suivants évaluent les variables age, snack-time, birthday, et friends qui ont été définies dans le paragraphe précédent :


print age
22
if current-time > snack-time [print snack-time]
12:32
print third friends
Georgia

Un bloc peut être évalué plusieurs fois en utilisant une boucle, comme le montrent les exemples suivants :


loop 10 [prin "*"] ;("prin" n'est pas une erreur de frappe, voir le manuel)
**********
loop 20 [
wait 8:00
send friend@rebol.com read http://www.cnn.com
]

repeat count 3 [print ["count:" count]]
count: 1
count: 2
count: 3

L'évaluation d'un bloc renvoie un résultat. Dans les exemples suivants, 5 et PM sont les résultats de l'évaluation, respectivement, de chaque bloc :


print do [2 + 3]
5
print either now/time < 12:00 ["AM"]["PM"]
PM

En REBOL, il n'y a pas d'opérateur particulier pour les régles de priorité, dans l'évaluation d'un bloc. Les valeurs et les mots d'un bloc sont toujours évalués du premier au dernier, comme l'illustre l'exemple :


print 2 + 3 * 10
50

L'usage de parenthèses peut permettre de contrôler l'ordre de l'évaluation, comme dans les exemples ci-dessous :


2 + (3 * 10)
32
(length? "boat") + 2
6

Vous pouvez aussi évaluer un bloc et retourner chacun des résultats calculés à l'intérieur du bloc. C'est l'objet de la fonction reduce :


reduce [1 + 2 3 + 4 5 + 6]
3 7 11

Fonctions

Une fonction est un bloc avec des variables qui donnent de nouvelles valeurs à chaque fois que le bloc est évalué.

Ces variables sont appelées les arguments de la fonction. Dans l'exemple suivant, le mot sum fait référence à une fonction qui va accepter deux arguments, a et b :


sum: func [a b] [a + b]

Dans l'exemple précédent, func est utilisée pour définir une nouvelle fonction.

Le premier bloc dans la fonction définit les arguments de cette fonction. Le second bloc est le bloc de code qui sera évalué quand la fonction sera utilisée. Dans cet exemple, le second bloc additionne les deux valeurs en arguments et renvoie le résultat.

Le prochain exemple illustre le fonctionnement de la fonction sum qui a été définie auparavant :


print sum 2 3
5

Certaines fonctions nécessitent des variables locales tout comme des arguments. Pour définir ce genre de fonction, vous pouvez utiliser function au lieu de func (NdT : dépassé ! Utilisez plutôt func avec le refinement /local), comme le montre l'exemple suivant :


average: function [series] [total] [
total: 0
foreach value series [total: total + value]
total / (length? series)
]

print average [37 1 42 108]
47

Dans l'exemple ci-dessus, le mot series est un argument et le mot total est une variable locale utilisée par la fonction, à des fins de calcul.

Le bloc d'argument de la fonction peut contenir des libellés décrivant l'objet et l'usage de la fonction, et de ses arguments, comme illustré ci-dessous :


average: function [
"Return the numerical average of numbers"
series "Numbers to average"
] [total] [
total: 0
foreach value series [total: total + value]
total / (length? series)
]

Les chaînes de caractères sont stockées avec la fonction et peuvent être consultées lors d'une demande d'aide, au sujet de la fonction, avec l'aide en ligne :


help average
USAGE:
AVERAGE series
DESCRIPTION:
Return the numerical average of numbers
AVERAGE is a function value.
ARGUMENTS:
series -- Numbers to average (Type: any)

Paths

NdT : le terme anglais "path" a été conservé.

Si vous utilisez des fichiers et des URLs, alors vous êtes déjà familier avec le concept de "paths" (chemins). Un path fournit un ensemble de valeurs qui sont utilisées pour "naviguer" d'un point à un autre. Dans le cas d'un fichier, un "path" spécifie le parcours au travers les différents répertoires jusqu'à l'endroit où se trouve le fichier.

En REBOL, les valeurs dans un path sont appelées des raffinements.

Le symbole slash ( / ) est utilisé pour séparer les mots et les valeurs dans un path, comme le montrent les exemples suivants pour un fichier ou une URL.


%source/images/globe.jpg

http://www.rebol.com/examples/simple.r

Les paths sont aussi utilisés pour sélectionner des valeurs de blocs, ou des caractères dans des chaînes , accéder à des variables au sein d'objets, et encore pour les raffinements d'une fonction, comme le montrent les exemples :


USA/CA/Ukiah/size (block selection)
names/12 (string position)
account/balance (object function)
match/any (function option)

La fonction print dans l'exemple ci-dessous montre la simplicité d'utilisation des paths pour accéder à une mini base de donnée sà partir de bloc :


towns: [
Hopland [
phone #555-1234
web http://www.hopland.ca.gov
]

Ukiah [
phone #555-4321
web http://www.ukiah.com
email info@ukiah.com
]
]

print towns/ukiah/web
http://www.ukiah.com

Objets

Un objet est un ensemble de variables dont les valeurs sont spécifiques à un contexte. Les objets sont utilisés pour manipuler des structures de données et des comportements complexes.

L'exemple suivant montre comment un compte bancaire est décrit par un objet dont les attributs et les fonctions sont spécifiés :


account: make object! [
name: "James"
balance: $100
ss-number: #1234-XX-4321
deposit: func [amount] [balance: balance + amount]
withdraw: func [amount] [balance: balance - amount]
]

Dans l'exemple ci-dessus, les mots name, balance, ss-numer, deposit, et withdraw sont des variables locales de l'objet account. Les variables deposit et withdraw sont des fonctions qui sont définies au sein de l'objet. Les variables de l'objet account sont accessibles avec un path :


print account/balance
$100.00
account/deposit $300

print ["Balance for" account/name "is" account/balance]
Balance for James is $400.00

L'exemple suivant montre comment créer un autre compte avec un nouveau solde, mais possédant toutes les autres valeurs provenant du premier compte.


checking-account: make account [
balance: $2000
]

Vous pouvez aussi créer un compte bancaire qui étend les caractéristiques de l'objet account en ajoutant le nom de la banque et la date de la dernière opération, comme illustré ci-dessous :


checking-account: make account [
bank: "Savings Bank"
last-active: 20-Jun-2000
]

print checking-account/balance
$2000.00
print checking-account/bank
Savings Bank
print checking-account/last-active
20-Jun-2000

Scripts

Un script est un fichier qui contient un bloc pouvant être chargé et évalué. Le bloc peut contenir du code ou des données, et aussi typiquement un certain nombre de sous-blocs.

Les scripts nécessitent un en-tête (header) pour identifier la présence de code. L'en-tête peut inclure le titre du script, la date, et d'autres informations. Dans l'exemple suivant, le premier bloc contient l'information propre à l'en-tête.


REBOL [
Title: "Web Page Change Detector"
File: %webcheck.r
Author: "Reburu"
Date: 20-May-1999
Purpose: ^{
Determine if a web page has changed since it was
last checked, and if it has, send the new page
via email.
^}
Category: [web email file net 2]
]

page: read http://www.rebol.com

page-sum: checksum page

if any [
not exists? %page-sum.r
page-sum <> (load %page-sum.r)
][
print ["Page Changed" now]
save %page-sum.r page-sum
send luke@rebol.com page
]

Fichiers

En REBOL, les fichiers peuvent facilement être manipulés. La liste suivante décrit quelques opérations relatives aux fichiers.

Récupérer le contenu d'un fichier texte :


data: read %plan.txt

Vous pouvez afficher un fichier texte avec :


print read %plan.txt

Pour écrire dans un fichier texte :


write %plan.txt data

Par exemple, vous pouvez écrire l'heure courante avec :


write %plan.txt now

Vous pouvez aussi facilement ajouter des données en fin de fichier :


write/append %plan data

Les fichiers binaires peuvent être lus ou écrits avec :


data: read/binary %image.jpg

write/binary %new.jpg data

Pour charger un fichier comme un bloc ou une valeur REBOL :


data: load %data.r

Sauvegarder un bloc ou une valeur dans un fichier est tout aussi facile :


save %data.r data

Pour évaluer un fichier en tant que script (ce qui nécessite un en-tête valide pour cela ) :


do %script.r

Vous pouvez lister le contenu d'un répertoire avec :


dir: read %images/

et, vous pouvez alors afficher les noms de fichiers avec :


foreach file dir [print file]

Pour créer un répertoire :


make-dir %newdir/

Pour savoir quel est le répertoire courant :


print what-dir

Si vous avez besoin d'effacer un fichier :


delete %oldfile.txt

Vous pouvez aussi renommer un fichier avec :


rename %old.txt %new.txt

Pour avoir les propriétés d'un fichier :


print size? %file.txt

print modified? %file.txt

print dir? %image

Réseau

Il existe plusieurs protocoles pré-inclus dans REBOL. Ces protocoles sont faciles à utiliser et nécessitent juste un minimum de connaissances relatives au Réseau.

HTTP

L'exemple suivant montre comment utiliser le protocole HTTP pour lire une page web :


page: read http://www.rebol.com

L'exemple ci-dessous récupére une image dans une page web, et la sauvegarde en local dans un fichier :


image: read/binary http://www.page.dom/image.jpg

write/binary %image.jpg image

FTP

Ici, le code suivant lit et écrit des fichiers sur un serveur en utilisant le protocole FTP :


file: read ftp://ftp.rebol.com/test.txt

write ftp://user:pass@site.dom/test.txt file

L'exemple suivant retourne le contenu d'un répertoire en FTP :


print read ftp://ftp.rebol.com/pub

SMTP

Les exemples suivants envoient un courrier électronique avec le protocole SMTP :


send luke@rebol.com "Use the force."

Ici le contenu d'un fichier texte est envoyé par email


send luke@rebol.com read %plan.txt

POP

L'exemple suivant récupére des emails avec le protocole POP et affiche tous les messages courants de la boîte de réception, en les laissant sur le serveur :


foreach message read pop://user:pass@mail.dom [
print message
]

NNTP

L'exemple qui suit récupére les news en utilisant le protocole NNTP (network news transfer protocol), en lisant toutes les nouvelles relatives à un groupe en particulier :


messages: read nntp://news.server.dom/comp.lang.rebol

Ici, l'exemple ci-dessous permet la lecture et l'impression de tous les groupes de discussions :


news-groups: read nntp://news.some-isp.net

foreach group news-groups [print group]

DAYTIME

L'exemple suivant retourne l'heure courante d'un serveur :


print read daytime://everest.cclabs.missouri.edu

WHOIS

Il est possible avec l'exemple ci-dessous de savoir qui est responsable d'un domaine, avec le protocole Whois :


print read whois://rebol@rs.internic.net

FINGER

L'exemple suivant ramène des informations concernant un utilisateur avec le protocole Finger :


print read finger://username@host.dom

DNS

Ici, une adresse Internet est déterminée à partir d'un nom de domaine, et inversement un nom de domaine à partir d'une adresse IP :


print read dns://www.rebol.com

print read dns://207.69.132.8

TCP

Les connections directes avec TCP/IP sont également possibles en REBOL.

L'exemple qui illustre ceci est un serveur simple, mais pratique, qui attend des connections sur un port, et exécute ce qui a été recu :


server-port: open/lines tcp://:9999

forever [
connection-port: first server-port
until [
wait connection-port
error? try [do first connection-port]
]
close connection-port
]

Manuel de l'utilisateur - Chapitre 7 - Les Séries de blocs

Historique de la traduction

Date Version Commentaires Auteur Email
22 mai 2005 7:42 1.0.0 Traduction initiale Philippe Le Goff lp—legoff—free—fr

Blocs de Blocs

Quand un bloc apparaît en tant que valeur au sein d'un autre bloc, il est compté comme un seul élément et cela, quelque soit le nombre de valeurs qu'il contient.

Par exemple :


values: [
"new" [1 2]
%file1.txt ["one" ["two" %file2.txt]]
]
probe values
new" [1 2] %file1.txt ["one" ["two" %file2.txt]]]

La longueur de values est quatre éléments. La seconde et la quatrième valeur sont comptés comme des éléments unitaires :


print length? values
4

Les blocs à l'intérieur d'autres blocs ne perdent pas leur caractéristique de bloc. Dans l'exemple ci-dessous, la fonction second est utilisée pour extraire la deuxième valeur du bloc values. Pour afficher le bloc, saisissez :


probe second values
[1 2]

Pour connaître la longueur de ce bloc, tapez :


print length? second values
2

Pour afficher le type de données (datatype) :


print type? second values
block!

De la même manière, les fonctions sur les séries peuvent être exploitées sur d'autres types de valeurs dans les blocs. Dans l'exemple suivant, pick est utilisé pour extraire %file1.txt du bloc values.

Pour récupérer la valeur du troisiéme élément, saisissez :


probe pick values 3
%file1.txt

Pour récupérer la longueur de la valeur :


print length? pick values 3
9

Pour voir le type de données associé à la valeur extraite :


print type? pick values 3
file

Paths, chemins pour les blocs imbriqués

La notation avec les paths est très pratique pour les blocs imbriqués.

La quatrième valeur de la série values est un bloc contenant d'autres blocs. L'exemple suivant utilise un path pour récupérer des informations dans ce bloc.

Pour voir les valeurs de ce bloc, tapez :


probe values/4
["one" ["two" %file2.txt]]
probe values/4/2
["two" %file2.txt]

Pour obtenir les longueurs :


print length? values/4
2
print length? values/4/2
2

Et pour voir le type de données, saisissez :


print type? values/4
block!
print type? values/4/2
block!

Les deux séries contenues dans cette quatrième valeur sont aisément accessibles. Pour voir ces valeurs, tapez :


probe values/4/2/1
two
probe values/4/2/2
%file2.txt

Pour obtenir les longueurs de ces valeurs :


print length? values/4/2/1
3
print length? values/4/2/2
9

et pour leurs datatypes (types de données) :


print type? values/4/2/1
string
print type? values/4/2/2
file

Pour modifier ces valeurs :


change (next values/4/2/1) "o"
probe values/4/2/1
too
change/part (next find values/4/2/2 ".") "r" 3
probe values/4/2/2
%file2.r

Les exemples précédents illustrent la capacité que possède REBOL à manipuler des valeurs imbriquées dans des blocs. Notez que, dans les derniers exemples, la fonction change est utilisée pour modifier une chaîne et un nom de fichier avec trois niveaux d'imbrication.

L'affichage du bloc values produit le résultat suivant :


probe values
["new" [1 2] %file1.txt ["one" ["too" %file2.r]]]

Tableaux

Les blocs sont utilisés pour créer des tableaux. Un exemple de tableau bi-dimensionnel statique est :


arr: [
[1 2 3 ]
[a b c ]
[$10 $20 $30]
]

Vous pouvez obtenir les valeurs d'un tableau avec les fonctions d'extraction relatives aux séries :


probe first arr
[1 2 3]
probe pick arr 3
[$10.00 $20.00 $30.00]
probe first first arr
1

Vous pouvez aussi utiliser des paths pour obtenir les valeurs d'un tableau :


probe arr/1
[1 2 3]
probe arr/3
[$10.00 $20.00 $30.00]
probe arr/3/2
$20.00

Les paths peuvent encore être utilisés pour changer les valeurs dans un tableau :


arr/1/2: 20

probe arr/1
[1 20 3]
arr/3/2: arr/3/1 + arr/3/3

probe arr/3/2
$40.00

Création de tableaux

La fonction array crée dynamiquement un tableau.

Cette fonction prend en argument soit un nombre entier, soit un bloc de nombres entiers, et elle retourne en résultat un bloc : le tableau. Par défaut, les cellules d'un tableau sont initialisées à none.

Pour intialiser les cellules d'un tableau avec d'autres valeurs, utilisez le raffinement /initial, qui est expliqué dans la section suivante.

Lorsqu'un tableau est fourni avec un seul nombre entier, c'est un tableau à une dimension, de la taille du nombre, qui est retourné.


arr: array 5
probe arr
[none none none none none]

Quand un bloc de plusieurs nombres entiers est passé en argument, le tableau est à plusieurs dimensions. Chaque nombre entier donne respectivement la taille de la dimension correspondante.

Voici un exemple d'un tableau possédant six cellules, sur deux lignes et trois colonnes :


arr: array [2 3]
probe arr
[[none none none] [none none none]]

Il est possible de faire un tableau à trois dimensions en rajoutant un autre nombre entier au bloc en argument :


arr: array [2 3 2]
foreach lst arr [probe lst]
[[none none] [none none] [none none]]
[[none none] [none none] [none none]]

Le bloc d'entiers qui est passé à la fonction array peut être très grand selon ce que la capacité de la mémoire de votre système.

Valeurs initiales

Pour initialiser les cellules d'un tableau à une valeur autre que none, utilisez le raffinement /initial.

Voici quelques exemples :


arr: array/initial 5 0
probe arr
[0 0 0 0 0]
arr: array/initial [2 3] 0
probe arr
[[0 0 0] [0 0 0]]
arr: array/initial 3 "a"
probe arr
["a" "a" "a"]
arr: array/initial [3 2] 'word
probe arr
[[word word] [word word] [word word]]
arr: array/initial [3 2 1] 11:11
probe arr
[[[11:11] [11:11]] [[11:11] [11:11]] [[11:11] [11:11]]]

Composition de blocs

La fonction compose est pratique pour créer des blocs avec des valeurs dynamiques. Elle peut être utilisée pour créer aussi bien des données et du code.

La fonction compose attend un bloc en argument et renvoie en résultat un bloc composé de chacune des valeurs du bloc en argument.

Les valeurs entre parenthèses sont évaluées en priorité, avant que le bloc ne soit retourné. Par exemple :


probe compose [1 2 (3 + 4)]
[1 2 7]
probe compose ["The time is" (now/time)]
["The time is" 10:32:45]

Si des parenthèses encadrent un bloc, alors chaque valeur de ce bloc sera utilisée :


probe compose [a b ([c d])]
[a b c d]

Pour éviter cela dans le résultat, vous devez inclure ce bloc dans un autre bloc :

(Ndt : c'est-à-dire protéger le bloc par un autre bloc).


probe compose [a b ([[c d]])]
[a b [c d]]

Un bloc sans éléments est sans effet :


probe compose [a b ([]) c d]
[a b c d]

Lorsque compose s'applique sur un bloc comprenant des sous-blocs, les sous-blocs ne sont pas évalués, même s'ils contiennent des parenthèses :


probe compose [a b [c (d e)]]
[a b [c (d e)]]

Si vous souhaitez que les sous-blocs soient évalués, utilisez le raffinement /deep. Le raffinement /deep entraine l'évaluation de toutes les valeurs entre parenthèses, indépendamment de la position où elles se trouvent :


probe compose/deep [a b [c (d e)]]
[a b [c d e]]

lundi 12 septembre 2005

Manuel de l'utilisateur - Chapitre 8 - Les Séries : chaînes

Historique de la traduction

Date Version Commentaires Auteur Email
26 mai 2005 22:17 1.0.0 Traduction initiale Philippe Le Goff lp—legoff—free—fr

Fonctions relatives aux chaînes de caractères

De nombreuses fonctions permettent de manipuler ou de créer des chaînes de caractères. Ces fonctions peuvent transformer des chaînes, y effectuer des recherches, les compresser ou les décompresser, modifier leur espacement, les analyser, et les convertir. Ces fonctions agissent sur tous les types de données liés aux chaînes de caractères, comme string !, binary !, tag !, file !, URL !, email !, et issue !.

Les fonctions de création, de modification et de recherche ont été présentées dans le chapitre sur les Séries. Cette présentation incluait les fonctions de chaînes :

copy : permet la copie d'une partie ou de toute une chaîne

make : alloue un espace mémoire pour la chaîne, crée un type

insert : insére un caractère ou une sous-chaîne dans une autre

remove : ôte un ou plusieurs caractères d'une chaîne

change : change un ou plusieurs caractères dans une chaîne

append : insère un caractère ou une sous-chaîne à la fin d'une chaîne

find : trouve ou effectue une correspondance entre chaînes

replace : trouve une chaîne et la remplace par une autre

De surcroît, les fonctions permettant de parcourir les séries, comme next, back, head, et tail ont déjà été présentées. Elles sont utilisées pour se déplacer dans les chaînes. Egalement, les fonctions de test des séries vous permettent de déterminer votre position dans une chaîne (Ndt : comme index ?, tail ?, head ?).

Ce chapitre va présenter d'autres fonctions qui permettent la conversion de valeurs REBOL en chaînes de caractères. Ces fonctions sont fréquemment utilisées, comme avec les fonctions print et probe.

Elles comprennent :

form : convertit des valeurs avec des espaces en un format humainement lisible

mold : convertit des valeurs en un format REBOL

join : concatène des valeurs

reform : réduit (évalue) des valeurs avant de les traduire avec form

remold : réduit (évalue) des valeurs avant de les traduire avec mold

rejoin : réduit (évalue) des valeurs avant de les concaténer

Ce chapitre décrira aussi les fonctions de chaîne de caractères :

detab : remplace les tabulations par des espaces

entab : remplace les espaces par des tabulations

trim : enléve les espaces blancs ou les lignes vierges autour de chaînes de caractère

uppercase : change en majuscules

lowercase : change en minuscules

checksum : calcule la valeur de checksum pour une chaîne

compress : compresse la chaîne

decompress : décompresse la chaîne

enbase : encode une chaîne sur une autre base numérique

debase : convertit une chaîne encodée

dehex : convertit des valeurs hexadécimales ASCII en caractères (ex. dans les URLs).

Conversion de valeurs en chaînes de caractères

Join

La fonction join prend deux arguments et les concaténe en une seule chaîne.

Le type de données de la série retournée est basé sur celui du premier argument. Quand le premier argument est une valeur de type "série", le même type est retourné :


str: "abc"
file: %file
url: http://www.rebol.com/

probe join str [1 2 3]
<span class="output">abc123</span>
probe join file ".txt"
<span class="output">%file.txt</span>
probe join url %index.html
<span class="output">http://www.rebol.com/index.html</span>

Quand le premier argument n'est pas une série, la fonction join le convertit en chaîne de caractère, puis effectue la concaténation :


print join $11 " dollars"
<span class="output">$11.00 dollars</span>
print join 9:11:01 " elapsed"
<span class="output">9:11:01 elapsed</span>
print join now/date " -- today"
<span class="output">30-Jun-2000 -- today</span>
print join 255.255.255.0 " netmask"
<span class="output">255.255.255.0 netmask</span>
print join 412.452 " light-years away"
<span class="output">412.452 light-years away</span>

Quand le deuxième argument ajouté est un bloc, les valeurs de ce bloc sont évaluées et ajoutées au résultat :


print join "a" ["b" "c" 1 2]
<span class="output">abc12</span>
print join %/ [%dir1/ %sub-dir/ %filename ".txt"]
<span class="output">%/dir1/sub-dir/filename.txt</span>
print join 11:09:11 ["AM" " on " now/date]
<span class="output">11:09:11AM on 30-Jun-2000</span>
print join 312.423 [123 987 234]
<span class="output">312.423123987234</span>

Rejoin

La fonction rejoin est identique à join, mis à part le fait qu'elle prend un argument de type bloc, qui est évalué :


print rejoin ["try" 1 2 3]
<span class="output">try123</span>
print rejoin ["h" 'e #"l" (to-char 108) "o"]
<span class="output">hello</span>

Form

La fonction form transforme une valeur en chaîne de caractères :


print form $1.50
<span class="output">$1.50</span>
print type? $1.50
<span class="output">money</span>
print type? form $1.50
<span class="output">string</span>

L'exemple suivant utilise form pour trouver un nombre par sa valeur décimale :


blk: [11.22 44.11 11.33 11.11]
foreach num blk [if find form num ".11" [print num]]
<span class="output">44.11
11.11</span>

Lorsque form est utilisée sur un bloc, toutes les valeurs du bloc sont converties en chaînes de caractères, avec des espaces entre chacune d'elles :


print form [11.22 44.11 11.33]
<span class="output">11.22 44.11 11.33</span>

La fonction form n'évalue pas les valeurs d'un bloc. Elle transforme des mots en chaînes de caractères :


print form [a block of undefined words]
<span class="output">a block of undefined words</span>
print form [33.44 num "-- unevaluated string:" str]
<span class="output">33.44 num -- unevaluated string: str</span>

Reform

La fonction reform est identique à form, excepté que les blocs sont réduits (évalués) avant d'être convertis en chaînes.


str1: "Today's date is:"
str2: "The time is now:"
print reform [str1 now/date newline str2 now/time]
<span class="output">Today's date is: 30-Jun-2000 The time is now: 14:41:44</span>

La fonction d'affichage print est basée sur la fonction reform.

Mold

La fonction mold convertit une valeur en chaîne de caractère utilisable par REBOL. Les chaînes créées avec mold peuvent être retransformées en valeurs REBOL avec la fonction load.


blk: [[11 * 4] ($15 - $3.89) "eleven dollars"]
probe blk
<span class="output">[[11 * 4] ($15.00 - $3.89) "eleven dollars"]</span>
molded-blk: mold blk
probe molded-blk
<span class="output">^{[[11 * 4] ($15.00 - $3.89) "eleven dollars"]^}</span>
print type? blk
<span class="output">block</span>
print type? molded-blk
<span class="output">string</span>
probe first blk
<span class="output">[11 * 4]</span>
probe first molded-blk
<span class="output">#"["</span>

Les chaînes renvoyées par mold peuvent être récupérées par REBOL :


new-blk: load molded-blk
probe new-blk
<span class="output">[[11 * 4] ($15.00 - $3.89) "eleven dollars"]</span>
print type? new-blk
<span class="output">block</span>
probe first new-blk
<span class="output">[11 * 4]</span>

La fonction mold n'évalue pas les valeurs d'un bloc :


money: $11.11
sub-blk: [inside another block mold this is unevaluated]
probe mold [$22.22 money "-- unevaluated block:" sub-blk]
<span class="output">^{[$22.22 money "-- unevaluated block:" sub-blk]^}</span>
probe mold [a block of undefined words]
<span class="output">[a block of undefined words]</span>

Remold

La fonction remold s'utilise comme mold, à l'exception du fait que les blocs sont réduits (évalués) avant d'être convertis.


str1: "Today's date is:"
probe remold [str1 now/date]
<span class="output">^{["Today's date is:" 30-Jun-2000]^}</span>

Fonctions pour gérer les espaces

Trim

La fonction trim enlève tous les espaces multiples d'une chaîne. Par défaut, trim enlève les espaces en excés au début et à la fin d'une chaîne :


str: " line of text with spaces around it "
print trim str
<span class="output">line of text with spaces around it</span>

Remarquez que la chaîne est modifiée dans le processus :


print str
<span class="output">line of text with spaces around it</span>

Pour exécuter trim sur une copie d'une chaîne, écrivez :


print trim copy str
<span class="output">line of text with spaces around it</span>

La fonction trim inclut quelques raffinement afin d'indiquer où les espaces doivent être supprimés dans la chaîne :

/head : enlève les espaces en début de chaîne

/tail : enlève les espaces en fin de chaîne

/auto : enlève les espaces à chaque ligne, relativement à la première ligne

/lines : enlève les sauts de lignes, et les remplace par des espaces

/all : enlève tous les espaces, les tabulations,et les sauts de lignes

/with : enlève tous les caractères spécifiés

Utilisez les raffinements /head et /tail pour ôter les espaces en début et en fin de chaîne :


probe trim/head copy str
<span class="output">line of text with spaces around it</span>
probe trim/tail copy str
<span class="output">line of text with spaces around it</span>

Utilisez le raffinement /auto pour effacer les espaces résiduels sur des lignes multiples, tout en conservant intacte l'indentation :


str: ^{
indent text
indent text
indent text
indent text
indent text
^}
print str
<span class="output">indent text
indent text
indent text
indent text
indent text</span>
probe trim/auto copy str
<span class="output">^{indent text
indent text
indent text
indent text
indent text
^}</span>

Le raffinement /lines permet d'enlever les espaces en début et en fin de chaîne, mais également de convertir les sauts de lignes en espaces :


probe trim/lines copy str
<span class="output">^{indent text indent text indent text indent text indent text^}</span>

L'usage du raffinement /all enléve tous les espaces, les tabulations, les sauts de lignes :


probe trim/all copy str
<span class="output">indenttextindenttextindenttextindenttextindenttext</span>

La raffinement /with permet d'éliminer de la chaîne tous les caractères qui ont été spécifiés avec /with. Dans l'exemple suivant, les espaces, les sauts de lignes, et les caractères "e" et "t" sont supprimés :


probe trim/with copy str " ^^/et"
<span class="output">indnxindnxindnxindnxindnx</span>

Detab et Entab

Les fonctions detab et entab transforment les tabulations en espaces et inversement, les espaces en tabulations.


str:
^{^^(tab)line one
^^(tab)^^(tab)line two
^^(tab)^^(tab)^^(tab)line three
^^(tab)line^^(tab)full^^(tab)of^^(tab)tabs^}
print str
<span class="output">line one
line two
line three
line full of tabs</span>

Par défaut, la fonction detab convertit chaque tabulation en une série de quatre espaces (le standard pour le style REBOL). Toutes les tabulations dans la chaîne seront transformées en espaces, quelque soient leurs positions.


probe detab str
<span class="output">^{ line one
line two
line three
line full of tabs^}</span>

Remarquez que les fonctions detab et entab modifient la chaîne qu'elles prennent en argument. Pour travailler sur une copie de la chaîne source, utilisez la fonction copy.

La fonction entab convertit les espaces en tabulations. Chaque série de quatre espaces sera transformée en une tabulation. Seuls les espaces en début de ligne seront transformés en tabulations.


probe entab str
<span class="output">^{^^-line one
^^-^^-line two
^^-^^-^^-line three
^^-line^^-full^^-of^^-tabs^}</span>

Vous pouvez utiliser le raffinement /size pour spécifier la taille des tabulations. Par exemple, si vous voulez convertir chaque tabulation en série de huit espaces, ou transformer ces huit espaces en une tabulation, vous pouvez utiliser cet exemple :


probe detab/size str 8
<span class="output">^{ line one
line two
line three
line full of tabs^}</span>
probe entab/size str 8
<span class="output">^{^^-line one
^^-^^-line two
^^-^^-^^-line three
^^-line^^-full^^-of^^-tabs^}</span>

Uppercase et Lowercase

Deux fonctions permettent le changement de la casse des caractères : uppercase et lowercase.

La fonction uppercase prend une chaîne en argument et la met en majuscule.


print uppercase "SamPle TExT, tO test CASES"
<span class="output">SAMPLE TEXT, TO TEST CASES</span>

La fonction lowercase effectue le travail inverse, elle met les caractères en minuscule :


print lowercase "Sample TEXT, tO teST Cases"
<span class="output">sample text, to test cases</span>

Pour transformer juste une partie de la chaîne, utilisez le raffinement /part :


print upppercase/part "ukiah" 1
<span class="output">Ukiah</span>

Checksum

La fonction checksum renvoie la valeur de checksum (somme de contrôle) d'une chaîne. Plusieurs types de checksum peuvent être calculés

CRC24 : contrôle de redondance cyclique (défaut)

TCP : checksum Internet TCP 16-bit.

Secure : Retourne un checksum sécurisé par cryptage

NdT :

Les élèments qui suivent correspondent à l'aide en ligne sur la fonction checksum, et non à la documentation officielle du User Guide, qui semble caduque sur ce point.

Checksum permet l'usage des raffinements :

/tcp : renvoie la valeur de checksum Internet 16 bits

/secure : renvoie la valeur de checksum sécurisé par cryptage

/hash : retourne une valeur d'index pour une table de hachage.

/method : utilise une méthode de cryptage, qui peut être SHA1 ou MD5

/key : utilise une clé pour une authentification HMAC ( Keyed-Hashing for Message Authentication Code).

NdT :

Voir l'aide en ligne pour plus de détails.

Par défaut, c'est la valeur de checksum CRC qui est calculée :


print checksum "hello"
<span class="output">52719</span>
print checksum (read http://www.rebol.com/)
<span class="output">356358</span>

Pour calculer la checksum TCP, utilisez le raffinement /tcp :


print checksum/tcp "hello"
<span class="output">10943</span>

Le raffinement /secure retournera une valeur binaire, pas un entier. Utilisez le raffinement /secure, pour calculer ce type de checksum :


print checksum/secure "hello"
<span class="output">#^{AAF4C61DDCC5E8A2DABEDE0F3B482CD9AEA9434D^}</span>

Le raffinement /method permet d'utiliser (par exemple pour contrôler des mots de passe) une méthode de cryptage MD5 ou SHA1 :


print checksum/method "password2005" 'md5
<span class="output">#^{9FDC0F6F1A5A0443F1C6E2393BE936DE^}</span>
print checksum/method "password2005" 'sha1
<span class="output">#^{3E352A5705741521337C01537AEA0A54DD13B993^}</span>

Compression et décompression

La fonction compress va compresser une chaîne et retourner un type de donnée binaire. Dans l'exemple suivant, un petit fichier est compressé :


Str:
^{I wanted the gold, and I sought it,
I scrabbled and mucked like a slave.
Was it famine or scurvy -- I fought it;
I hurled my youth into a grave.
I wanted the gold, and I got it --
Came out with a fortune last fall, --
Yet somehow life's not what I thought it,
And somehow the gold isn't all.^}

print [size? str "bytes"]
<span class="output">306 bytes</span>
bin: compress str

print [size? bin "bytes"]
<span class="output">156 bytes</span>

Remarquez que le résultat de la compression est du type de données binaire (binary !).

La fonction decompress décompresse une chaîne qui a été préalablement compressée.


print decompress bin
<span class="output">I wanted the gold, and I sought it,
I scrabbled and mucked like a slave.
Was it famine or scurvy -- I fought it;
I hurled my youth into a grave.
I wanted the gold, and I got it --
Came out with a fortune last fall, --
Yet somehow life's not what I thought it,
And somehow the gold isn't all.</span>

Sauvegarde de vos données :

Conservez toujours une copie non compressée de vos données compressées. Si vous perdez un seul octet d'une chaîne binaire compressée, il sera difficile de récupérer les données. Ne sauvegardez pas des fichiers d'archives en format compressé à moins que vous n'ayiez des copies d'origine non compressées.

Modification de la base numérique

Pour être envoyé sous forme de texte, les chaînes binaires doivent être encodées en hexadécimal ou en base 64. Ceci est fréquemment réalisé pour le courrier électronique, ou le contenu de groupes de nouvelles (newsgroups).

La fonction enbase encodera une chaîne binaire :


line: "No! There's a land!"
print enbase line
<span class="output">Tm8hIFRoZXJlJ3MgYSBsYW5kIQ==</span>

Les chaînes encodées peuvent être décodées avec la fonction debase. Notez que le résultat est une valeur de type binaire. Pour convertir cette valeur en une chaîne de caractéres (string !), utilisez la fonction to-string.


b-line: debase e-line
print type? b-line
<span class="output">binary</span>
probe b-line
<span class="output">#^{4E6F2120546865726527732061206C616E6421^}</span>
print to-string b-line
<span class="output">No! There's a land!</span>

Le raffinement /base peut être utiisé avec les fonctions enbase et debase, pour spécifier un encode en base-2 (binaire), base-16 (hexadécimal) ou base-64.

Voici quelques exemples utilisant l'encodage en base 2 :


e2-str: enbase/base str 2
print e2-str
<span class="output">01100001</span>
b2-str: debase/base e2-str 2
print type? b2-str
<span class="output">binary</span>
probe b2-str
<span class="output">#^{61^}</span>
print to-string b2-str
<span class="output">a</span>

Quelques exemples avec un encodage en hexadécimal (base-16) :


e16-line: enbase/base line 16
print e16-line
<span class="output">4E6F2120546865726527732061206C616E6421</span>
b16-line: debase/base e16-line 16
print type? b16-line
<span class="output">binary</span>
probe b16-line
<span class="output">#^{4E6F2120546865726527732061206C616E6421^}</span>
print to-string b16-line
<span class="output">No! There's a land!</span>

Décodage hexadécimal pour Internet

La fonction dehex convertit les caractères encodés en hexadécimal des URLs Internet ou CGI en chaînes de caractères. La représentation hexadécimal ASCII se présente dans un URL ou une chaîne CGI comme %xx, où xx est une valeur hexadécimale.


str: "there%20seem%20to%20be%20no%20spaces"
print dehex str
<span class="output">there seem to be no spaces</span>
print dehex "%68%65%6C%6C%6F"
<span class="output">hello</span>

mardi 09 août 2005

There is CATCH in REBOL

The CATCH function

This function essentially enables us to immediately finish a complicated evaluation.

Sample code


catch [
; doing complicated evaluation...
if done? [throw result1]
; more evaluations...
if done? [throw result2]
; more evaluations...
; now we are done for sure
result3
]

Similar effect can be achieved using ANY, ALL or CASE functions, but in the general case CATCH is the most appropriate for the job.

When using "embedded" CATCH evaluation, we can use the CATCH/NAME refinement to be able to specify the target for the desired results as follows:


catch/name [
; ...
catch/name [
; ...
if done-a? [throw/name result 'a] ; this is meant for the 'a CATCH (the "outer" CATCH)
; ...
if done-b? [throw/name result 'b] ; this is meant for the 'b CATCH (the "inner" CATCH)
; ...
result-b
] 'b
; ...
if done-a? [throw/name result 'a]
; ...
result-a
] 'a

The [catch] function attribute

This attribute is meant to enable "above standard" error handling in functions.

Example: let's suppose we need a HANDLE function to handle every integer number except for 66. We consider it an error to call the HANDLE function with number 66 as its argument. Code:


handle: func [
[catch]
argument1 [integer!]
argument2 [block!]
] [
if argument1 = 66 [throw make error! "number 66 not allowed as argument1"]
do argument2
]

Now expression


handle 1 ["OK"]

yields "OK", while


handle 66 ["OK"]

is an error.

Comparison

the [catch] function attribute has a different purpose than the CATCH function.
there isn't a similar "mechanism" of discerning the meaning of THROW for embedded functions

Interference

An embedded [catch] - attribute function cannot discern the meaning of THROWS and it catches all throws as far as they are throwing errors. Example:


index: 1
block: copy ["OK"]
insert tail block make error! "error"
type? catch [
; ...
handle 1 [throw pick block index]
]

So far so good, but if we change the first line to


index: 2

, the interference will appear. We may ask whether the /NAME refinement could help, but the answer is negative as Romano found out.

Solution

I offered TFUNC functions to solve the throw issue (as well as some other issues) for embedded functions earlier. (see http://www.compkarori.com/vanilla/display/Function-Attributes).

The interference between [catch] and CATCH can be solved by using local throws too, but some users may find this solution uncomfortable.

A simpler solution might use /NAME refinement for THROW, but that should be extended to enable us to specify an appropriate catch name for [catch] functions too. In that case I think, that it would be great if the name comparison was using =? not just = to use the full power of Rebol.

The End

jeudi 04 août 2005

REBOL/View Graphic System Reference

Official RT documentation !
"The REBOL/View engine was designed to be powerful yet minimal. Rather than build a user interface system based on static interface elements (buttons, fields, and other "widgets"), we decided to design a system for building interface systems."
This documentation handles the inside of REBOL's graphic system.

Other format:

- page 2 de 7 -