• Aucun résultat trouvé

[PDF] Cours general des nouveautés de Lua | Cours informatique

N/A
N/A
Protected

Academic year: 2021

Partager "[PDF] Cours general des nouveautés de Lua | Cours informatique"

Copied!
14
0
0

Texte intégral

(1)

Les expressions en LUA

 Définition  Expressions arithmétiques  Expressions de comparaison  Opérateurs logiques  Opérateurs ternaires

 Les expressions conditionnelles et la valeur nil

Définition

Les expressions en LUA sont évaluées afin d'exécuter les calculs pour affecteer des valeurs aux variables ou pour passer des arguments aux fonctions.

Nous emploierons = la notation racourcie dans ce document. Les valeurs peuvent facilement être assignées à une variable, par exemple,

> x = 7 > print(x) 7 > = 7 7

Expressions arithmétiques

Lua utilise les opérateurs habituels d'arithmétique binaire. > = 2+3, 5-12, 2*7, 7/8 5 -7 14 0.875 > = 5*(2-8.3)/77.7+99.1 98.694594594595 Négation unaire : > = -(-10), -(10) 10 -10 Puissance de : > = 7^2, 107^0, 2^8 49 1 256

Expressions de comparaison

On fournit des opérateurs relationnelles qui renvoient les valeurs booléennes true ou false.

== égale à

~= pas égale à

< moins que

> plus grand que

<= inférieur ou égal à

>= supérieur ou égal à

(2)

> = 1 == 1, 1 == 0 true false > = 1 ~= 1, 1 ~= 0 false true > = 2 < 7, 2 > 7 true false > = 3 <= 7, 7 <= 7, 8 <= 7 true true false

> = 3 >= 7, 7 >= 7, 8 >= 7 false true true

Ceux-ci opérent également sur des chaînes de caractères et d'autres types. > = "abc" < "def" true > = "abc" > "def" false > = "abc" == "abc" true > = "abc" == "a".."bc" true

Les objets ne seront pas égaux si les types sont différents ou se rapportent à différents objets.

> = {} == "table" false

> = {} == {} -- two different tables are created here false

> t = {} > t2 = t

> = t == t2 -- we're referencing the same table here true

La coercition ne fonctionne pas ici, les types doivent être convertis explicitement. Voir Nombres et Chaînes pour l'explication de la coercition.

> = "10" == 10 false

> = tonumber("10") == 10 true

Opérateurs logiques

Lua dispose des opérateurs logiques and, or et not. En Lua tous nil et valeur

booléenne false représentent false (faux) dans une expression logique. Quelque chose qui n'est pas faux (l'un ou l'autre nilou false) est true (vrai). Il y a plus de notes sur les implications de ceci à la fin de cette page.

> = false==nil -- although they represent the same thing they are not equivalent false

> = true==false, true~=false false true

> = 1==0 false

> = does_this_exist -- test to see if variable "does_this_exist" exists. no, false. nil

(3)

Le mot-clé not inverse une valeur logique d'expression : > = true, false, not true, not false

true false false true

> = not nil -- nil represents false true

> = not not true -- true is not not true! true

> = not "foo" -- anything not false or nil is true false

and - (et)

L'opérateur binaire and ne renvoie pas nécessairement une valeur

booléenne true ou false à l'expression logique X et y. Dans certains languages,

l'opérateur and retourne une valeur booléenne dépendante des deux valeurs entrées. Par contre dans Lua, elle renvoie le premier argument si sa valeur est false ou nil, et le deuxième argument si le premier argument n'était pas faux. Ainsi, un booléen est seulement retourné si les valeurs passées étaient booléen.

> = false and true -- false is returned because it is the first argument false

> = nil and true -- as above nil

> = nil and false nil

> = nil and "hello", false and "hello" nil false

Toutes les expressions ci-dessus renvoient le premier argument. Toutes les expressions suivantes renvoient le deuxième argument, car le premier est vrai.

> = true and false false

> = true and true true

> = 1 and "hello", "hello" and "there" hello there

> = true and nil nil

Comme vous pouvez voir que les expressions logiques sont encore évaluées correctement mais nous avons un comportement intéressant en raison des valeurs retournées.

or - (ou)

or L'opérateur binaire également ne renvoie pas nécessairement une valeur booléenne

(voir les notes pour and ci-dessus). Si le premier argument n'est pas faux il est retourné, autrement le deuxième argument est retourné.

> = true or false true > = true or nil true > = "hello" or "there", 1 or 0 hello 1

Ceci peut être une propriété très utile. Par exemple, plaçant des valeurs par défaut dans une fonction :

(4)

> function foo(x)

>> local value = x or "default" -- if argument x is false or nil, value becomes "default" >> print(value, x)

>> end >

> foo() -- no arguments, so x is nil default nil > foo(1) 1 1 > foo(true) true true > foo("hello") hello hello

Opérateurs ternaires

Les opérateurs ternaires sont un dispositif utile dans le C. par exemple. int value = x>3 ? 1 : 0;

Ce comportement peut être partiellement émulé dans Lua en utilisant les opérateurs logiques and et or. La forme de C :

value = test ? x : y; traduit en Lua : value = test and x or y Par exemple.

> print( 3>1 and 1 or 0 ) 1

> print( 3<1 and 1 or 0 ) 0

> print( 3<1 and "True" or "False" ) False

> print( 3>1 and true or "false" ) true

Cependant, il y a une limite, ceci fonctionne seulement quand la première valeur de retour n'est pas nil ou false.

> print( 3>1 and 1 or "False" ) -- works 1

> print( 3>1 and false or "oops" ) -- failed, should return false oops

> print( 3>1 and nil or "oops" ) -- failed, should return nil oops

Les expressions conditionnelles et la valeur nil

Un point important à noter est que la valeur 0 n'est pas une condition d'essai fausse dans Lua. Dans d'autre langage, par exemple C, un test :

if (0)

printf("true"); else

(5)

montrerait "false". Dans Lua, > if 0 then >> print("true") >> else >> print("false") >> end true affiche "true".

Vous devriez employer false, ou nil au lieu de 0 : > if false then print("true") else print("false") end false

> if nil then print("true") else print("false") end false

Pourquoi ?

La raison de ceci est historique. Lua n'a pas soutenu les types booléens

(c.-à-d. true et false) avant la version 5.0. Avant la version 5.0 une valeur nil représentatit false (faux). Maintenant, tous les deux nil et false agiront en tant qu'état faux dans une expression conditionnelle. Par exemple,

> if nil then print("true") else print("false") end false

> if 1 then print("true") else print("false") end true

> if 0 then print("true") else print("false") end true

> if 1==2 then print("true") else print("false") end false

Un autre point à noter est celui true et false ne sont des valeurs numériques, par exemple, 1 et 0 comme dans d'autres languages.

> = true, false true false > = 1 + true

stdin:1: attempt to perform arithmetic on a boolean value stack traceback:

stdin:1: in main chunk [C]: ?

En outre, nil est forcé à une valeur booléenne une fois utilisé avec un opérateur logique : > = not nil true > = not 1 false > = not 0 false

(6)

 Définir des fonctions  Déclarations de fonction  Arguments

 Fonctions anonymes  Destruction de fonction

Définir des fonctions

Des fonctions peuvent être définies en utilisant le mot-clé function . Il y a deux variations dans la manière de déclarer des fonctions :

function function_name (argument) corps end

est le même que :

function_name = function( arguments ) corps end

Ce qui suit est un exemple d'une fonction simple pour doubler un nombre : > function foo(n) return n*2 end

> = foo(7) 14

Nous définissons une fonction appelée "foo" qui prend un argument simple et renvoie deux fois sa valeur. La fonction ci-dessus pourrait également avoir été écrite :

> foo = function(n) return n*2 end > = foo(4)

8

Quand nous définissons une fonction, vous pourriez dire que nous assignons un corps de fonction à une variable. Cette capacité à traiter des fonctions comme nous traiterions tout autre objet que nous pouvons affecter à une variable , implique que les fonctions

soient des valeurs de première classe. La variable à laquelle est affectée une fonction a le type fonction. Nous n'avons pas à indiquer un type complexe de fonction à la variable, comme par exemple en utilisant les pointeurs de fonction en C qui contiennent l'argument et le type de l'information de retour.

Déclarations de fonction

Dans Lua vous n'avez pas besoin de déclarer des types pour des valeurs retournées par des fonctions ou pour des arguments passés aux fonctions !

Lua est un langage avec un typage dynamique avec les objets de première classe. Ceci signifie que nous découvrons seulement si quelque chose est une fonction quand nous essayons de l'exécuter. Les languages typés statiquement (comme C) doivent connaître les types des variables lors de la compilation.

> x = "onion" > x()

stdin:1: attempt to call global `x' (a string value) stack traceback:

stdin:1: in main chunk [C]: ?

Nous ne pourrions pas appeler l'objet x parce que c'est une chaîne de caractères. Quand nous assignons la fonction foo à la variable x, nous pouvons l'appeler (comme dans l'exemple précédent).

(7)

Remarquez ci-dessous la simplicité de la déclarations de la fonction ou ne devons pas dire à Lua que foo est une fonction.

> x = foo > = x(77) 154

Nous n'avons aucun problème affecter des fonctions de différents types à la variable x puisque x n'a aucune notion du type de l'objet qu'il lui est affecté. > x = function(a,b) return a+b end

> = x(5,6) 11

> function x(a,b) return a..b end > = x('a','b')

ab

Naturellement nous devons faire attention à ne pas appeler accidentellement des variables de la même manière, car nous n'aurions pas d'erreurs explicites comme dans des

languages typés statiquement Cependant, cette fonctionnalité est très utile et nous permet d'écrire du code très flexible et très simplement.

Arguments

Puisque Lua n'a aucune déclaration de fonction il doit traiter des arguments de fonction et des valeurs de retour d'une façon flexible. Lua supporte des arguments multiples, des liste d'arguments variables et des valeurs de retour multiples. Ceci est couvert en plus détail dans Appel de Fonctions.

Fonctions anonymes

Il est parfois utile de définir des fonctions pour exécuter une tâche sans leur donner un nom en les assignant à une variable.

Nous insérerons une définition de fonction dans une modification de l'exemple ci-dessus. Nous définirons une fonction pour passer table.foreach() à ce qui pour la liste variable d'argument montre chaque clef, sa valeur et le type de l'objet de valeur :

> function foo(...) >> table.foreach(arg, function(key,value) >> print(key,value,type(value)) >> end) >> end -- foo > foo("apple",2,"banana",3.1415927,foo) 1 apple string 2 2 number 3 banana string 4 3.1415927 number

5 function: 004419E8 function n 5 number

Remarquez que la fonction n'a aucun nom : function(key,value)

print(key,value,type(value)) end

Ceci s'appelle une fonction anonyme. La fonction est définie et au lieu d'être affecté à une variable, une référence est passée comme argument table.foreach.

(8)

Destruction de fonction

Dans l'exemple suivant nous créons une fonction appelée "foo", qui comme nous pouvons voir a le type "function" :

> function foo() >> print("foo!") >> end > > foo() foo!

> = type(foo) -- what type is foo? function

Puisque foo est juste une référence à un corps de fonction nous pouvons affecter d'autres variables pour avoir la même valeur. Nous pouvons également supprimer la référence à foo pour lui affecter la valeur nil . Ceci supprime efficacement la variable foo . > bar = foo -- copy foo's reference to another variable

> foo = nil -- delete the reference to the function body > = foo

nil

> foo() -- try to invoke the function

stdin:1: attempt to call global `foo' (a nil value) stack traceback:

stdin:1: in main chunk [C]: ?

Remarque, si la variable pointe sur le corps de fonction que nous l'avons défini elle sera inaccessible, et sera supprimée (voir Garbage Collection). Dans ce cas nous avons affecté le corps de fonction à la variable bar, ainsi d'une manière nous avons renommé la fonction. Mais quand nous plaçons la variable bar à nil, il n'y a aucune autre variable pointant sur le corps de fonction, et il sera supprimé quand le garbage collector sera appelé.

> bar() -- bar still points to the same function that foo did foo!

> bar = nil -- now nothing points to the function so it can be garbage collected

Remarquez que nous n'avons pas dû indiquer les types de fonction, ni nous inquiéter de la façon dont les arguments seront passés. C'est parce que Lua est un language typé

dynamiquement où une variable peut pointer sur un objet de n'importe quel type. La variable est juste une référence à un objet et le type vient de l'objet référencé.

Instructions de sélection

tant que ... faire ... - (while..do...)

répéter ... jusqu'à... - (repeat...until...) pour ... faire... - (for...do...)

si ... alors ...ou alors ... sinon... - (If .. then ...elseif...else)

Les structures de commande de Lua seront familiers aux programmeurs. Les expressions conditionnelles mentionnées ("exp") sur cette page sont aussi abordées au

chapître Expressions. Veuillez lire préalablement la note sur les valeur nil Expressions.

Tant que ... faire ... - (while..do...)

(9)

L'expression de boucle conditionnel while a la forme :

while condition do instruction end

Elle s'interprète de la façon suivante: Tant que la condition n'est pas satisfaite exécuter l'instruction

Par exemple, une boucle simple : i = 3 > while i>0 do >> print(i) >> i = i-1 >> end 3 2 1

Nous pouvons quitter la boucle de while en utilisant le mot-clé break . Notez, dans Lua que le mot-clé break doit être le dernier mot dans un bloc, c.-à-d. que le mot-clé end doit le suivre. Vous obtiendrez des erreurs de compilation si vous n'avez pas break end. a,b = 0,1

> while true do -- infinite loop >> io.write(b, ", ")

>> a,b = b,a+b

>> if a>500 then break end -- exit the loop if the condition is true >> end

1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, >

Répéter ... jusqu'à... - (repeat...until...)

L'expression faisant une boucle conditionnel repeat a la forme :

repeat instruction until condition

Elle s'interprète de la façon suivante: Répéter l'instruction tant que la condition n'est pas satisfaite

Par exemple, une boucle simple : i = 3 > repeat >> print(i) >> i = i-1 >> until i==0 3 2 1

Comme por l'expression while nous pouvons quiiter la boucle repeat utilisant break: > i = 1

> repeat >> print(i) >> i = i+1

>> if i>3 then break end >> until cows_come_home 1

(10)

2 3

cows_come_home est une variable qui n'est pas définie. Quand nous l'accédons nous

obtenons la valeur nil, qui signifie "jusqu'à faux", ou pour toujours.

Pour ... faire... - (for...do...)

Elle s'interprète de la façon suivante: Pour les valeurs précisées faire l'instruction l'expression de réitération for a deux formes.

Le premier est pour l'itération numérique, par exemple, > for count = 1,3 do print(count) end -- numerical iteration 1

2 3

La seconde est pour l'itération séquentielle, par exemple imprimer le contenu d'une table :

> for key,value in {10, math.pi, "banana"} do print(key, value) end 1 10

2 3.1415926535898 3 banana

L'exemple ci-dessus est modifié avce une combinaison de syntaxe pour l'exemple

suivant. for est passé à une fonction d'iteration, qui est ici la fonction pairs(), dont le but il est de fournir les valeurs de chaque itération :

> for key,value in pairs({10, math.pi, "banana"}) do print(key, value) end 1 10

2 3.1415926535898 3 banana

Il y a plus de détail sur toutes les formes de for au chapître Boucle For.

Si ... alors ... ou si ... alors ... sinon... - (If .. then ...elseif...else)

l'expression if a la forme :

if condition_1 then instruction_1 { elseif condition_x then instruction_x}

[ else instruction_2 ] end

Elle s'interprète de la façon suivante: Si la condition_1 est satisfaite exécuter l'instruction_1 ou si la condition_x est satisfaite alors exécuter

l'instruction_x sinon exécuter l'instruction_2 Par exemple if ... then ... end

if 10>2 then print("bigger") end bigger

(11)

> if 1>10 then print("bigger") else print("smaller") end smaller

if ... then ... elseif ... else ... end

> number = 3 > if number < 1 then

>> value = "smaller than one" >> elseif number==1 then >> value = "one"

>> elseif number==2 then >> value = "two"

>> elseif number==3 then >> value = "three"

>> else

>> value = "bigger than three" >> end

> print(value) three

Itération avec for

 Progression numérique  Iterations o Itération de tables o Fonction pairs(table) o Fonction ipairs(table) o Fonction: io.lines() o Fonction: file:lines()

La boucle d'itération for est disponible sous deux formes. Une peut être employé pour réitérer par une progression numérique et l'autre peut être employé pour réitérer des fonctions finies appelées les iterators.

Progression numérique

La version numérique de progression de for a la syntaxe suivante :

for variable = from_expression , to_expression [, step_expression] do instruction end La boucle d'itération for positionne la valeur variable à from_exp avant d'éxécuter l'intruction. L'intruction est exécutée seulement si la variable n'a pas passé la dernière valeur de to_exp. Ceci inclut la première fois que la boucle est réitérée. Chaque fois que instruction est exécuter step_exp est ajouté à la variable. L'indication de step_exp est facultative. Si on ne l'indique pas la valeur de 1 est employée. Par exemple,

> for i = 1,3 do print(i) end -- count from 1 to 3 1

2 3

> for i = 3,1 do print(i) end -- count from 3 to 1 in steps of 1. zero iterations! > for i = 3,1,-1 do print(i) end -- count down from 3 to 1

3 2 1

> for i=1,0,-0.25 do print(i) end -- we're not limited to integers 1

0.75 0.5

(12)

0.25 0

for i = e1,e2,e3 do end est équivalent au code suivant de Lua :

do

local i, limit, step = tonumber(e1), tonumber(e2), tonumber(e3) or 1 if not (i and limit and step) then error() end

while (step>0 and i<=limit) or (step<=0 and i>=limit) do -- block code

i = i + step end

end

Iterations

La deuxième forme de la boucle for a la syntaxe : for var {, var} in explist do block end

l'explist (liste d'expressions) est évalué avant l'entrée dans la boucle. Les résultats de cette évaluation sont une fonction

iterative (qui place les valeurs de var), un état (d'ou les valeurs peuvent être lues), et une valeur initiale (d'ou part l'itération).

Itération de tables

Si nous mettions une table au lieu d'explist Lua fournira l'explist correct pour nous. Chaque élément dans une table est représenté par une paire de clef et de valeur. Lisez Table pour plus de détails au sujet de l'utilisation des tables. Pourafficher tous les éléments dans une table nous pouvons faire ce qui suit :

t = { 3,7,10,17; banana="yellow", pi=3.14159 } > for key,value in t do print(key,value) end 1 3 2 7 3 10 4 17 pi 3.14159 banana yellow Fonction: pairs(table)

Lua fournit une fonction pairs() pour créer l'information d'explist pour itèration d'une table. La fonction pairs()permettra l'itération sur les paires de clef-valeur.

for key,value in pairs(t) do print(key,value) end 1 3 2 7 3 10 4 17 pi 3.14159 banana yellow Fonction: ipairs(table)

ipairs() La fonction permettra l'itération sur des paires d'index-valeur. Ce sont des

(13)

> for index,value in ipairs(t) do print(index,value) end 1 3

2 7 3 10 4 17

Remarquez comment seulement la rangée de la table est affiché parce que seulement ces éléments ont des clefs d'index.

Fonction: next()

La fonction next(table [,index]) réalise une itèration sur une table. Avce une table et un index elle renvoie la prochaine paire de clef-valeur de la table, par exemple,

= next(t) -- index will be nil, the beginning 1 3

> = next(t,"pi") banana yellow

pairs() La fonction renvoie un explist (liste d'expressions) contenant next() ainsi nous

pouvons faire une itération sur les tables. Nous pouvons passer notre propre liste d'expression à la condition forcomme suit :

> for key,value in next,t,nil do print(key,value) end 1 3 2 7 3 10 4 17 pi 3.14159 banana yellow

Nous passons next,table,nil comme liste d'expression à la condition for . Nous disons ici que nous voulons employer la fonction d'iteration next(), sur la table appelée la "table", commençant à nil (le commencement). La condition for continue à s'exécuter jusqu'à ce que la fonction next() retourne nil (l'extrémité de la table).

Fonction: io.lines()

Lua fournit d'autres iteration utiles, comme io.lines([filename]) dans la

bibliothèque io. Nous pouvons démontrer ceci en créant un dossier fait sur commande contenant quelques lignes de texte.

io.output(io.open("my.txt","w"))

> io.write("This is\nsome sample text\nfor Lua.") > io.close()

Fonction: file:lines()

La bibliothèque io fournit une autre manière de lire les lignes de texte d'un fichier. > for line in io.lines("my.txt") do print(line) end

This is

some sample text for Lua.

(14)

> file = assert(io.open("my.txt", "r")) > for line in file:lines() do print(line) end This is

some sample text for Lua.

> file:close()

Quelles sont les différences avec io.lines()?

Vous devez explicitement ouvrir et fermez le ficheir. Un des avantage est que si le dossier ne peut pas être ouvert, vous pouvez gérer cet échec dans le code. Ici, assert a le même effet que io.lines: l'interprèteur LUA s'arrête avec un message d'erreur et pointe sur la ligne défectueuse ; mais vous pouvez tester sur la valeur nil de file et faire autre chose. Un autre avantage est que vous pouvez commencer la boucle sur n'importe quelle ligne : file = assert(io.open("list.txt", "r"))

local line = file:read()

if string.sub(line, 1, 1) ~= '#' then

ProcessLine(line) -- File doesn't start with a comment, process the first line end

-- We could also loop on the first lines, while they are comment -- Process the remainder of the file

for line in file:lines() do ProcessLine(line) end

file:close()

Iterators faits sur commande

Nous pouvons écrire nos propres iterations, similaires à next(), pour réaliser des itérations sur des séquences quelconques de données. Ceci est couvert plus en détail dans Iterations.

Références

Documents relatifs

2/ Perception et représentation de l’espace après avoir assisté à du théâtre de rue Tout d’abord, il apparaît que ces spectacles sont des occasions pour les passants

MAIN+ seeks to demonstrate the potential for process virtualization (existing or to be deployed processes) and suggests several tools to be chosen according of constraints

Cependant, ce travail repose sur un support théorique qui prend la forme d’un dictionnaire fixant un jeu de termes, et qui est issu d’une expérience menée

Dans l'univers sonore du romancier, le terrain d'union entre les personnes n'existe que pour des individus curieux d'ouïr ; mais cette curiosité est liée aux tour- ments que les

L’archive ouverte pluridisciplinaire HAL, est destinée au dépôt et à la diffusion de documents scientifiques de niveau recherche, publiés ou non, émanant des

لا ملاعلإا&#34; كرتشملا امهباتك يف ديدج ا ةسايسلاو :يهو عاونأ ةثلاث قفو ديدجلا ملاعلإا عضي &#34; ةيكيرملأ * ةميدق ايجولونكتب ديدجلا ملاعلإا :

The on-line step consists to compare the set of characters representing the 3D-object query and that of each object in the given dataset.. The experimental results obtained on the

paysage urbain : « J’interprète Barcelone dans les dernières décennies des années 2000 par la destruction caractérisée d’une bonne part de sa mémoire – cette même ville, la