Lua: Le tutoriel  wxWidgets
Lua
Les fonctions: La portée lexicale.

Quand une fonction est incluse dans une autre fonction, elle a pleinement accès aux variables locales de la fonction englobante, cette fonctionnalité est appelée portée lexicale.

Commençons par un exemple simple.
Supposez que vous ayez une liste de noms d'élèves et un tableau qui associe ces noms à des notes.
Vous voulez trier la liste des noms, selon leur note (dans un ordre décroissant).
Vous pouvez effectuer cette tâche comme suit:

-- Pour exécuter cet exemple, rajouter le code wxWidgets N°3

	noms = {"Peter", "Paul", "Mary"}
	notes = {Mary = 10, Paul = 7, Peter = 8}

	-- Affichage des noms avant le trie
	textCtrl:AppendText("Affichage des noms avant le tri.\n")
	for k, v in ipairs(noms) do
		Affiche(k, v)
	end

	-- Le tri
	table.sort(noms, function(n1, n2)
		return notes[n1] > notes[n2] -- compare les notes
		end)

	-- Affichage des noms après le tri		
	textCtrl:AppendText("\nAffichage des noms après le trie.\n")	
	for k, v in ipairs(noms) do
		Affiche(k, v)
	end
				

Maintenant, si vous voulez créer une fonction qui remplisse la même tâche...

	noms = {"Peter", "Paul", "Mary"}
	notes = {Mary = 10, Paul = 7, Peter = 8}
					
	function Tri_Par_Note(noms, notes)
	  table.sort(nom, function(n1, n2)
		 return notes[n1] > notes[n2] -- compare les notes
		 end)
	end
				
Ce qui est intéressant dans cet exemple, c'est que la "fonction anonyme" utilisée pour trier, a effectivement accès aux paramètres "notes" qui appartiennent à la fonction Tri_Par_Note(noms, notes).
Dans cette fonction anonyme, notes n'est ni une variable globale, ni une variable locale.
C'est une variable locale externe ou upvalue.
	function newCounter()
	  local i = 0
	  return function() -- fonction anonyme
		 i = i + 1
		 return i
	  end
	end

	h2 = newCounter()
	print(h2())  --> 1
	print(h2())  --> 2
				
La fonction anonyme, utilise la upvalue i, qui lui permet de conserver le compteur.
Car le temps d'appeler la fonction anonyme, la variable locale i est déjà hors de portée puisque la fonction qui a créée cette variable (newCounter) est rentrée dans sa phase return.
Mais LUA gère correctement cette situation en utilisant la notion de closure (ou clôture).
Rappelez-vous, une closure est une fonction supplémentaire qui permettra à la fonction anonyme, d'accéder correctement à ses upvalues.
En appelant une nouvelle fois newCounter(), il y aura création d'une nouvelle variable local i, puis nous obtiendrons une nouvelle closure qui agira par dessus la nouvelle variable locale i, reprenant si besoin est, la suite du premier compteur.
	c2 = newCounter()
	(c2())  --> 1
	(h2())  --> 3
	(c2())  --> 2
				
Dans cet exemple, le premier c2 et le deuxième c2 opèrent une closure différente au cours de la même fonction, en agissant indépendamment sur la variable locale i.
Les fonctions étant stockées dans des variables régulières, il est facile de redéfinir les fonctions prédéfinies.
Supposez que vous souhaitiez redéfinir la fonction sin() afin de fournir un résultat en degrés à la place de radians.
	oldSin = math.sin
	math.sin = function(x)
		return oldSin(x * math.pi/180)
		end
				
Ci-dessous, une façon plus "propre" de faire la même chose:
	do
	  local  oldSin = math.sin
	  local k = math.pi/180
	  math.sin = function(x)
		 return oldSin(x * k)
		 end
	end
				
Cette fonctionnalité est aussi utilisée pour créer un environnement "sécurisé".
Les environnements sécurisés sont essentiels, lors de l'exécution de programme exécuté par un serveur au travers d'Internet.
L'exemple suivant, va redéfinir la fonction open (de la bibliothèque io), en utilisant des closures.
	do
	  local oldOpen = io.open
	  io.open = function(filname, mode)
		 if access_OK(filename, mode) then
			return oldOpen(filename, mode)
		 else
			return nil -- accès refusé
		 end
	  end
	end
				

Après cette redéfinition, il n'y a plus aucun moyen d'appeler la fonction open normalement.
La fonction open est maintenant une fonction sécurisée.

logo wxWidgets Le savoir ne vaut que s'il est partagé par tous...
logo-internet_32x32.png Dernière mise à jour, le 20 novembre 2012.
Valid XHTML 1.0 Transitional

wxlualogo
Flèche haut
Flèche gauche
Flèche haut
Flèche droite