Contacts

Présentation de Lua. Vous voulez tout savoir. Lua Language Apprendre le lua à partir de zéro

Un de mes amis proches s'est récemment rendu à un entretien d'embauche avec une entreprise locale de développement de jeux. Je ne vais pas citer de noms ici, juste dire que c'était une sorte de grande boutique de développement de jeux à Vancouver. Il n'a pas trouvé de travail, mais aujourd'hui, on ne parle pas de lui. Personnellement, je pense que l'une des raisons était son manque de relations amicales avec le langage de script qu'ils utilisent.

introduction

Je suis dans ce domaine car j'enseigne la programmation de jeux aux étudiants, mais c'est le sujet auquel je n'ai pas suffisamment prêté attention par le passé. Nous couvrons Unreal Script dans le cadre du cours Utilisation de l'existant. Mais nous n'avons pas réellement considéré le moteur de script comme faisant partie des utilitaires ou du moteur. Alors, armé d'un site internet, j'ai décidé de briser cette petite barrière. Le résultat est décrit dans ce document.

La seule chose, je ne suis pas sûr de la taille de ce document. Je peux le décomposer en plusieurs petites parties ou le publier dans son intégralité dans une longue tirade du début à la fin. Quoi qu'il en soit, je déciderai cela un peu plus tard, lorsque je mettrai mes notes dans un format plus significatif et cohérent.

Pourquoi et pourquoi pas ?

Tout d'abord, pourquoi utiliser un langage de script ? La majeure partie de la logique du jeu peut être écrite dans un langage de script à diverses fins, plutôt que d'être programmée dans le cadre du moteur de jeu. Par exemple, le chargement ou l'initialisation d'un niveau. Après avoir chargé le niveau, vous voudrez peut-être traduire la scène dans le plan de jeu, ou vous voudrez peut-être afficher un texte préliminaire. À l'aide d'un système de script, vous pouvez faire en sorte que certains objets du jeu effectuent des tâches spécifiques. Pensez également à mettre en œuvre l’intelligence artificielle. Les personnages non-joueurs doivent savoir quoi faire. Programmer chaque PNJ « manuellement » dans le corps du moteur de jeu compliquera inutilement la tâche. Lorsque vous souhaitez modifier le comportement d'un PNJ, vous devrez recompiler votre projet. Avec un système de script, vous pouvez le faire de manière interactive en modifiant le comportement et en enregistrant les paramètres.

J'ai abordé un peu ce problème dans le dernier paragraphe, nous en reparlerons un peu plus tard. La question est, pourquoi ne pas écrire de la logique exclusivement en C/C++ ? Pour faire simple, qu'à terme le programmeur a le fait que tout lui tombe directement et qu'il part, respectivement, du code du jeu, en même temps il devra écrire un moteur et des utilitaires, etc. Mais nous pouvons maintenant transférer certaines des tâches de fonctionnalité aux concepteurs de niveaux avec un langage de script simple. Ils peuvent commencer à bricoler le niveau et à optimiser le gameplay. Voici un exemple :

Imaginons que Joe, notre malheureux programmeur, écrive lui-même l'intégralité du moteur de jeu, des outils et de la logique du jeu. Oui, Joe va avoir des ennuis, mais supposons qu'il s'en fiche. Nous avons aussi Brandon, le game designer. Brandon est un enfant assez intelligent avec de bonnes idées pour le jeu. Et donc notre codeur Joe rampe et implémente toute la logique du jeu en utilisant la boîte à outils qu'il a développée sur la base du projet initial de Brandon. Tout va bien au bureau. La première phase est terminée, et Joe et Brandon sont assis dans la salle du conseil et passent en revue leur travail considérable. Brandon remarque plusieurs problèmes avec le gameplay, qui ne se comporte pas correctement. Joe revient donc au code et apporte les modifications nécessaires. Ce processus peut prendre une journée, du moins s'il ne s'agit pas d'un changement trivial. Puis un autre jour pour recompiler le projet. Afin de ne pas perdre une journée supplémentaire, la plupart des bureaux laissent le processus d'assemblage pendant la nuit. Donc, comme on peut le voir, il faut 24 heures avant que Brandon ne voie le changement qu'il a demandé.

Maintenant, supposons que notre protagoniste Joe décide que la mise en œuvre de la logique du jeu utilise le moteur de script à son avantage. Cela prendra du temps au début, mais il pense que cela profitera à long terme. Et ainsi, il déplace certaines fonctionnalités du moteur de jeu vers le système de script du jeu. Il écrit également toute la logique du jeu dans le système de script mentionné précédemment. Et ainsi, lorsqu'il rencontre Brandon et que le concepteur remarque quelque chose qui ne correspond pas à son idée, Joe ouvre rapidement la console, apporte quelques modifications au script, redémarre le jeu et voit déjà le nouveau comportement. Les modifications peuvent être effectuées immédiatement et affichées immédiatement, au lieu d'attendre la recompilation. Et si Joe était particulièrement expressif, le système de script pourrait être utilisé pour les utilitaires et disponible pour les concepteurs de niveaux lors de la création de niveaux. Si vous suivez ce chemin, alors avec un peu de formation, les concepteurs de niveaux pourraient définir eux-mêmes des événements de jeu, tels que des déclencheurs, des portes, d'autres événements de jeu et profiter de la vie sans fatiguer le programmeur.

C'est un exemple plutôt artificiel et peut-être un peu exagéré, mais j'espère qu'il montre la différence entre les approches. Alors ce que nous essayons de faire avec ce modèle, c'est-à-dire évoluer vers des données gérées de manière plus automatique. Alors, en gros, où allons-nous:

  1. Le codeur s'intéresse à l'écriture du code du moteur/des outils, pas de la logique du jeu.
  2. Du temps a été consacré à l'écriture du moteur/des outils du jeu.
  3. Les concepteurs aiment jouer avec les choses. Les scripts leur donnent la liberté de concevoir des niveaux et des fonctionnalités. Cela leur donne également plus de flexibilité pour expérimenter des choses pour lesquelles ils impliqueraient normalement un programmeur.
  4. Vous n'avez pas besoin de recompiler si vous souhaitez modifier les fonctionnalités du jeu. Changez simplement le script.
  5. Vous voulez rompre la connexion entre la machine et le code du jeu. Ils doivent être en deux parties distinctes. De cette façon, il sera pratique d'utiliser le moteur pour les futures suites (j'espère).

Je vais faire quelques prédictions ici. Au cours des 5 prochaines années, les concepteurs de niveaux devront faire plus que simplement construire des niveaux. Ils doivent être capables d'utiliser le script pour les scènes de jeu. Plusieurs entreprises de pointe ont déjà adopté cette approche. En outre, vous pouvez voir cette méthode d'intégration dans des éditeurs comme UnrealEd et Aurora toolset Bioware.

Clarification et délire

J'espère que maintenant vous avez déjà accepté mes paroles et que vous vouliez inclure un composant de script dans votre jeu. Alors la question suivante est : comment diable faites-vous cela ?

Ce que je vais utiliser pour mon composant de script est un moteur de script injectable Lua... Au début, je dirai que je ne suis pas un expert en Lua, mais c'est une langue relativement simple et ne nécessite pas d'apprentissage fastidieux pour la maîtriser. Certains des exemples que je reviendrai plus tard sont assez simples. À la fin de ce document, je vais inclure des documents de référence supplémentaires. Pour être juste, il existe d'autres langages de script comme Small, Simkin, Python, Perl. Cependant, Lua est une langue agréable et propre. C'est un très bon avantage.

Lua est open source. C'est bien parce que : (a) vous obtenez la source de la langue et vous pouvez creuser autant que vous le souhaitez, (b) c'est gratuit. Vous pouvez l'utiliser dans des applications commerciales sans dépenser d'argent. Eh bien, pour les projets non commerciaux, vous comprenez vous-même gratuitement == bien.

Alors, qui utilise actuellement Lua ? Lua est écrit par un bureau de la sharashka et n'est utilisé que par les pauvres ? Mmm... pas vraiment. Lua n'est pas apparue hier et a été utilisée par des personnalités connues :

  • Lucasarts
    • Fandango sinistre
    • Évadez-vous de l'île aux singes
  • Bioware
    • Nuits d'hiver

Ok, assez avec le who-is-who des développeurs lua. Vous pouvez le constater par vous-même sur le site Web de lua.

Commençons très simplement. La première chose que nous devons construire nous montrera comment l'interpréteur lua est utilisé. Ce qui est requis pour cela :

  1. Obtenir le code interpréteur Lua.
  2. Configuration de votre environnement de développement.
  3. Construire l'interprète à partir de zéro.

Hé, je pensais que tu avais dit assez de discours ?

Est-ce suffisant? Passons donc aux choses sérieuses. Vous pouvez obtenir tout le code source de Lua sur le site officiel. Je voudrais également prendre une seconde et souligner qu'une nouvelle version de Lua 5.0 se profile à l'horizon. Je ne vais pas discuter de cette version dans cet article. Je m'en occupe plus tard, mais pour l'instant, nous utiliserons la 4.0.1.

La première chose que nous allons faire est de construire la bibliothèque lua. Ainsi, nous n'avons pas besoin d'inclure les sources à chaque fois que nous construisons le projet. Ce n'est pas difficile et ce n'est pas le but de nos cours. Par conséquent, j'ai inclus la bibliothèque à l'avance dans le cadre de cet article. J'ai utilisé une bibliothèque statique pour cet exemple. Oui, je l'aurais peut-être construit en tant que DLL, mais pour un système de script, une bibliothèque statique est un peu plus rapide. Remarquez, pas grand-chose, mais plus rapide.

Notre invité d'aujourd'hui est un vrai combattant du front caché. Vous l'avez peut-être vu dans des jeux (World of Warcraft, Angry Birds, X-Plane, S.T.A.L.K.E.R.) ou des produits Adobe (Lightroom), mais vous n'avez même jamais pensé à son existence. En attendant, cette langue a déjà presque 25 ans, et pendant tout ce temps, elle a imperceptiblement amélioré un peu notre vie virtuelle.

Référence rapide

Lua aurait été inventé en 1993 par l'Université catholique de Rio de Janeiro. Le nom est traduit du portugais par Luna, et les créateurs demandent de manière convaincante de ne pas écrire LUA, afin que, Dieu nous en préserve, quelqu'un ne prenne pas le nom pour une abréviation. Il s'agit d'un langage de script multi-paradigmes utilisant le modèle prototype POO.

La saisie est dynamique ici et les métatables sont utilisées pour implémenter l'héritage, c'est-à-dire qu'il s'agit d'un excellent outil pour étendre les capacités de votre produit. De plus, en raison de sa compacité, il convient à une utilisation sur presque toutes les plates-formes. Jugez par vous-même : tarball Lua 5.3.4 ne pèse que 296 kilo-octets (non compressé - 1,1 mégaoctet), l'interpréteur (écrit en C) pour Linux - de 182 à 246 kilo-octets, et l'ensemble standard de bibliothèques - 421 kilo-octets supplémentaires.

Le code

En apparence et en capacités, Lua ressemble à une autre tentative de refonte de JavaScript, si ce n'est du fait que ce dernier est apparu deux ans plus tard. Voir par vous-même:

Commençons par le traditionnel :

imprimer ("Bonjour le monde")

D'accord, familier et pas trop informatif. Un exemple plus intéressant du point de vue de la familiarité avec Lua est le calcul de la factorielle d'un nombre entré :

Fait de fonction (n)
si n == 0 alors
retour 1
autre
retourner n * fait (n-1)
finir
finir

Imprimer ("entrez un nombre :")
a = io.read ("* nombre") - lit un nombre
imprimer (fait (a))

Tout est très clair. Soit dit en passant, Lua prend en charge l'affectation parallèle :

Et enfin, un exemple assez simple utilisant des librairies :

#inclure
#inclure
#inclure
#inclure
#inclure

Int principal (vide) (
buff omble;
Dans la terreur;
lua_State * L = lua_open (); / * ouvre Lua * /
luaopen_base (L); / * ouvre la bibliothèque de base * /
luaopen_table (L); / * ouvre la bibliothèque de tables * /
luaopen_io (L); / * ouvre la bibliothèque I/O * /
luaopen_string (L); / * ouvre la chaîne lib. * /
luaopen_math (L); / * ouvre la bibliothèque mathématique. * /

Tant que (fgets (buff, sizeof (buff), stdin)! = NULL) (
error = luaL_loadbuffer (L, buff, strlen (buff), "ligne") ||
lua_pcall (L, 0, 0, 0);
si (erreur) (
fprintf (stderr, "% s", lua_tostring (L, -1));
lua_pop (L, 1); / * pop message d'erreur de la pile * /
}
}

Lua_close (L);
renvoie 0 ;
}

Avantages et inconvénients

Alors qu'est-ce qu'il y a de bien avec Lua ?

Tout d'abord, comme déjà noté, par sa compacité, et couplé au fait que le code source est écrit en C, vous obtenez une interaction complète avec l'un des langages les plus populaires de la planète et un large éventail de plates-formes disponibles.

Environnements de développement

LDT (Lua Development Tools) pour Eclipse - une extension pour l'un des IDE les plus populaires ;

ZeroBrane Studio est un environnement spécialisé écrit en Lua ;

Decoda n'est pas l'IDE multiplateforme le plus populaire, mais il fonctionnera comme une alternative.

SciTE est un bon éditeur avec une prise en charge complète de Lua ;

WoWUIDesigner - devinez quel jeu cet environnement aide à traiter les scripts, y compris Lua ?

Liens utiles

http://www.lua.org/home.html - le site officiel avec toutes les informations nécessaires, tutoriel, livres, documentation, et même un peu d'humour spécifique ;

http://tylerneylon.com/a/learn-lua/ est un excellent tutoriel de Tyler Neylon. Convient aux programmeurs expérimentés qui connaissent bien l'anglais (cependant, il n'y aura pas non plus de gros problèmes avec le dictionnaire) et qui souhaitent simplement élargir leurs horizons ;

https://zserge.wordpress.com/2012/02/23/lua-for-60-minutes/ - Les bases de Lua en 60 minutes par un programmeur qui n'est visiblement pas indifférent à ce langage. En russe;

http://lua-users.org/wiki/LuaTutorial - tutoriel wiki

https://youtube.com/watch?v=yI41OL0-DWM- des didacticiels vidéo sur YouTube qui vous aideront à comprendre visuellement la configuration de l'IDE et les principes de base du langage.

Scripts Lua

Un script écrit en Lua n'a pas de fonction spéciale à partir de laquelle démarrer son exécution. Un script peut être considéré simplement comme un ensemble de commandes (instructions) exécutées à partir de la première instruction.

Un script peut être soit très simple, composé d'une seule commande, soit très complexe, contenant des dizaines, des centaines ou même des milliers d'instructions. Les instructions consécutives peuvent être séparées par des points-virgules (;). Cependant, cette exigence est facultative, donc tout le code ci-dessous est syntaxiquement correct :

Travailler avec des variables dans Lua

Les variables sont utilisées pour stocker des valeurs lors de l'exécution du script.

Noms de variables en Lua

Les noms de variables (identifiants) en Lua peuvent être n'importe quelle séquence de lettres, de chiffres et de traits de soulignement qui ne commencent pas par un chiffre.

Remarque

Lua est sensible à la casse, donc abc, Abc, ABC sont des noms différents.

Le tableau ci-dessous montre les mots qui sont réservés par le langage Lua et ne peuvent pas être utilisés dans les noms de variables :

et casser faire d'autre sinon

fin faux pour la fonction si

en local nil pas ou

répéter return puis vrai jusqu'à ce que

De plus, tous les noms commençant par un trait de soulignement suivi de lettres majuscules (par exemple, _VERSION) sont également réservés.

Quelles variables y a-t-il dans Lua ?

Les variables dans Lua peuvent être globales ou locales. Si une variable n'est pas explicitement déclarée comme locale, elle est considérée comme globale.

Variables globales Lua

La variable globale apparaît lorsque la première valeur lui est affectée. Avant que la première valeur ne soit affectée, l'appel à la variable globale renvoie nil.

MsgBox (tostring (g)) -> nil

MsgBox (tostring (g)) -> 1

Une variable globale existe tant que l'environnement d'exécution du script existe et est disponible pour tout code Lua exécuté dans cet environnement.

Si nécessaire, vous pouvez supprimer explicitement une variable globale en lui affectant simplement une valeur nulle.

g = 1 - crée une variable globale g avec la valeur 1

g = nil - supprime la variable globale g

MsgBox (tostring (g)) -> nil

Toutes les variables globales sont des champs d'une table régulière appelée environnement global. Cette table est accessible via la variable globale _G. Puisque les champs de l'environnement global sont tous des variables globales (y compris _G lui-même), alors _G._G == _G.

Variables locales Lua

Toute variable locale doit être déclarée explicitement à l'aide du mot-clé local. Vous pouvez déclarer une variable locale n'importe où dans le script. La déclaration peut inclure l'attribution d'une valeur initiale à la variable. Si aucune valeur n'est affectée, la variable contient nil.

local a - déclare une variable locale a

local b = 1 - déclarer une variable locale b, lui affecter la valeur 1

local c, d = 2, 3 - déclarer les variables locales c et d, leur attribuer les valeurs 2 et 3

La portée d'une variable locale commence après la déclaration et se poursuit jusqu'à la fin du bloc.

Noter

La portée d'une variable est un morceau de code de programme dans lequel vous pouvez accéder à la valeur stockée dans une variable donnée.

Un bloc signifie :

le corps de la structure de contrôle (si-alors, sinon, pour, tandis que, répéter) ;

corps de fonction;

un morceau de code inclus dans les mots-clés do ... end.

Si une variable locale est définie en dehors de tout bloc, sa portée s'étend jusqu'à la fin du script.

local i = 1 - la variable i est locale dans le script

alors que je<= a do - цикл от 1 до 5

local a = i ^ 2 - la variable a est locale à l'intérieur de la boucle while

MsgBox (a) -> 1, 4, 9, 16, 25

MsgBox (a) ->

si je> 5 alors

local a - la variable a est locale à l'intérieur de then

MsgBox (a) -> 10

MsgBox (a) -> 5 (ici référence au global a)

local a = 20 - la variable a est locale à l'intérieur du do-end

MsgBox (a) -> 20

MsgBox (a) -> 5 (ici référence au global a)

Remarque

Dans la mesure du possible, il est recommandé d'utiliser des variables locales au lieu de variables globales. Cela évitera d'"encombrer" l'espace de noms global et offrira de meilleures performances (puisque l'accès aux variables locales dans Lua est un peu plus rapide que les variables globales).

Types de données Lua

Quels types de données Lua prend-il en charge ?

Lua prend en charge les types de données suivants :

1. Néant (rien). Correspond au fait qu'une variable n'a pas de valeur. Ce type est représenté par une valeur unique, nil.

2. Booléen (logique). Ce type comprend les valeurs false et true.

Lors de l'exécution d'opérations logiques, nil est considéré comme faux. Toutes les autres valeurs, y compris le nombre 0 et la chaîne vide, sont considérées comme vraies.

3. Numéro (numérique). Sert à représenter des valeurs numériques.

Les constantes numériques peuvent contenir une partie fractionnaire facultative et un ordre décimal facultatif, spécifiés par les caractères "e" ou "E". Les constantes numériques entières peuvent être spécifiées en hexadécimal à l'aide du préfixe 0x.

Exemples de constantes numériques valides : 3, 3.0, 3.1415926, 314.16e-2, 0xff.

4. Chaîne (chaîne). Sert à représenter des chaînes.

Les valeurs de chaîne sont spécifiées sous la forme d'une séquence de caractères, entre guillemets simples ou doubles :

a = "ceci est une chaîne"

b = "c'est la deuxième ligne"

Les chaînes entre guillemets peuvent interpréter des séquences d'échappement de type C (séquences d'échappement) qui commencent par le caractère "\" (barre oblique inverse) :

\ b (espace),

\ n (saut de ligne),

\ r (retour chariot);

\ t (onglet horizontal),

\\ (barre oblique inverse);

\ "" (double citation);

\ "(simple citation).

Remarque

Un caractère dans une chaîne peut également être représenté par son propre code à l'aide d'une séquence d'échappement :

où ddd est une séquence de trois chiffres maximum.

En plus des guillemets, des crochets doubles peuvent également être utilisés pour définir une chaîne :

La définition d'une chaîne avec des crochets doubles permet d'ignorer toutes les séquences d'échappement, c'est-à-dire que la chaîne est créée exactement comme décrit :

local a = [] en Lua] =]

Il y aura un terme : "définition de la chaîne [] en Lua"

5. Fonction. Les fonctions de Lua peuvent être écrites dans des variables, transmises en tant que paramètres à d'autres fonctions et renvoyées à la suite de l'exécution de fonctions.

6. Tableau. Une table est un ensemble de paires clé-valeur, appelées champs ou éléments de table. Les clés et les valeurs des champs de la table peuvent être de tout type sauf nil. Les tableaux n'ont pas de taille fixe : vous pouvez leur ajouter un nombre arbitraire d'éléments à tout moment.

Plus de détails - dans l'article "Créer des tables en Lua"

7. Données utilisateur (données utilisateur). C'est un type de données spécial. Les valeurs de ce type ne peuvent pas être créées ou modifiées directement dans un script Lua.

Userdata est utilisé pour représenter de nouveaux types créés dans le programme d'appel de script ou dans des bibliothèques écrites en C. Par exemple, les bibliothèques d'extension Lua pour "CronosPRO" utilisent ce type pour représenter des objets tels que :

banques de données (classe Banque) ;

bases de données (classe de base);

records (classe Record), etc.

8. Enfiler (fil). Correspond au flux d'exécution. Ces flux ne sont liés d'aucune manière au système d'exploitation et sont pris en charge exclusivement par Lua lui-même.

Comment définir le type d'une variable dans Lua ?

Lua ne définit pas explicitement le type d'une variable. Le type d'une variable est défini au moment où une valeur est affectée à la variable. N'importe quelle variable peut se voir affecter une valeur de n'importe quel type (quel que soit le type de valeur qu'elle contenait auparavant).

a = 123 - la variable a est de type numéro

a = "123" - maintenant la variable a est de type chaîne

a = vrai - maintenant la variable a est de type booléen

a = () - maintenant la variable a est de type table

Remarque

Les variables de type table, fonction, thread et userdata ne contiennent pas les données elles-mêmes, mais stockent des références aux objets correspondants. Lors de l'affectation, du passage à une fonction en tant qu'argument et du retour d'une fonction en conséquence, les objets ne sont pas copiés, seules les références à eux sont copiées.

a = () - crée un tableau. Une référence à la table est placée dans la variable a

b = a - la variable b renvoie au même tableau qu'a

a = 10 - l'élément du tableau d'indice 1 reçoit la valeur 10

MsgBox (b) -> "10"

MsgBox (a) -> "20"

Le reste des données sont des valeurs immédiates.

MsgBox (a) -> "20"

MsgBox (b) -> "10"

Comment obtenir le type d'une variable en Lua ?

Le type de la valeur stockée dans une variable peut être connu à l'aide du type de fonction standard. Cette fonction retourne une chaîne contenant le nom du type ("nil", "number", "string", "boolean", "table", "function", "thread", "userdata").

t = type (" ceci est une chaîne ") - t est égal à " chaîne "

t = type (123) - t est égal à "nombre"

t = type (type) - t est "fonction"

t = type (vrai) - t est "booléen"

t = type (nil) - t est "nil"

t = type (CroApp.GetBank ()) - t est égal à "userdata"

Comment convertir le type d'une variable en Lua ?

Lua convertit automatiquement les nombres en chaînes et vice versa selon les besoins. Par exemple, si une valeur de chaîne est un opérande dans une opération arithmétique, elle est convertie en nombre. De même, une valeur numérique qui apparaît là où une chaîne est attendue sera convertie en chaîne.

a = "10" + 2 - a égale 12

a = "10" + 2 - a est égal à "10 + 2"

a = "-5.3e-10" * "2" - a est égal à -1.06e-09

a = "chaîne" + 2 - Erreur ! Impossible de convertir "chaîne" en nombre

Toute valeur peut être explicitement convertie en chaîne à l'aide de la fonction tostring standard.

a = tostring (10) - a est égal à "10"

a = tostring (true) - a est égal à "true"

a = tostring (nil) - a est égal à "nil"

a = tostring ((= "ceci est le champ 1")) - a est égal à "table: 06DB1058"

Dans l'exemple précédent, vous pouvez voir que le contenu des tables n'est pas converti par la fonction tostring. Cette transformation peut être effectuée à l'aide de la fonction render.

a = rendu (10) - a est égal à "10"

a = rendu (vrai) - a est égal à "vrai"

a = rendu (nil) - a est égal à "nil"

a = rendu ((= "c'est le champ 1")) - a est égal à "(=" c'est le champ 1 ")"

Vous pouvez utiliser la fonction tonumber standard pour convertir explicitement une valeur en nombre. Si la valeur est une chaîne qui peut être convertie en nombre (ou est déjà un nombre), la fonction renvoie le résultat de la conversion, sinon elle renvoie nil.

a = tonumber ("10") - a est égal à "10"

a = tonumber ("10" .. ". 5") - a est égal à 10,5

a = tonumber (vrai) - a est "nil"

a = tonumber (nil) - a est "nil"

Organisation des commentaires en Lua

Un commentaire en Lua commence par deux signes moins (-) et se poursuit jusqu'à la fin de la ligne.

local a = 1 - commentaire sur une seule ligne

Si deux crochets ouvrants ([[)] suivent immédiatement les caractères « - », le commentaire est multiligne et continue jusqu'à deux crochets fermants (]]).

local a = 1 - [[multiligne

un commentaire ]]

Les doubles crochets dans les commentaires peuvent être imbriqués. Afin de ne pas les confondre, un signe égal (=) est inséré entre les parenthèses :

local a = [[Société Kronos]] - [= [

local a = [[Société Kronos]]

Le nombre de symboles "=" détermine l'imbrication :

local a = [= [définition d'une chaîne [] en langue Lua] =] - [== [

local a = [= [définition d'une chaîne [] en langue Lua] =]

Opérations Lua

Les types d'opérations suivants peuvent être utilisés dans les expressions écrites en Lua :

1. Opérations arithmétiques.

Lua prend en charge les opérations arithmétiques suivantes :

+ (addition) ;

- (soustraction);

* (multiplication) ;

/ (partie) ;

^ (exponentiation);

% (reste de la division).

Remarque

Les opérations arithmétiques s'appliquent à la fois aux nombres et aux chaînes, qui dans ce cas sont convertis en nombres.

2. Opérations de comparaison.

Les opérations de comparaison suivantes sont autorisées en Lua :

== (égal);

~ = (pas égal);

< (меньше);

> (plus);

<= (меньше или равно);

> = (supérieur ou égal).

Remarque

Les opérations de comparaison renvoient toujours la valeur booléenne true ou false.

Les règles de conversion des nombres en chaînes (et vice versa) ne fonctionnent pas pour les comparaisons, c'est-à-dire que l'expression "0" == 0 est fausse.

3. Opérations logiques.

Les opérations logiques comprennent :

et (ET logique).

L'opérateur and renvoie son premier opérande s'il est faux ou nil. Sinon, l'opération renvoie le deuxième opérande (de plus, cet opérande peut être de n'importe quel type).

a = (nil et 5) - a est nul

a == (faux et 5) - a est égal à faux

a == (4 et 5) - a vaut 5

ou (OU logique).

L'opérateur ou renvoie le premier opérande s'il n'est pas faux ou nil, sinon il renvoie le deuxième opérande.

a == (4 ou 5) - a est égal à 4

a == (faux ou 5) - a est égal à 5

Remarque

Les opérations booléennes et et ou peuvent renvoyer des valeurs de tout type.

Les opérateurs logiques et et ou évaluent la valeur du deuxième opérande uniquement s'il doit être renvoyé. S'il n'est pas requis, le deuxième opérande n'est pas évalué. Par exemple:

a == (4 ou f ()) - la fonction f () ne sera pas appelée

non (NON logique).

L'opération not renvoie toujours vrai ou faux.

4. Opération de concaténation.

Pour concaténer (joindre) des chaînes, utilisez l'opération ... (deux points).

a = "Kronos" .. "-" .. "Inform" - la variable a recevra la valeur "Kronos-Inform"

Remarque

Si un ou les deux opérandes sont des nombres, ils sont convertis en chaînes.

a = 0..1 - la variable a recevra la valeur "01"

5. L'opération d'obtention de la longueur.

Lua définit un opérateur de longueur # qui peut être utilisé pour obtenir la longueur d'une chaîne.

a = "chaîne"

len = #a - len est 6

len = # "une autre ligne" - len vaut 10

Remarque

Vous pouvez également utiliser l'opération # pour connaître l'index (ou la taille) maximum d'un tableau. Plus de détails - dans l'article "Travailler avec des tableaux en Lua".

Opération prioritaire en Lua

En Lua, les opérations sont effectuées selon la priorité suivante (par ordre décroissant) :

2.pas # - (unaire)

6. < > <= >= ~= ==

Appel de scripts à partir de formulaires

Chaque formulaire (y compris les formulaires imbriqués) est associé à un script distinct, qui contient généralement des fonctions qui gèrent les événements du formulaire et de ses éléments.

Lorsque le formulaire est lancé, son script est chargé dans l'environnement global. Lorsqu'un événement d'un formulaire ou de son élément se produit, le système appelle la fonction gestionnaire associée à cet événement.

Il est à noter que le script de formulaire, bien qu'il ne contienne pas d'appel à la fonction module, est en fait un module. Cela signifie que les variables déclarées dans le script de formulaire sans le mot-clé local ne sont pas déplacées vers l'environnement global et ne sont disponibles que dans ce script. Si vous devez rendre une valeur disponible pour des scripts d'autres formes, elle doit être explicitement définie dans la table globale _G :

local a = _G.var

Blocs d'instructions

Les principaux opérateurs Lua sont :

mission;

opérateur conditionnel ;

opérateurs pour l'organisation des boucles.

Un groupe d'instructions peut être combiné en un bloc (instruction composée) en utilisant la construction do… end.

do - le début du bloc

<оператор1>- corps de bloc

<оператор2>

<операторN>

fin - la fin du bloc

Le bloc ouvre une nouvelle portée dans laquelle vous pouvez définir des variables locales.

a = 5 - variable globale a

local a = 20 - à l'intérieur de la variable locale de fin a est défini

MsgBox (a) -> 20

MsgBox (a) -> 5 (ici l'appel est déjà vers le global a)

Opérateur d'affectation Lua

Une affectation modifie la valeur d'une variable ou d'un champ de table. Dans sa forme la plus simple, une affectation pourrait ressembler à ceci :

a = 1 - la variable a reçoit la valeur 1

a = b + c - la variable a se voit attribuer la somme des valeurs des variables b et c

a = f (x) - la variable a reçoit la valeur renvoyée par la fonction f (x)

Lua permet l'affectation dite multiple, lorsque plusieurs variables à gauche de l'opérateur d'affectation reçoivent les valeurs de plusieurs expressions écrites à droite de l'opérateur d'affectation :

a, b = 1,5 * c - a est égal à 1 ; b est égal à 5 ​​* c

S'il y a plus de variables que de valeurs, nil est affecté aux variables "extra".

a, b, c = 1, 2 - a vaut 1 ; b vaut 2 ; c est nul

S'il y a plus de valeurs que de variables, les valeurs "supplémentaires" sont ignorées.

a, b = 1, 2, 3 - a vaut 1 ; b vaut 2 ; valeur 3 non utilisée

L'affectation multiple peut être utilisée pour échanger des valeurs entre variables :

a = 10 ; b = 20 - a vaut 10, b vaut 20

a, b = b, a - maintenant a vaut 20, b vaut 10

Instruction conditionnelle (if) en Lua

L'instruction if teste si la condition spécifiée est vraie. Si la condition est vraie, la partie du code suivant le mot-clé then (la section then) est exécutée. Sinon, le code suivant le mot-clé else est exécuté (la section else).

si a> b alors

renvoie a - si a est supérieur à b, renvoie a

retourner b - sinon, retourner b

La section else est facultative.

si un< 0 then

a = 0 - si a est inférieur à 0, définissez a sur 0

Au lieu d'instructions if imbriquées, vous pouvez utiliser la construction elseif. Par exemple, le code suivant :

il sera plus facile à comprendre si vous le remplacez par ce qui suit :

renvoie "Ivan" - si a vaut 1

sinon si a == 2 alors

renvoie "Pierre" - si a vaut 2

sinon si a == 3 alors

renvoie "Sergey" - si a vaut 3

retourner "Il n'y a pas de tel joueur" - si a n'est aucun de ce qui précède

Boucle while Lua

L'instruction while est conçue pour organiser des boucles avec une condition préalable et a la forme suivante :

tandis que faire

... - le corps du cycle

Avant chaque itération de la boucle, la condition est vérifiée :

si la condition est fausse, la boucle se termine et le contrôle est transféré à la première instruction suivant l'instruction while ;

si la condition est vraie, le corps de la boucle est exécuté, après quoi toutes les actions sont répétées.

tandis que i> 0 do - boucle de 10 à 1

t [i] = "champ" ..i

a = (3, 5, 8, -6, 5)

tandis que i> 0 do - recherche d'une valeur négative dans le tableau

si un [i]< 0 then break end - если найдено, прерываем цикл

i = i - 1 - sinon passer à l'élément suivant

si i> 0 alors

MsgBox ("Index de valeur négative :" ..i)

MsgBox ("Le tableau ne contient pas de valeurs négatives")

Noter

Boucle avec postcondition (répétition) en Lua

L'instruction repeat est conçue pour organiser des boucles avec une postcondition et se présente sous la forme suivante :

... - le corps du cycle

jusqu'à

Le corps de la boucle est exécuté tant que la condition ne deviendra pas vrai. La condition est vérifiée après l'exécution du corps de la boucle, par conséquent, dans tous les cas, le corps de la boucle sera exécuté au moins une fois.

Additionner les valeurs du tableau a jusqu'à ce que la somme dépasse 10

a = (3, 2, 5, 7, 9)

somme = somme + a [i]

jusqu'à somme> 10

MsgBox ("Stacked" ..i .. "items. Amount is" ..sum)

Vous pouvez utiliser l'instruction break pour quitter la boucle avant qu'elle ne se termine.

Noter

Plus de détails sur les fonctionnalités de l'utilisation de l'opérateur break - dans l'article "Les instructions break et return"

Lua pour les boucles

L'instruction for est conçue pour organiser des boucles et peut être écrite sous deux formes :

simple (numérique pour) ;

étendu (universel pour).

La forme simple de l'instruction for

La forme simple de l'instruction for ressemble à ceci :

pour var = exp1, exp2, exp3 faire

... - le corps du cycle

Le corps de la boucle est exécuté pour chaque valeur de la variable de boucle (compteur) var dans la plage de exp1 à exp2, avec l'étape exp3.

Noter

Le pas n'est peut-être pas défini. Dans ce cas, il est pris égal à 1.

pour i = 1, 10 do - boucle de 1 à 10 avec pas 1

MsgBox ("i est égal à" ..i)

pour i = 10, 1, -1 do - boucle de 10 à 1 avec un pas de -1

MsgBox ("i est égal à" ..i)

Remarque

Les expressions exp1, exp2 et exp3 ne sont évaluées qu'une seule fois, avant le début de la boucle. Ainsi, dans l'exemple ci-dessous, la fonction f (x) sera appelée pour calculer la limite supérieure de la boucle une seule fois :

pour i = 1, f (x) do - boucle de 1 à la valeur renvoyée par la fonction f ()

MsgBox ("i est égal à" ..i)

La variable de boucle est locale à l'instruction de boucle et n'est pas définie à sa fin.

for i = 1, 10 do - boucle de 1 à la valeur renvoyée par f ()

MsgBox ("i est égal à" ..i)

MsgBox ("Après avoir quitté la boucle, i est égal à" ..i) - Faux ! je suis nul

Remarque

La valeur d'une variable de boucle ne peut pas être modifiée à l'intérieur d'une boucle : les conséquences d'un tel changement sont imprévisibles.

Pour quitter la boucle avant qu'elle ne se termine, utilisez l'instruction break.

a = (3, 5, 8, -6, 5)

for i = 1, # a do - recherchez une valeur négative dans le tableau

si un [i]< 0 then - если найдено...

index = i - stocke l'index de la valeur trouvée ...

rompre - et rompre la boucle

MsgBox ("Index de valeur négative :" ..index)

Noter

Plus de détails sur les fonctionnalités de l'utilisation de l'opérateur break - dans l'article "Les instructions break et return")

Je suis un programmeur sentimental. Parfois, je tombe amoureux des langages de programmation, puis je peux en parler pendant des heures. Je partagerai une de ces heures avec vous.

Lua ? Qu'est-ce que c'est ça?

Lua est un langage intégrable simple (il peut être intégré à vos programmes écrits dans d'autres langages), léger et direct, avec un seul type de données, avec une syntaxe uniforme. La langue parfaite à apprendre.

Pourquoi?

Lua pourrait vous être utile :

* si vous êtes un joueur (plugins pour World of Warcraft et bien d'autres jeux)
* si vous écrivez des jeux (très souvent dans les jeux, le moteur est écrit en C/C++, et AI - en Lua)
* si vous êtes un programmeur système (vous pouvez écrire des plugins pour nmap, wireshark, nginx et d'autres utilitaires en Lua)
* si vous êtes un développeur embarqué (Lua est très rapide, compact et nécessite très peu de ressources)

1. Apprenez à programmer. Au moins un peu. Peu importe la langue.
2. Installez Lua. Pour ce faire, téléchargez la version 5.2 ici (http://www.lua.org/download.html), ou recherchez-la dans les dépôts. La version 5.1 fonctionnera aussi, mais sachez qu'elle est très ancienne.

Exécutez tous les exemples de l'article dans le terminal avec une commande telle que "lua file.lua".

Premières impressions

Lua est un langage typé dynamiquement (les variables obtiennent des types "à la volée" en fonction des valeurs attribuées). Vous pouvez y écrire à la fois dans un style impératif et orienté objet ou fonctionnel (même si vous ne savez pas comment c'est, ce n'est pas grave, continuez à lire). Voici Hello world en Lua :

Ma première application lua : hello.lua print "hello world" ; imprimer ("au revoir monde")

Ce que l'on peut déjà dire sur la langue :

* les commentaires d'une seule ligne commencent par deux tirets "-"
* les parenthèses et les points-virgules peuvent être omis

Opérateurs de langue

L'ensemble des conditions et des boucles est assez typique :

Instructions conditionnelles (il ne peut y avoir aucune branche else) if a == 0 then print ("a is zero") else print ("a is not zero") end - forme abrégée if / elseif / end (au lieu de switch / case) if a == 0 then print ("zero") elseif a == 1 then print ("one") elseif a == 2 then print ("two") else print ("other") end - compteur boucle pour i = 1, 10 do print (i) end - boucle avec précondition b = 5 tandis que b> 0 do b = b - 1 end - boucle avec postcondition répéter b = b + 1 jusqu'à b> = 5

PENSEZ : que pourrait signifier la boucle "for i = 1, 10, 2 do ... end" ?

Dans les expressions, vous pouvez utiliser les opérateurs suivants sur les variables :

* affectation : x = 0
* arithmétique : +, -, *, /,% (reste de la division), ^ (exponentiation)
* booléen : et, ou, non
* comparaison :>,<, ==, <=, >=, ~ = (pas-égal, oui-oui, au lieu de l'habituel "! =")
* concaténation de chaînes (opérateur ".."), par exemple : s1 = "hello"; s2 = "monde" ; s3 = s1..s2
* longueur / taille (opérateur #): s = "bonjour"; a = #s ('a' sera 5).
* obtenir un élément par index, par exemple : s

Pendant longtemps, il n'y avait pas d'opérations au niveau du bit dans le langage, mais dans la version 5.2 la bibliothèque bit32 est apparue, qui les implémente (en tant que fonctions, pas en tant qu'opérateurs).

Types de données

Je vous ai menti quand j'ai dit que la langue a un type de données. Il en a beaucoup (comme tout langage sérieux) :

* néant (rien du tout)
* nombres booléens (vrai / faux)
* nombres (nombres) - pas de division par des nombres entiers / réel. Juste des chiffres.
* cordes - d'ailleurs, elles ressemblent beaucoup aux cordes de pascal
* fonctions - oui, une variable peut être de type "fonction"
* fil
* données arbitraires (userdata)
* tableau

Si tout est clair avec les premiers types, alors qu'est-ce que userdata ? N'oubliez pas que Lua est un langage intégré et travaille généralement en étroite collaboration avec des composants de programmes écrits dans d'autres langages. Ainsi, ces composants "étrangers" peuvent créer des données en fonction de leurs besoins et stocker ces données avec des objets lua. Ainsi, les données utilisateur sont la partie sous-marine de l'iceberg, qui du point de vue du langage lua n'est pas nécessaire, mais nous ne pouvons tout simplement pas l'ignorer.

Et maintenant, la chose la plus importante dans la langue, ce sont les tableaux.

les tables

Je vous ai encore menti quand j'ai dit que le langage a 8 types de données. Vous pouvez supposer qu'il en est un : tout est tables (d'ailleurs, ce n'est pas vrai non plus). Une table est une structure de données très élégante, elle combine les propriétés d'un tableau, d'une table de hachage ("clé" - "valeur"), d'une structure, d'un objet.

Voici donc un exemple de tableau sous forme de tableau : a = (1, 2, 3) - un tableau de 3 éléments print (a) - affichera "2", car les indices sont comptés à partir d'un - Un tableau est un tableau clairsemé (qui n'a pas tous les éléments) a = () - table vide a = 1 a = 5

PENSEZ : Qu'est-ce qu'un pour un tableau clairsemé ?

Dans l'exemple ci-dessus, la table se comporte comme un tableau, mais en réalité - nous avons des clés (index) et des valeurs (éléments de tableau). Et en même temps, les clés peuvent être de n'importe quel type, pas seulement des chiffres :

A = () a ["hello"] = true a ["world"] = false a = 1 - ou comme ceci : a = (hello = 123, world = 456) print (a ["hello")) print ( a.hello) est identique à un ["hello"], bien qu'il ressemble à une structure avec des champs

Soit dit en passant, puisque la table a des clés et des valeurs, vous pouvez parcourir toutes les clés et leurs valeurs correspondantes dans une boucle :

T = (a = 3, b = 4) pour la clé, valeur par paires (t) faire imprimer (clé, valeur) - imprime "a 3", puis "b 4" fin

Mais qu'en est-il des objets ? Nous les apprendrons un peu plus tard, d'abord - sur les fonctions.

Les fonctions

Voici un exemple de fonction courante.

Fonction add (a, b) return a + b end print (add (5, 3)) - affichera "8"

Les fonctions de langage vous permettent de prendre plusieurs arguments et de retourner plusieurs arguments. Par exemple, les arguments qui ne sont pas explicitement spécifiés sont supposés être nuls.

PENSEZ : Pourquoi voudriez-vous retourner plusieurs arguments ?

Fonction swap (a, b) return b, a end x, y = swap (x, y) - d'ailleurs, cela peut se faire sans fonction : x, y = y, x - et si la fonction retourne plusieurs arguments , - et vous n'en avez pas besoin - ignorez-les avec - la variable de soulignement spéciale "_" a, _, _, d = some_function ()

Les fonctions peuvent prendre un nombre variable d'arguments :

Dans le prototype, le nombre variable d'arguments est écrit sous forme de points de suspension, fonction somme (...) s = 0 pour _, n par paires (arg) do - dans la fonction, ils sont appelés la table "arg" s = s + n end return a end sum (1, 2, 3) - renverra 6 sum (1, 2, 3, 4) - renverra 10

Étant donné que les fonctions sont un type de données à part entière, vous pouvez créer des variables de fonction ou transmettre des fonctions en tant qu'arguments à d'autres fonctions.

A = fonction (x) retour x * 2 fin - fonction qui multiplie par 2 b = fonction (x) retour x + 1 fin - fonction qui augmente de 1 fonction appliquer (table, f) résultat = () pour k, v dans paires (table) font résultat [k] = f (v) - remplacez l'élément par une fonction de cet élément end end - PENSEZ : ce qui appelle t = (1, 3, 5) retournera s'appliquer (t, a) s'appliquer ( t, b)

Objets = fonctions + tableaux

Puisque nous pouvons stocker des fonctions dans des variables, nous pouvons également le faire dans les champs des tables. Et cela s'avère déjà, pour ainsi dire, des méthodes. Pour ceux qui ne sont pas familiers avec la POO, je dirai que son principal avantage (au moins en Lua) est que les fonctions et les données avec lesquelles elles travaillent sont côte à côte - au sein du même objet. Pour ceux qui connaissent la POO, je dirai qu'il n'y a pas de classes ici, mais l'héritage est prototypique.

Passons aux exemples. Nous avons un objet, disons, une ampoule. Elle sait brûler et ne pas brûler. Eh bien, il y a deux actions que vous pouvez faire avec - l'activer et le désactiver :

Lampe = (on = false) fonction turn_on (l) l.on = true end fonction turn_off (l) l.on = false end ne sont que des fonctions pour travailler avec la structure turn_on (lampe) turn_off (lampe)

Et si nous transformons l'ampoule en objet et transformons les fonctions turn_off et turn_on en champs de l'objet, nous obtenons :

Lamp = (on = false turn_on = fonction (l) l.on = true end turn_off = fonction (l) l.on = false end) lamp.turn_on (lampe) lamp.turn_off (lampe)

Nous sommes obligés de passer l'objet ampoule lui-même comme premier argument, car sinon notre fonction ne saura pas avec quelle ampoule elle doit fonctionner pour changer l'état marche / arrêt. Mais pour ne pas être verbeux, Lua a un raccourci qui est généralement utilisé - lampe : turn_on (). Au total, nous connaissons déjà plusieurs de ces simplifications syntaxiques :

Lamp: turn_on () - la notation la plus courante lamp.turn_on (lampe) - du point de vue de la syntaxe, c'est également la lampe correcte ["turn_on"] (lampe) - et ceci

En continuant à parler d'abréviations, les fonctions peuvent être décrites non seulement explicitement, en tant que champs d'une structure, mais aussi sous une forme plus pratique :

Lamp = (on = false) - à travers une période, alors l'argument doit être spécifié fonction lamp.turn_on (l) l.on = true end - à travers les deux-points, alors l'argument est implicitement défini comme la variable "self" - "self " - et il y a la lampe pour laquelle la fonction lampe a été appelée : turn_off() self.on = false end

Intéressant?

Fonctions spéciales

Certains noms de fonctions (méthodes) de table sont réservés et ont une signification particulière :

* __add (a, b), __sub (a, b), __div (a, b), __mul (a, b), __mod (a, b), __pow (a, b) - appelé lorsque des opérations arithmétiques sont effectuées sur tableau
* __unm (a) - opération moins unaire (quand ils écrivent quelque chose comme "x = -x")
* __lt (a, b), __le (a, b), __eq (a, b) - calcule le résultat de la comparaison (<, <=, ==)
* __len (a) - appelé lorsque "#a" est fait
* __concat (a, b) - appelé quand "a..b"
* __call (a, ...) - appelé quand "a ()". Les arguments variables sont des arguments lorsqu'ils sont appelés
* __index (a, i) - appel à un [i], à condition qu'aucun élément de ce type n'existe
* __newindex (a, i, v) - création de "a [i] = v"
* __gc (a) - lorsqu'un objet est supprimé par le ramasse-miettes

En remplaçant ces méthodes, vous pouvez surcharger les opérateurs et utiliser la syntaxe du langage à vos propres fins. L'essentiel est de ne pas en faire trop.

Héritage

Pour ceux qui ne connaissent pas la POO, l'héritage permet d'étendre les fonctionnalités d'une classe existante. Par exemple, une simple ampoule peut s'allumer et s'éteindre, et une ampoule super-légère modifiera également sa luminosité. Pourquoi devons-nous réécrire les méthodes turn_on/turn_off alors que nous pouvons les réutiliser ?

Lua a le concept d'une table méta pour cela, c'est-à-dire tables d'ancêtres. Chaque table a une table parent et la table enfant peut faire tout ce que le parent peut faire.

Disons que nous avons déjà créé l'objet table de lampe. Ensuite, la super ampoule ressemblera à ceci:

Superlamp = (luminosité = 100) - spécifiez la table parent setmetatable (superlamp, lamp) - et ses méthodes sont maintenant disponibles superlamp : turn_on () superlamp : turn_off ()

Extension des fonctionnalités

Il existe de nombreux types de tables parents (enfin, les chaînes et les tables, bien sûr, les nombres et les booléens, et nil pas). Disons que nous voulons ajouter toutes les lignes en utilisant l'opérateur "+", pas "..". Pour ce faire, remplacez la fonction "+" (__add) pour la table parente de toutes les lignes :

S = getmetatable ("") - a obtenu la table parent de la ligne s .__ add = fonction (s1, s2) return s1..s2 end - a changé la méthode - check a = "hello" b = "world" print ( a + b) - écrira "helloworld"

En fait, nous pouvons toujours remplacer la fonction d'impression par "print = myfunction", et de nombreuses autres choses de piratage peuvent être faites.

Portées

Les variables sont globales et locales. Une fois créées, toutes les variables de Lua sont globales.

PENSEZ : pourquoi ?

Pour spécifier la portée locale, écrivez le mot-clé local :

Local x local var1, var2 = 5, 3

N'oubliez pas ce mot.

Traitement des erreurs

Souvent, si des erreurs se produisent, vous devez arrêter d'exécuter une fonction particulière. Vous pouvez, bien sûr, faire de nombreuses vérifications et appeler "retour" si quelque chose ne va pas. Mais cela augmentera la quantité de code. Lua utilise quelque chose comme des exceptions.

Les erreurs sont renvoyées à l'aide de la fonction d'erreur (x). Tout peut être passé en argument (ce qui est pertinent pour l'erreur - une description de chaîne, un code numérique, l'objet avec lequel l'erreur s'est produite, etc.)

Habituellement, après cette fonction, tout le programme se bloque. Et ce n'est pas toujours nécessaire. Si vous appelez une fonction qui peut générer une erreur (ou que ses fonctions enfants peuvent générer une erreur), appelez-la en toute sécurité à l'aide de pcall() :

Fonction f (x, y) ... if ... then error (" n'a pas réussi à faire quelque chose ") end ... end status, err = pcall (f, x, y) - f : fonction, xy : ses arguments si ce n'est pas le statut alors - gérer l'erreur err. Dans notre cas, err contient le texte d'erreur end

Bibliothèques standards

Il existe de nombreuses bibliothèques non standard, elles peuvent être trouvées sur LuaForge, LuaRocks et d'autres référentiels.

Entre Lua et Non-Lua

Et si la fonctionnalité des bibliothèques standards ne nous suffisait pas ? Et si nous avons notre programme C et que nous voulons appeler ses fonctions depuis Lua ? Il existe un mécanisme très simple pour cela.

Disons que nous voulons créer notre propre fonction qui renvoie un nombre aléatoire (Lua a math.random()), mais nous voulons apprendre). Nous devrons écrire le code suivant en C :

#inclure #inclure #inclure / * en fait que faire lors de l'appel de `rand (from, to)` * / static int librand_rand (lua_State * L) (int from, to; int x; from = lua_tonumber (L, 1); / * premier paramètre du fonction * / to = lua_tonumber (L, 2); / * deuxième paramètre de la fonction * / x = rand ()% (to - from + 1) + from; lua_pushnumber (L, x); / * valeur de retour * / return 1; / * ne retourne qu'un argument * /) / * dans Lua "rand" correspond à notre fonction librand_rand() * / static const luaL_reg R = (("rand", librand_rand), (NULL, NULL) / * end de la liste des fonctions exportées * / ); / * appelé lorsque la bibliothèque est chargée * / LUALIB_API int luaopen_librand (lua_State * L) (luaL_openlib (L, "librand", R, 0); srand (time (NULL)); return 1; / * success * /)

Celles. Lua nous fournit des fonctions pour travailler avec des types de données, pour recevoir des arguments de fonction et renvoyer des résultats. Les fonctions sont rares. Nous construisons maintenant notre bibliothèque en tant que bibliothèque dynamique et nous pouvons utiliser la fonction rand() :

Random = require ("librand") - charge la bibliothèque print (random.rand (1, 100)) print (random.rand (0, 1))

Et si nous voulons appeler le code Lua depuis nos programmes ? Ensuite, nos programmes devraient créer une machine virtuelle Lua, dans laquelle les scripts Lua seront exécutés. C'est beaucoup plus simple :

#include "lua.h" #include "lauxlib.h" int main () (lua_State * L = lua_open (); // crée une machine virtuelle Lua luaL_openlibs (L); // charge la bibliothèque standard luaL_dofile (L, " rand. lua "); // exécute le script lua_close (L); // ferme Lua return 0;)

Tout.

Vous pouvez maintenant écrire en Lua. Si vous découvrez des points intéressants sur Lua qui pourraient être reflétés dans l'article, écrivez !

Cette série de tutoriels que j'ai conçue traitera du langage de programmation Lua. Je vais essayer de rendre la présentation aussi accessible que possible pour les débutants, et je vais me concentrer sur eux. C'est-à-dire que les codeurs Lua expérimentés n'apprendront probablement rien de nouveau (je suis sûr qu'ils ne trouveront de place que pour des remarques et des remarques harcelantes, qui, en fait, sont même les bienvenues de leur part), mais si vous n'avez pas de riche expérience de programmation derrière vous, alors je pense que vous pouvez gérer quelque chose.

Toute la série n'obéira à aucun système. Les leçons introduiront séquentiellement un certain nombre de constructions linguistiques de sorte qu'à la troisième ou quatrième leçon, vous puissiez déjà écrire vos programmes. Mon objectif est de vous pousser à apprendre la langue par vous-même, de vous aider à la ressentir, et non de l'expliquer de A à Z - si vous voulez maîtriser complètement la langue, lisez le manuel de référence (qui, bien que mal, est traduit en russe : http://www.lua .ru/doc/). Plus vite vous passerez des leçons « pour les nuls » sur le web à l'étude du guide, mieux ce sera.

Si quelque chose n'est pas clair, n'oubliez pas de poser une question dans les commentaires, et moi et d'autres membres essaierons de vous aider.

Lua est un langage de programmation généraliste populaire, facile à apprendre, intégrable, interprété et typé dynamiquement. Non, vous n'avez pas besoin de comprendre même la moitié des mots de la phrase précédente - l'essentiel est de savoir qu'elle est populaire et simple. Soit dit en passant, il a gagné sa popularité en raison de sa simplicité et de la petite taille du kit de distribution (environ 150 kilo-octets). Les scripts Lua sont pris en charge par un grand nombre d'applications, y compris des jeux. World of Warcraft et S.T.A.L.K.E.R. utiliser la langue Lua. Mon moteur de jeu préféré vous permettra de créer facilement une variété de jeux en utilisant Lua. Comme vous pouvez le constater, Lua vous ouvre plein d'horizons !

Avant de commencer, vous devez configurer un environnement de programmation : c'est-à-dire trouver un programme qui accepte le code Lua que vous écrivez et l'exécute : l'interpréteur. Il y a trois options ici :

1. Téléchargez la distribution officielle Lua depuis l'un des sites qui les fournissent.

Seul le code source de l'interprète peut être téléchargé sur le site officiel de Lua. Cependant, en examinant http://lua.org/download.html dans la section Binaries, vous pouvez trouver des liens vers des sites avec des fichiers exécutables pour Windows. L'un d'eux: . Téléchargez à partir de là une des archives (correspondant à votre plate-forme : Win32 ou Win64) et décompressez-la quelque part, de préférence dans un répertoire avec un chemin court : comme C:\lua. À partir de maintenant, je suppose que vous utilisez Windows et que votre interprète est là.

Les utilisateurs de systèmes d'exploitation basés sur Linux sont plus faciles dans ce sens : ils ont juste besoin d'utiliser le gestionnaire de packages et d'installer Lua à partir des référentiels. Sur Debian et Ubuntu, cela se fait avec apt-get install lua, et sur Fedora, Red Hat et leurs dérivés, cela se fait avec yum install lua. Cependant, ne me faites pas aveuglément confiance et consultez le manuel de votre système d'exploitation pour savoir exactement comment procéder.

2. Utilisez un interprète en ligne.

Situé à http://www.lua.org/demo.html. Au début, cela peut suffire, mais plus tard, lorsque nous aborderons les modules, vous devrez utiliser la version hors ligne. L'utilisation de l'interpréteur en ligne est très simple : saisissez votre programme dans la fenêtre avec le texte et cliquez sur le bouton Exécuter. Le programme sera exécuté, la fenêtre de sortie affichera la sortie de votre programme, ainsi que les rapports d'erreur, le cas échéant.

3. Utilisez IDE.

Par exemple ZeroBrane Studio : http://studio.zerobrane.com/. Il y en a d'autres - recherchez sur Internet.

Il existe désormais deux versions légèrement différentes de Lua en circulation : 5.1 et 5.2. Je me concentrerai sur la version la plus récente - la version 5.2, mais je soulignerai certainement les différences importantes entre elle et 5.1, car cette dernière est également assez courante. Soit dit en passant, Lua 5.1 exécute le code une fois et demie plus rapidement que Lua 5.2, donc vous le savez.

=== Leçon #1 ===

Alors, commençons. Créez un fichier main.lua dans un dossier isolé des fichiers superflus et écrivez dedans :

200 ? "200px": "" + (this.scrollHeight + 5) + "px"); ">
- main.lua -
imprimer ("Bonjour tout le monde!")

Lancez ensuite en ligne de commande (n'oubliez pas de vous déplacer dans le répertoire avec main.lua à l'aide de la commande cd) :

200 ? "200px": "" + (this.scrollHeight + 5) + "px"); ">
> C:\lua\lua.exe main.lua

En réponse, l'interprète Lua émettra :

200 ? "200px": "" + (this.scrollHeight + 5) + "px"); ">
Bonjour le monde!

En principe, il fallait s'y attendre. Dans le programme, nous avons appelé la fonction d'impression. La fonction d'impression prend un nombre arbitraire de paramètres et les imprime séquentiellement à l'écran. Dans cet exemple, nous lui avons passé la chaîne (chaîne de caractères) "Hello world!" Vous pouvez tout aussi bien passer en paramètre :

200 ? "200px": "" + (this.scrollHeight + 5) + "px"); ">
print (8) - un nombre décimal
- affichera : 8

Imprimer (0xDEADBEEF) - nombre hexadécimal
- affichera : 3735928559

Print ("0xDEADBEEF") est une chaîne, pas un nombre ! Voyez-vous les citations?
- affichera : 0xDEADBEEF

Imprimer (1.35e-4) - nombre à virgule flottante (nombre fractionnaire)
- Sortira 0,000135. 1,35e-4 doit être compris comme "1,35 multiplié
- de dix au moins quatrième degré », si quelqu'un ne le sait pas.

Impression ((198 * 99) -3 * 500 + 14/88) - expression
- Affiche la valeur de l'expression : 18102.159090909. Pas une mauvaise alternative
- une calculatrice de bureau !

Imprimer (198/7, "engrais", 2 ^ 9) - plusieurs paramètres d'un arbitraire
- taper. Les valeurs de chacun d'eux seront affichées, séparées par des signes
- onglets :
- 28.285714285714 engrais 512
- Veuillez noter que les citations autour des engrais ne sont pas affichées !

Imprimer (1,35) est deux nombres, pas une fraction décimale de 1,35 !
- Une virgule est utilisée pour séparer les paramètres.
- Sortira :
-- 1 35

Le signe "-" n'est pas seulement une imitation d'un tiret, qui est inséré pour la beauté. Le signe "-" dans Lua indique des commentaires : des conseils pour le programmeur qui sont ignorés par l'interpréteur et destinés à rendre le code plus facile à comprendre. Vous pouvez essayer d'écrire dans le programme :

200 ? "200px": "" + (this.scrollHeight + 5) + "px"); ">
- imprimer ("rien")

L'interprète pensera qu'il s'agit d'un commentaire et ne suivra pas les instructions.

Note à l'hôtesse : si vous souhaitez imprimer une seule ligne, vous pouvez écrire l'appel d'impression comme ceci, sans parenthèses :

200 ? "200px": "" + (this.scrollHeight + 5) + "px"); ">
imprimer "Juste une chaîne"

La commodité est définitivement discutable : gardez juste à l'esprit que c'est possible. Cependant, de tels appels sont inacceptables :

200 ? "200px": "" + (this.scrollHeight + 5) + "px"); ">
print 2 - ne fonctionnera pas, 2 - pas une chaîne.
imprimer 2 * 2 + 6 - d'autant plus ne fonctionnera pas

Str = "chaîne !!" - affecté à la variable str la valeur "string !!"
- lire sur les variables ci-dessous
print str ne fonctionnera pas non plus.

Dans chacun des cas ci-dessus, le programme refusera simplement de fonctionner. Ainsi, dans un appel "sans parent", un nom de fonction ne peut être suivi que d'un littéral de chaîne (c'est-à-dire d'une séquence de caractères entre guillemets), et rien d'autre. À l'avenir, je parlerai de cette fonctionnalité un peu plus en détail, mais pour l'instant, cela vous suffit.

Dans tout bon langage de programmation, il est possible de déclarer des variables : de petits conteneurs pouvant contenir des données. Lua procède ainsi :

200 ? "200px": "" + (this.scrollHeight + 5) + "px"); ">
<имя_переменной> = <выражение>

Par exemple:

200 ? "200px": "" + (this.scrollHeight + 5) + "px"); ">
star = 8 - La variable star stocke maintenant le nombre 8
wars = "owl" - La variable wars contient la chaîne "owl"
jedi = 42/2 - En jedi variable - numéro 21
luke = star * jedi - La variable luke est le nombre 168 (oui, 21 fois 8)

Les valeurs des variables et des expressions avec elles peuvent également être affichées :

200 ? "200px": "" + (this.scrollHeight + 5) + "px"); ">
impression (star, wars, jedi, jedi-star + luke)
- Sortira :
- 8 chouette 21 181

N'essayez tout simplement pas d'ajouter les variables star et wars - essayer d'ajouter 8 à "owl" ne vous servira à rien !

Comme vous avez dû le remarquer, le nom d'une variable peut être à peu près n'importe quoi : l'essentiel est qu'il ne commence pas par un nombre. Sérieusement, vous pouvez même déclarer une variable nommée print, puis la fonction print cessera de fonctionner, car le nom print fera référence à la variable nouvellement déclarée. Mais il existe un groupe de mots qu'il est interdit d'utiliser comme noms de variables - ce sont des mots-clés de langue que nous n'avons pas encore rencontrés, mais qui valent vraiment la peine d'être regardés :

200 ? "200px": "" + (this.scrollHeight + 5) + "px"); ">
et casser faire autre chose si fin
false pour la fonction goto si dans
local nil pas ou répéter le retour
puis vrai jusqu'à ce que

En créant une variable avec l'un de ces noms, vous provoquerez une erreur dans le programme, et cela ne fonctionnera certainement pas. Veuillez noter que dans Lua 5.1, il n'y a pas de mot-clé goto, et vous pouvez nommer une variable de cette façon, mais il vaut mieux ne pas le faire.
Notez également que les noms de variables sont sensibles à la casse. Cela signifie que foo, fOo, fOO et FOO sont quatre variables différentes, donc si vous écrivez le nom d'une variable en lettres minuscules et l'écrivez plus tard en majuscules, il est fort probable que le programme ne fonctionnera pas correctement.

Maintenant, un point important : que se passe-t-il si, par accident ou volontairement, vous faites référence à une variable inexistante ? Dans la plupart des autres langues, cela provoquera une erreur, mais en Lua, cette situation est acceptable. Elle est interprétée comme si une variable inexistante existait réellement, mais sa valeur est néant. néant- souviens-toi de ce mot ! est un type de valeur spécial en Lua qui signifie "rien". Pas un zéro ou une chaîne vide (une chaîne comme "" - essayez de l'afficher), mais rien. Comparez cela avec ce modèle : il y a deux personnes, l'une a un compte bancaire, mais il n'y a pas d'argent dessus, et l'autre n'a pas de compte bancaire du tout. En termes Lua, on considérera que le premier a 0 dollar sur le compte, et le second a néant... Et même pas de dollars, mais juste néant... J'espère que je ne vous ai pas confondu.

Essayez, par exemple, d'exécuter un programme comme celui-ci :

200 ? "200px": "" + (this.scrollHeight + 5) + "px"); ">
- main.lua -
foo = "barre"
imprimer (foo, baz)
- Sortira :
- barre nulle

Ainsi, la variable baz, qui n'existe pas mais est supposée l'être, a une valeur de nil, et la fonction print le comprend et l'affiche à l'écran sous la forme de la chaîne "nil". Lua a une bonne méthode pour vérifier l'existence d'une variable : si la valeur d'une variable n'est pas nulle, alors elle est au moins déclarée. Alternativement, vous pouvez déclarer explicitement une variable à nil :

200 ? "200px": "" + (this.scrollHeight + 5) + "px"); ">
cool_var = nil

Cela peut être fait, et bien que cela puisse sembler idiot à première vue, c'est parfois fait. Dans les leçons suivantes, vous apprendrez qui et pourquoi, et vous commencerez probablement à faire de même. Parfois, bien sûr.
Soyez prudent avec nil : vous pouvez imprimer nil, mais vous ne pouvez pas faire d'arithmétique avec ! 99+ nul égalait 99. Croyez-moi, j'étais aussi bouleversé quand je l'ai découvert.

Résumé:
1. Nous avons appris la fonction print, ce qu'elle peut faire et comment l'appeler correctement sans parenthèses.
2. J'ai appris à déclarer des variables, à calculer des expressions (bien qu'un peu), quels peuvent être les noms de variables.
3. J'ai appris le néant, imprégné de son mystère mystique et j'ai acquis la confiance qu'à l'avenir nous serons associés à beaucoup d'entre eux.

Pour ceux qui sont curieux et qui veulent approfondir leurs connaissances, je propose des exercices simples, que vous pouvez ignorer si vous vous sentez déjà suffisamment compétent :
1. Écrivez un programme qui joue le refrain de votre chanson préférée.
2. Essayez de sortir les valeurs des expressions suivantes. Essayez de comprendre pourquoi certains d'entre eux fonctionnent et d'autres non. Examinez les erreurs causées par les expressions ayant échoué.

200 ? "200px": "" + (this.scrollHeight + 5) + "px"); ">
2 + "chaîne" ;
6 + "14";
"boîte" - "vox" ;
1 * "11b"
"148" * "1e6" ;


3. Écrivez un programme qui échange deux variables. C'est-à-dire:

200 ? "200px": "" + (this.scrollHeight + 5) + "px"); ">
a = 6502
b = 8086


Faites en sorte que a devienne égal à 8086 et b égal à 6502. Pour ce faire, créez une troisième variable et effectuez quelques échanges simples. Assurez-vous que le problème est résolu correctement en appelant print (a, b) avant l'échange et print (a, b) après.

Vous avez aimé l'article ? Partagez-le