Cours gratuits » Cours informatique » Cours développement web » Cours Rebol » Documentation complet pour apprendre à utiliser REBOL

Documentation complet pour apprendre à utiliser REBOL

Problème à signaler:

Télécharger



★★★★★★★★★★3.5 étoiles sur 5 basé sur 1 votes.
Votez ce document:

Documentation complet pour apprendre à utiliser REBOL

...

Rebol, un langage simple et moderne

Comme je l'ai dit en introduction, Rebol est un langage beaucoup plus facile à utiliser que les langages de bas niveau comme C ou C++ pour tout ce qui touche à la manipulation de données. Il implémente en effet des outils puissants (dont nous aurons l'occasion de reparler) pour cela, et, ce qui est pratique, permet de profiter d'une certaine abstraction pour les tâches habituellement fastidieuses : il peut par exemple gérer à votre place les allocations mémoire (dites adieu à malloc et aux pointeurs !) ou les connexions au r&eacut

e;seau (nous verrons cela au chapitre 5). Si vous faites une recherche sur le web, Rebol vous semblera peu connu, et la version actuelle, Rebol 2, est de plus en fin de vie. Tout ceci nuit un peu à l'image du langage, mais c'est dû au développement de la version 3 du langage, qui a pris beaucoup plus de temps que prévu. N'ayez craintes, la version 2 est mature et utilisable en production, pour des projets sérieux. Parmi ces projets sérieux, beaucoup concernent le web. Les créateurs de Rebol prennent très au sérieux le développement croissant du web ainsi que les technologies comme AJAX, et citent sur les pages communautaires du langage le projet Qtask, un système de gestion de projets via un site web moderne, entièrement écrit en Rebol, ou encore AltME, un logiciel de messagerie décentralisé lui aussi développé en Rebol (l'équipe de Rebol est d'ailleurs accessible via ce logiciel). Vous l'aurez donc compris, Rebol est conçu pour simplifier le développement d'applications utilisant le réseau, qu'elles soient centralisées ou non, qu'elles tournent dans un navigateur web, comme Qtask, ou non, comme AltME. Rebol intègre en effet son propre moteur d'affichage, VID, conçu pour être simple et néanmoins très souple à la fois, et qui est intégré à l'interpréteur Rebol dans un programme nommé RebView - qui tient dans moins d'un mo lui aussi (il est donc facile à déployer).

Un langage interprété

Pourquoi s'embêter à utiliser un langage interprété ?

Rebol, comme la plupart des langages de scripts, nécessite la présence sur la machine cible d'un interpréteur, qui est un programme (souvent écrit en C ou dans un langage de bas niveau) traduisant les programmes écrits dans le langage interprété? pour qu'ils soient réellement exécutables. Cela veut dire que Rebol, comme Python, Perl, PHP? sera plus lent que le C (entre autres), et qu'il nécessitera un logiciel pré-installé. C'est a priori assez gênant. Cependant, comme je l'ai dit en introduction, l'interpréteur de Rebol peut être embarqué avec vos programmes, qui eux sont livrés sous forme de fichiers source (et non de binaires), et il pèse finalement assez peu. Vous pourrez donc le fournir avec vos programmes sans que ça soit vraiment un problème. D'autre part, pour ce qui est des performances, Rebol est effectivement à la traîne. Mais ce serait problématique si vous comptiez utiliser ce langage pour faire un jeu vidéo - ce qui n'est pas le cas. Clairement, Rebol ne remplacera jamais les langages bas niveau là où ils sont utiles. En revanche, le côté interprété de Rebol a permis à ses développeurs de donner au langage une certaine flexibilité qui serait difficile à décrire pour l'instant, mais dont nous profiterons bien vite. Rebol n'est pas fait pour être rapide, il est fait pour faciliter le développement en utilisant des concepts de haut niveau. Ainsi, il introduit un concept nouveau, l'utilisation de langages spécialisés pour différentes tâches. C'est comme si vous manipuliez des objets qui comprennent chacun un langage qui ressemble à Rebol lui-même, mais avec de nouveaux mots (une espèce de jargon).

Par exemple, si vous vous adressez à un robot Lego pilotable par ordinateur, vous écrivez quelque chose comme

insert lego [motor left power 10 start] où des mots comme motor, left etc. n'ont de sens que dans ce contexte (notez le mot lego qui précède). Utilisez des dialectes se fait simplement en Rebol, grâce à ses outils comme la fonction parse - mais nous verrons tout cela plus tard . Notez que VID, l'outil d'interface graphique de Rebol, est aussi un dialecte, qui lui définit de nouveaux mots comme button ou layout.

Une archive contenant Rebol

Nous allons travailler avec la version 2.7.6 de Rebol, plus particulièrement avec une version spéciale un peu plus lourde (11 méga-octets quand même !) qui contient tous les outils pratiques pour découvrir le langage. Vous la trouverez sans problème sur cette page de téléchargement. Récupérez une archive adaptée à votre système. Dans cette archive se trouve un répertoire "tools", qui contient normalement un exécutable nommé "rebol" : c'est lui que nous utiliserons dans un premier temps, car il nous permettra de tester en ligne de commande tout ce dont nous avons besoin. Lancez-le (chez moi, double-cliquer dessus suffit). Vous aurez alors une ligne de commande, dans laquelle vous pourrez entrer des expressions Rebol pour avoir leur résultat. Par exemple, Rebol peut afficher

REBOL is a Trademark of REBOL Technologies

All rights reserved.

>> 

Les >> sont le signe que l'interpréteur attend vos commandes. Nous allons lui en donner !

Maintenant que Rebol est installé, à l'abordage !

Premiers contacts avec le langage

Nous allons découvrir Rebol et sa syntaxe (assez inhabituelle pour les débutants) à l'aide de quelques exemples d'expressions dans ce langage. Il suffit de les taper en ligne de commande et nous avons le résultat .

Des calculs

La première chose que nous pouvons faire en Rebol est de vérifier si nos opérateurs mathématiques habituels fonctionnent encore :

>> 40 + 2

== 42

>> 545 - 2342 + 12

== -1785

>> 2 * 3

== 6

>> 2 ** 16

== 65536.0

À chaque fois, Rebol nous donne le résultat sur la ligne suivante, précédé par un "==". Notez l'opérateur ** qui sert à élever un nombre à une certaine puissance. Le résultat est un nombre flottant : ils se notent comme en C, à l'aide d'un point pour la virgule. Testez l'exemple suivant : 12 + 3 * 2. Surprise ! Rebol ne gère pas la priorité des opérateurs ! En effet, et c'est peut-être un peu dommage, Rebol ne tient pas compte de règles de priorité pour les opérateurs mathématiques (ou autres) et exécute de gauche à droite tout ce qu'il trouve. Il faudra faire avec . Bien que Rebol soit faiblement typé (nous reviendrons sur ce terme), il possède une vague notion de types de données. De même qu'en C vous utilisiez des nombres de types int ou long pour les entiers, float ou double pour les flottants, ici les types Rebol sont appelés Integer! et Decimal!. Avec le point d'exclamation, oui. Si vous essayez vos propres calculs, vous écrirez peut-être à un moment une opération mathématique sans espace de chaque côté des opérateurs : Rebol vous signalera une erreur ! Les opérateurs doivent être séparés des opérandes par un espace.

Des variables

Ceci ne devrait pas trop vous dépayser : vous connaissez certainement les variables, pour les avoir déjà rencontrées dans d'autres langages. Elles servent à stocker des résultats intermédiaires, et peuvent être déclarées en ligne de commande comme les autres. Regardez ces exemples pour comprendre quelle est la syntaxe :

>> a: 42

== 42

>> foo-bar: a

== 42

>> a + foo-bar

== 84

>> c: d: e: 14

== 14

>> a + (z: 32)

== 74

Il faut donc utiliser deux points pour définir une variable (et pas de caractère étrange pour en utiliser une). Des notations assez riches sont autorisées, par exemple foobar qui ne sera pas compris comme étant une soustraction (cf. fin de la partie précédente ) mais comme un nom. Notez qu'une définition de variable renvoie la valeur stockée, d'où l'exemple de la dernière ligne. Suivant l'ordre des parenthèses, z est défini à 32, puis la valeur 32 est renvoyée, et l'opération est effectuée. Je ne vous conseille pas d'abuser de cette possibilité, ça ne facilite en rien la lecture du code.

Profitons-en pour découvrir quelques fonctions (ici encore, vous connaissez le concept). Commençons par la fonction print : elle affiche ce que vous lui donnez en argument, et finit par un retour à la ligne.

>> print "Bonjour les zéros !"

Bonjour les zéros !

Ici, pas de symbole "==" : ça n'est pas une valeur de retour que Rebol nous a affichée, mais bien du texte imprimé sur l'écran par la commande print. Il existe aussi une fonction prin qui se comporte comme print mais sans retour à la ligne. Dans certains langages (comme Python avant la version 3), l'instruction print permet d'afficher plusieurs éléments à la suite si on les sépare par des virgules. Par exemple on pourrait avoir en Python

>> print "a vaut", a, "!" a vaut 42 !

Pour faire ceci en Rebol, pas besoin d'utiliser une syntaxe spéciale : il suffit d'utiliser un type de données que nous aborderons plus tard, les blocs. Les blocs contiennent plusieurs éléments, séparés par des espaces, entre des crochets. Ils permettent par exemple d'écrire print ["a vaut" a "!"] pour avoir un résultat équivalent au précédent .

Des mots

Voici un concept important, sur lequel nous devrons pourtant nous montrer brefs pour l'instant : Rebol sait manipuler des objets d'un type étrange, les mots. Ce sont des expressions a priori anodines, et elles pourraient vous rappeler les chaînes de caractères. Grossière erreur ! Les mots sont plus que ça. Contrairement aux blocs et aux valeurs littérales comme les chaînes de caractères ou les nombres, ils n'ont de valeur que quand vous les définissez. Par exemple, avant d'être une fonction, print est un mot? qui a été défini pour être la fonction print que nous connaissons. Un peu tordu non ? Les mots sont un nom avant d'être une valeur. Cela veut dire qu'on peut les manipuler en tant que tels, en faisant précéder ce nom par un ' (apostrophe). Par exemple, il est correct d'écrire

>> variable: 'print

== print

>> print variable

== print

La variable variable contient le mot print. Nous aurions pu écrire print 'print. Ici, le mot print apparaît deux fois, mais la deuxième fois (avec l'apostrophe) il a un sens littéral, tandis que la première fois, il est évalué comme étant une fonction. C'est simple : précéder un mot d'une apostrophe empêche son évaluation. Nous verrons plus tard à quoi cela peut servir. Il y a une autre opération que l'on peut faire sur les mots, qui empêche leur évaluation mais ne donne pas pour autant leur sens littéral. En ajoutant : avant leur nom, on permet de copier ces mots sans les évaluer, mais sans se contenter de stocker leur nom pour autant. Petit exemple :

>> foo: 'print

== print

>> bar: rint

>> baz: print

** Script Error: print is missing its value argument

** Near: baz: print

>> foo 3

== 3

>> bar 3

3

Nous tentons de définir trois variables. L'une d'elle contient le mot littéral print. L'autre copie la fonction print. La dernière? ne sera pas définie, car la syntaxe est incorrecte. En effet, quand nous écrivons baz: print, Rebol croit que nous souhaitons stocker dans baz le résultat qui se trouve à droite des deux points, or print tout seul n'est pas une opération correcte (l'erreur nous le dit : il manque des arguments). Ensuite, nous utilisons nos deux variables en tentant de passer 3 en argument. Dans le premier cas, on pourrait croire que cela réussit, mais non : rappelez-vous de ce que je vous ai dit ! Si c'était print qui affichait un résultat à l'écran, il n'y aurait pas de "==" placé avant le 3 . Rebol se contente donc d'évaluer la dernière expression et de la renvoyer. En revanche, dans le deuxième cas, la variable bar agit comme print, et affiche son argument à l'écran. Pour l'instant, les mots vous semblent probablement inutiles. Nous verrons cependant qu'ils permettent de définir au sein de Rebol des micro-langages adaptés en fonction du contexte, et qu'ils autorisent une grande souplesse dans la syntaxe du langage. Contrairement au C (et à la grande majorité des langages) où il existe des mots réservés, Rebol vous autorise par exemple? à redéfinir le mot if, dont nous verrons au chapitre suivant qu'il a pourtant le même sens qu'en C, à savoir de permettre les instructions conditionnelles. Mais l'intérêt de ceci est également encore assez flou pour vous, je le sens bien . N'ayez pas peur de Rebol. Je vous ai présenté les mots pour vous déstabiliser un petit peu, mais maintenant que c'est fait plus rien de compliqué ne nous attend .

Les blocs

Rebol, en tant que langage dynamique, vous permet de manipuler des blocs de code qui peuvent être exécutés quand bon vous semble. Mais ces blocs sont aussi la principale structure de données, et pourront également vous servir à contenir des données diverses.

Les blocs sont des conteneurs

Construire des blocs

Nous en avons un tout petit peu parlé précédemment. Les blocs servent à contenir des objets Rebol comme des chaînes, des nombres ou autres (pourquoi pas d'autres blocs ?), tous rangés dans un certain ordre. On écrit le bloc avec des crochets, en séparant les objets par un espace. Par exemple foo: [1 2 3 4] stocke un bloc contenant ces 4 chiffres dans la variable foo. Il existe plusieurs fonctions pour manipuler les blocs, dont les plus simples sont empty?et length?. La première fonction renvoie true quand son argument est un bloc vide, la seconde renvoie la longueur de son argument quand c'est un bloc :

>> empty? []

== true

>> empty? [foo]

== false

>> length? foo ; notre variable foo: [1 2 3 4]

== 4

>> length? [a b [foo bar]] ; Notez que le mot bar n'a pas besoin d

'être défini ; nous y reviendrons.

== 3

Naturellement, il nous faut aussi des fonctions pour construire des blocs (qui seront par exemple utilisées dans des boucles ou des fonctions comme nous le verrons prochainement). La fonction la plus élémentaire pour ça est la fonction append. Elle prend en argument un bloc et une valeur à ajouter. Par exemple :

>> append [1 2 3] 4

== [1 2 3 4]

Cependant, observez l'exemple suivant :

>> append [1 2 3] [unbloc]

== [1 2 3 unbloc]

Voici un comportement singulier. Quand nous utilisons append sur deux blocs, la fonction ajoute le contenu du deuxième au premier. Mais si nous voulions ajouter le bloc [unbloc] comme élément du premier ?

Il faut utiliser ce que l'on appelle un raffinement. Les raffinements sont des options que l'on peut passer à certaines fonctions. Ici, append peut recevoir le raffinement /only, ce qui donne

>> append/only [1 2 3] [unbloc]

== [1 2 3 [unbloc]]

Bien sûr dans les cas précédents, append continue d'avoir le même comportement.

Nous utiliserons cette particularité lorsque nous voudrons construire des blocs de blocs.

Cela ne s'est pas vu ici, mais la fonction append modifie les blocs sur lesquels elle travaille. En d'autres termes, si nous écrivons append unbloc unevaleur, le bloc unbloc est modifié, append ne se contente pas de renvoyer le résultat.

Altérer des blocs déjà existant

Une autre fonction intéressante est insert. Cette fonction prend en argument un bloc et une valeur et modifie ce bloc pour insérer le résultat au début. Voici des exemples :

>> insert [1 2 3] 0

== [1 2 3]

>> foo: [1 2 3]

== [1 2 3]

>> insert foo 0

== [1 2 3]

>> print foo

0 1 2 3

Il est important que vous compreniez qu'ici, ce qui compte ça n'est pas le résultat de insert, qu'on pourrait à la limite ignorer. Ce qui compte, c'est la modification que cette fonction réalise sur le bloc.

Pour modifier une valeur dans un bloc, utilisez replace bloc valeur1 valeur2.

Pour supprimer une valeur, utilisez remove bloc (supprime l'élément en tête). Un petit exemple vaut mieux qu'un long discours :

>> foo: [1 1 3 1 1]

== [1 1 3 1 1]

>> replace foo 1 2

== [2 1 3 1 1]

>> replace/all foo 1 2

== [2 2 3 2 2]

>> foo

== [2 2 3 2 2]

>> remove foo

== [2 3 2 2]

>> foo

== [2 3 2 2]

>> remove/part foo length? foo

== []

Notez le raffinement replace/all qui remplacera les valeurs dans le bloc entier (sans ce raffinement seule la première valeur qui correspond à ce que l'on cherche est remplacée). Notez également le raffinement remove/part qui ajoute un argument : le nombre d'éléments à supprimer. Ici, on passe en argument length? foo soit le nombre d'éléments total contenu dans le bloc.

Une question d'index

Les blocs sont particulièrement importants en Rebol. Si vous connaissez le langage Lisp, ils ont autant d'importance que les listes dans ce langage. Toutefois, les blocs Rebol possèdent une caractéristique importante que les listes n'ont pas : ils contiennent un index interne, qui sert à faire des opérations. C'est une notion qui se révèlera utile, comme toutes les autres, mais qui est pleine de pièges. On peut voir cet index comme une sorte de curseur qui indique où l'on est en train de travailler, sans pour autant détruire le bloc. En quelques sortes, on "cache" une partie du bloc pour faire des opérations sur le reste. Cependant, on peut récupérer à tout moment le bloc original, en profitant des modifications qui on été réalisées. La seule fonction que nous présenterons pour l'instant est next, qui permet d'avancer d'un cran le curseur dans un bloc. Il en existe d'autres comme back et skip, au sujet desquelles je vous invite à vous renseigner, en tapant help back dans la ligne de commande Rebol par exemple.

La fonction next va en fait renvoyer le bloc privé de son premier élément (sauf si le bloc est vide bien sûr), et il faut alors le stocker dans une variable (éventuellement la même) ou réaliser des opérations directement dessus. Par exemple :

>> foo: [1 2 3 4 5]

== [1 2 3 4 5]

>> foo: next next foo

== [3 4 5]

>> foo

== [3 4 5]

À ce stade on dirait que foo a été modifiée de façon irréversible? On peut stocker une nouvelle valeur dans cette "nouvelle" variable foo, par exemple :

>> insert foo 0

== [3 4 5]

>> foo

== [0 3 4 5]

Mais, à l'aide de la fonction head, nous pouvons alors afficher le bloc depuis le début (ce qui ne déplace pas le curseur, cela produit juste un affichage) :

>> head foo

== [1 2 0 3 4 5]

Surprise ! Ni le 1 ni le 2 n'ont été perdus, ils étaient simplement mis de côté pendant que nous travaillions plus loin dans le bloc? Nous reviendrons sur les index lorsque nous utiliserons des boucles pour modifier des blocs de données.

Des blocs de code

Outre le fait qu'ils contiennent des données, les blocs en Rebol servent surtout à contenir? du code ! Rebol permet en effet de manipuler du code, et d'utiliser certaines fonctions sur les blocs pour exécuter ce code dans un contexte particulier. Si vous n'avez utilisé pour le moment que des langages de bas niveau, cela peut vous sembler étrange et contre nature. Pourtant, cela peut se montrer très utile. On a alors la possibilité d'écrire des fonctions (dites "d'ordre supérieur") qui manipulent ce code pour le faire s'exécuter dans des contextes particuliers. Imaginons que vous commandiez un robot : vous pourrez alors définir une fonction d'évaluation des commandes du robot qui reconnaît, en plus des mots habituels, des instructions pour que le robot avance, recule, tourne? Vous écririez par exemple

robot [

 avance 5

 tourne 90

 avance 10

]

et le sens de ces instructions serait compris par la fonction robot. Plus intéressant encore, puisque ce qui se trouve entre les blocs n'est pas directement évalué, vous pouvez utiliser des langages spécialisés dont vous pouvez contrôler la syntaxe. Cependant, toute ce côté "conception de micro-langages" (on les appelle "dialectes") ne nous intéressera que plus tard. Pour l'instant, étudions un peu comment Rebol stocke les blocs de code, et quelles opérations nous pouvons effectuer dessus.

Évalutation retardée

Le gros avantage de ces blocs est, comme je l'ai dit, d'attendre sagement qu'on les évalue. Nous pouvons stocker dans un bloc un code qui afficherait du texte à l'écran, en faisant a: [print "Bonjour les Zéros !"], mais ce code n'est pas évalué (rien n'est pour l'instant affiché à l'écran), puisque pour cela il faut une fonction adaptée.


55