π
<-

Classes custom

Pour TI-Nspire OS 3.0 ou ultérieur.

Classes custom

Unread postby DarkFire » 24 Mar 2015, 20:50

Bonjour! :)

J'ai récemment mis au point un code pour créer des classes en Lua, que je pense meilleur que celui de base, puisque il gére l'héritage multiple et tout ça en peu de ligne de code! ;)
J'aimerai savoir ce que vous en pensez, et j'essayerai de voir si je peux optimiser le code où ajouter des fonctionnalité plus complexe.
Code: Select all
local setmetatable = setmetatable
local unpack = unpack
local pairs = pairs
local ipairs = ipairs
local string_match = string.match

do
   -- __call
   local function __call(self,...)
      local ins = setmetatable( {}, getmetatable(self) )

      for k,v in pairs(self) do
         if k ~= "__call" then
            ins[k] = v
         end
      end

      if ins.init then ins:init(...) end
      return ins
   end

   -- __is
   function is(o,c)
      if getmetatable(o) == getmetatable(c) then
         return true
      else
         for i,v in ipairs(o.__parents) do
            if v:is(c) then
               return true
            end
         end
      end
      return false
   end
   
   -- __super
   function super(ins, superclass)
      if ins == superclass then
         return superclass
      else
         return ins.__parents[1]
      end
   end
   
   -- Class
   function Class(...)
      -- create the new class table
      local c = {__parents={...}, is=is, super=super, __call=__call}
      -- inherit all
      for i=1,#c.__parents do
         for k,v in pairs(c.__parents[i]) do
            if not c[k] then
               c[k] = v  -- copy the parent table content into the new class
            end
         end
      end

      return setmetatable(c,c)
   end
end -- do block


Et si la fonction class de base vous suffit sur la Ti-Nspire, elle n'existe pas sur PC, donc elle reste toujours utile! :#top#:
Last edited by DarkFire on 16 Apr 2015, 23:21, edited 3 times in total.
User avatar
DarkFire
Niveau 3: MH (Membre Habitué)
Niveau 3: MH (Membre Habitué)
Level up: 28%
 
Posts: 14
Joined: 14 Mar 2015, 23:28
Gender: Male
Calculator(s):
MyCalcs profile
Class: 1ere S (SI)

Re: Classes custom

Unread postby Adriweb » 24 Mar 2015, 20:58

C'est une bien vieille idée de vouloir améliorer le système de classe existant :P Ca a été fait (cf. Jim Bauwens), mais peu utilisé il me semble.
Enfin bref, ça peut être utile, quand on en a besoin, certes :)

Quelques trucs:
- Tu ne copies pas les metatables des parents - c'est voulu ?
- Le problème avec l'héritage multiple, c'est si plusieurs méthodes sont valables (même signatures) - laquelle appeler ?
- Je vais demander à Jim de faire un tour sur ce topic :P

Pour info, le code de class([parent]) de TI (source Wiki Inspired-Lua):
Show/Hide spoilerAfficher/Masquer le spoiler
Code: Select all
class = function(prototype)
local derived={}
   if prototype then
      function derived.__index(t,key)
         return rawget(derived,key) or prototype[key]
      end
   else
      function derived.__index(t,key)
         return rawget(derived,key)
      end
   end
   function derived.__call(proto,...)
      local instance={}
      setmetatable(instance,proto)
      local init=instance.init
      if init then
         init(instance,...)
      end
      return instance
   end
   setmetatable(derived,derived)
   return derived
end

MyCalcs: Help the community's calculator documentations by filling out your calculators info!
MyCalcs: Aidez la communauté à documenter les calculatrices en donnant des infos sur vos calculatrices !
Inspired-Lua.org: All about TI-Nspire Lua programming (tutorials, wiki/docs...)
My calculator programs
Mes programmes pour calculatrices
User avatar
AdriwebAdmin
Niveau 16: CC2 (Commandeur des Calculatrices)
Niveau 16: CC2 (Commandeur des Calculatrices)
Level up: 79.9%
 
Posts: 14841
Images: 1133
Joined: 01 Jun 2007, 00:00
Location: France
Gender: Male
Calculator(s):
MyCalcs profile
Twitter: adriweb
GitHub: adriweb

Re: Classes custom

Unread postby DarkFire » 24 Mar 2015, 21:30

Adriweb wrote:- Tu ne copies pas les metatables des parents - c'est voulu ?

Hmm... Tu me fais réfléchir... Parce que le seul regret sur cette version, c'est que je ne peux pas tester si une classe a hérité d'une autre...
Adriweb wrote:- Le problème avec l'héritage multiple, c'est si plusieurs méthodes sont valables (même signatures) - laquelle appeler ?

C'est vrai que là, on ne peut qu'appeller la dernière méthode enregistrée... Pour gérer ça, il faudrait faire un truc avec __index et __newindex. Je vais y réfléchir. (En fait j'avais déjà bossé sur les classes en Lua pour PC il y a un moment, et je suis parvenu à un système d'héritage multiple avec l'accès et la création interdite aux attributs hors des méthodes,etc...
Mais c'était plutôt long et j'ai décidé de le réecrire en plus court sans toute ces limitations... Voila le code:
Show/Hide spoilerAfficher/Masquer le spoiler
Code: Select all
Class = {}
function Class:new(...)
   -- * Class method "new", to create new Class * --
   local mt = {__call=self.__call}
   mt.__metatable = "private stuff"
   mt.__newindex = function(t, k, v)
      if type(v) == "function" then
         t.__met[k] = v
      end
   end
   local class = setmetatable({__met={},__atr={},__a=false}, mt)
   -- inherit
   local t = unpack{{...}}
   for c in ipairs(t) do
      for i in pairs(t[c]) do
         for k, v in pairs(t[c].__met) do
            class.__met[k] = v
         end
         for k, v in pairs(t[c].__atr) do
            class.__atr[k] = v
         end
      end
   end
   -- return the class table
   return class
end

function Class:__call(...)
   -- * Class method "__call", to create instance * --
   local ins = {__met={},__atr={},__a=false}
   for k, atr in pairs(self.__atr) do
      ins.__atr[k] = atr
   end
   for k, met in pairs(self.__met) do
      ins.__met[k] = function(...)
         local old__a = ins.__a
         ins.__a = true
         local f = met(...)
         ins.__a = old__a
         return f
      end
   end
   local mt = {__metatable="private stuff"}
   mt.__index = function(t, k)
      if t.__met[k] then
         return t.__met[k]
      elseif t.__a and t.__atr[k] then
         return t.__atr[k]
      end
   end
   mt.__newindex = function(t, k, v)
      if type(v) == "function" then
         t.__met[k] = v
      elseif type(v) ~= "function" then
         t.__atr[k] = v
      end
   end

   setmetatable(ins, mt)
   ins:__init(...)
   ins.__met.__init = nil
   return ins
end


Merci pour la réponse rapide! :D

EDIT: Je pense avoir trouvé la solution pour les signatures identique, le truc serait de faire comme les fonctions memoize: on enregistre les arguments. Sauf que là on enregistre le type des arguments et non pas la valeur.
User avatar
DarkFire
Niveau 3: MH (Membre Habitué)
Niveau 3: MH (Membre Habitué)
Level up: 28%
 
Posts: 14
Joined: 14 Mar 2015, 23:28
Gender: Male
Calculator(s):
MyCalcs profile
Class: 1ere S (SI)

Re: Classes custom

Unread postby technolapin » 25 Mar 2015, 21:40

Je sais pas vraiment ce que c'est les classes héritées ou pas (parce que il n'y en a pas en lua nspire de base ou alors j'en ai jamais eu besoin), mais j'ai pas pu résister à canger des détails :p :
Code: Select all
do
   local function __call(ins,...)
     -- ins (que tu a appellé self) est déjà une instance parce que c'est comme ça en lua
     pcall(ins:init(...)) -- je sais pas si c'est vraiment mieux, mais j'aime bien les pcall, c'est pratique (ne retourne rien si ça fait une erreur et ignore cette erreur)
      return ins
   end

   function Class(...)
      -- create the new class table
      local c = {__call=__call}

      local parents = {...}
      -- inherit all
      for a, b in pair (parents) do -- + efficace ou au pire je suis juste un maniaque des pairs
         for k,v in pairs(b) do
            c[k] = v  -- copy the parent table content into the new class
         end
      end

      return setmetatable(c,c)
   end
end


Voilà, ça sert à rien de faire ces changements à part pour simplifier un peu et gagner 0.0001% de performance environ.
Votez Kasane Teto 2017
User avatar
technolapin
Niveau 13: CU (Calculateur Universel)
Niveau 13: CU (Calculateur Universel)
Level up: 97.8%
 
Posts: 514
Images: 25
Joined: 31 Dec 2012, 10:48
Location: Chez moi
Gender: Male
Calculator(s):
MyCalcs profile
Class: Chui en vacance ducon

Re: Classes custom

Unread postby DarkFire » 26 Mar 2015, 19:57

A non désolé, mais la fonction __call n'est pas valide du tout: j'ai besoin de renvoyer une copie de self, pas de self lui même...
pour ce qui est des performances, un simple test booléen sera toujours plus rapide qu'une fonction et c'est pareil pour la boucle for (car pairs est une fonction). Mais sinon, c'est simpa de m'aider à optimiser mon code! ;)
( Voir https://springrts.com/wiki/Lua_Performance )

Sinon j'ai modifié mon code, maintenant il supporte:
- Les tests pour savoir si un objet est de telle ou telle classe qui est facilement accesible via une comparaison classique ou la fonction is(o, c)
- Une fonction super qui retourne soit le premier parent connu de la classe, soit l'un des parent donné en argument qui s'écrit super(ins,[superclass)
- Et très important: la suppression de la métaméthode __call lors de la création de l'objet!
User avatar
DarkFire
Niveau 3: MH (Membre Habitué)
Niveau 3: MH (Membre Habitué)
Level up: 28%
 
Posts: 14
Joined: 14 Mar 2015, 23:28
Gender: Male
Calculator(s):
MyCalcs profile
Class: 1ere S (SI)

Re: Classes custom

Unread postby technolapin » 27 Mar 2015, 12:26

Ah non, faire un pcall est plus rapide que de vérifier que la fonction est exécutable puis l’exécuter.
Code: Select all
local function __call(ins,...)
         pcall(ins:init(...))
         return ins
       end

revient à la même chose que
Code: Select all
local function __call(self,...)
         local ins = unpack({self})
         if ins.init then ins:init(...) end
         ins.__call = nil
         return ins
       end

mais sans le test, sans les problèmes, en plus court et plus rapide.
Votez Kasane Teto 2017
User avatar
technolapin
Niveau 13: CU (Calculateur Universel)
Niveau 13: CU (Calculateur Universel)
Level up: 97.8%
 
Posts: 514
Images: 25
Joined: 31 Dec 2012, 10:48
Location: Chez moi
Gender: Male
Calculator(s):
MyCalcs profile
Class: Chui en vacance ducon

Re: Classes custom

Unread postby DarkFire » 27 Mar 2015, 13:54

Bon d'accord, mais pcall ou pas, là n'est pas le problème: je le répéte, mais, j'ai absolument besoin d'une copie de la table d'origine!
En programmation orientée objet, une classe est un peu comme le plan de construction d'un objet.
Avec mon code, on crée une classe comme ça:
Show/Hide spoilerAfficher/Masquer le spoiler
Code: Select all
local Car = Class()
function Car:init(max_speed)
    self.max_speed = max_speed
    self.speed = 0
    self.started = false
end

function Car:start()
    self.started = true
end

Et on l'instancie comme ça:
Show/Hide spoilerAfficher/Masquer le spoiler
Code: Select all
local voiture1 = Car(120)
local voiture2 = Car(130)
local voiture3 = car(140)

Comme tu peux le remarquer, il est possible de créer plusieurs instance de "Car", donc il faut en créer des copies.
En plus, la classe n'est censé contenir que des méthodes, et pas autre chose.
Les autres type de variables sont crée par la fonction "init".

Alors que le code que tu me propose ne copie aucune table... Donc lorsque tu appelle __call tu retourne la classe elle même.
C'est comme si une classe était un plan de construction d'une maison, et que lorsque tu envoie des ouvriers construire la maison, à la place ils modifient le plan de construction original...

Si ce n'est pas clair, je t'invite à te renseigner sur la programmation orientée objet (POO ou encore OOP pour les intimes) ;)
User avatar
DarkFire
Niveau 3: MH (Membre Habitué)
Niveau 3: MH (Membre Habitué)
Level up: 28%
 
Posts: 14
Joined: 14 Mar 2015, 23:28
Gender: Male
Calculator(s):
MyCalcs profile
Class: 1ere S (SI)

Re: Classes custom

Unread postby technolapin » 27 Mar 2015, 19:16

Oui mais c'est déjà une copie.
Par exemple, dans ce code, a ne varie pas:
Code: Select all
local a = "a"
local function lol (var) var = 1 end
print a
lol(a)
print a

En lua, les arguments renvoient une copie de la variable localisée dans la fonction et non pas la variable originale, la modifier ne change pas la variable originelle.
Votez Kasane Teto 2017
User avatar
technolapin
Niveau 13: CU (Calculateur Universel)
Niveau 13: CU (Calculateur Universel)
Level up: 97.8%
 
Posts: 514
Images: 25
Joined: 31 Dec 2012, 10:48
Location: Chez moi
Gender: Male
Calculator(s):
MyCalcs profile
Class: Chui en vacance ducon

Re: Classes custom

Unread postby Levak » 27 Mar 2015, 19:20

technolapin wrote:Oui mais c'est déjà une copie.
Par exemple, dans ce code, a ne varie pas:
Code: Select all
local a = "a"
local function lol (var) var = 1 end
print a
lol(a)
print a

En lua, les arguments renvoient une copie de la variable localisée dans la fonction et non pas la variable originale, la modifier ne change pas la variable originelle.


Sauf si c'est un tableau.
User avatar
LevakAdmin
Niveau 14: CI (Calculateur de l'Infini)
Niveau 14: CI (Calculateur de l'Infini)
Level up: 98.9%
 
Posts: 6414
Images: 22
Joined: 27 Nov 2008, 00:00
Location: 0x1AACC355
Gender: Male
Calculator(s):
MyCalcs profile
Class: BAC+5: Epita (ING3)

Re: Classes custom

Unread postby Adriweb » 27 Mar 2015, 19:25

Levak wrote:
technolapin wrote:Oui mais c'est déjà une copie.
Par exemple, dans ce code, a ne varie pas:
Code: Select all
local a = "a"
local function lol (var) var = 1 end
print a
lol(a)
print a

En lua, les arguments renvoient une copie de la variable localisée dans la fonction et non pas la variable originale, la modifier ne change pas la variable originelle.


Sauf si c'est un tableau.


(les table en Lua étant purement des pointeurs, d'où l'intérêt de se faire des helpers du genre copyTable et deepCopy)

MyCalcs: Help the community's calculator documentations by filling out your calculators info!
MyCalcs: Aidez la communauté à documenter les calculatrices en donnant des infos sur vos calculatrices !
Inspired-Lua.org: All about TI-Nspire Lua programming (tutorials, wiki/docs...)
My calculator programs
Mes programmes pour calculatrices
User avatar
AdriwebAdmin
Niveau 16: CC2 (Commandeur des Calculatrices)
Niveau 16: CC2 (Commandeur des Calculatrices)
Level up: 79.9%
 
Posts: 14841
Images: 1133
Joined: 01 Jun 2007, 00:00
Location: France
Gender: Male
Calculator(s):
MyCalcs profile
Twitter: adriweb
GitHub: adriweb

Next

Return to Nspire-Lua

Who is online

Users browsing this forum: ClaudeBot [spider] and 1 guest

-
Search
-
Social TI-Planet
-
Featured topics
Comparaisons des meilleurs prix pour acheter sa calculatrice !
"1 calculatrice pour tous", le programme solidaire de Texas Instruments. Reçois gratuitement et sans aucune obligation d'achat, 5 calculatrices couleur programmables en Python à donner aux élèves les plus nécessiteux de ton lycée. Tu peux recevoir au choix 5 TI-82 Advanced Edition Python ou bien 5 TI-83 Premium CE Edition Python.
Enseignant(e), reçois gratuitement 1 exemplaire de test de la TI-82 Advanced Edition Python. À demander d'ici le 31 décembre 2024.
Aidez la communauté à documenter les révisions matérielles en listant vos calculatrices graphiques !
1234
-
Donations / Premium
For more contests, prizes, reviews, helping us pay the server and domains...
Donate
Discover the the advantages of a donor account !
JoinRejoignez the donors and/or premium!les donateurs et/ou premium !


Partner and ad
Notre partenaire Jarrety Calculatrices à acheter chez Calcuso
-
Stats.
759 utilisateurs:
>716 invités
>36 membres
>7 robots
Record simultané (sur 6 mois):
7582 utilisateurs (le 25/06/2025)
-
Other interesting websites
Texas Instruments Education
Global | France
 (English / Français)
Banque de programmes TI
ticalc.org
 (English)
La communauté TI-82
tout82.free.fr
 (Français)