lotrointerface.com
Search Downloads


Go Back   LoTROInterface > LotRO > Developer Discussions > Lua Programming Help (L)

Reply
Thread Tools Display Modes
  #11  
Unread 10-08-2010, 07:36 AM
Kryso Kryso is offline
The Undefeated
 
Join Date: Oct 2010
Posts: 8
And now I'm lost. Current class implementation doesn't create new or copy functions for each instance, they are stored in table that acts like both prototype and instance factory thanks to metatables. Making new copy of function instead of referencing it doesn't make any sense unless we need to access parent scope.
Reply With Quote
  #12  
Unread 10-08-2010, 08:28 AM
Digital_Utopia's Avatar
Digital_Utopia Digital_Utopia is offline
The Undying
Interface Author - Click to view interfaces
 
Join Date: Sep 2010
Posts: 207
Send a message via MSN to Digital_Utopia Send a message via Yahoo to Digital_Utopia
Quote:
Originally Posted by Kryso
And now I'm lost. Current class implementation doesn't create new or copy functions for each instance, they are stored in table that acts like both prototype and instance factory thanks to metatables. Making new copy of function instead of referencing it doesn't make any sense unless we need to access parent scope.
So let me get this straight, calling a function with a dot operator, i.e.

foo.bar();

will create a copy of that function each time it's called.

However, setting a variable with a dot operator, i.e.

foo.bar = 1;

won't create a copy of the variable each time it's set/used?
__________________

Lord of the Rings Online
75 Fourohfour | 75 Artemedis | 60 Whiskeytango Foxtrot | 50 Mistah Boombastic | 56 Appetizer | 25 Aggromi
61 Onepointtwentyone Gigawatts


World of Warcraft
90 Downlo 85 Gravetaxi 85 Ümad 85 Artemedis 85 Guthuros
Reply With Quote
  #13  
Unread 10-08-2010, 09:49 AM
Kryso Kryso is offline
The Undefeated
 
Join Date: Oct 2010
Posts: 8
What? no no no

calling given function with dot operator won't create anything by itself. But the function that created function so we can call it with dot operator and valid self reference will. Example:

Code:
-- Class
Foo = class();

function Foo:Constructor()
    self.num = 0;

    self.Bar = function( increment )
        -- here we can access "self" because we take it from parent scope
        self.num = self.num + increment;
    end   
end

-- Test init
print = Turbine.Shell.WriteLine;

-- Testing code
local instance1 = Foo();
-- those calls won't create anything and we must call this function with ".", ":" would break it

print(" ");
print("Testing . operator")
instance1.Bar( 1 );
instance1.Bar( 2 );
instance1.Bar( 3 );
print( " - " .. tostring( instance1.num ) );

print(" ");
print("Testing : operator")
success, message = pcall( function() instance1:Bar( 3 ); end );
if ( not success ) then
	print( " - Error: " .. message );
end

print(" ");
print("Testing memory wastage")
local instance2 = Foo();
-- however here, "Bar" function would be created again, which leads to increased memory usage
if ( instance2.Bar ~= instance1.Bar ) then
    print( " - functions are not same!" );
end

print(" ");

But in general you don't want to do this. When you need reference to "self" (which is just standardized argument name) use either ":" operator or put self as first argument. Example

Code:
Foo = class();

Foo.Constructor = function( self )
    self.secret = "123456789";
end

Foo.Bar = function( this )
    -- now there wouldn't be any "self" but "this" instead (holding the same reference).. it is against the standard, but it can come in handy sometime
    Turbine.Shell.WriteLine( this.secret );
end

function Foo:Smth()
    Turbine.Shell.WriteLine( self.secret );
end

local instance = Foo();
instance:Bar();
instance.Bar( instance );
instance:Smth();
instance.Smth( instance );
Reply With Quote
  #14  
Unread 10-08-2010, 10:06 AM
Digital_Utopia's Avatar
Digital_Utopia Digital_Utopia is offline
The Undying
Interface Author - Click to view interfaces
 
Join Date: Sep 2010
Posts: 207
Send a message via MSN to Digital_Utopia Send a message via Yahoo to Digital_Utopia
Okay, so you're basically saying that there's really no need to duplicate the function itself, and by sticking with just using "self" for variables, it would have the same effect, with less memory usage.

Do I have this right?

If so, one question. If you only create one instance of a class, and use:

self.Foo=function()

how many copies of that function are created? Would it just be one, or would there be two? This isn't some kind of justification either - I'm just curious how it would work. Obviously conserving memory should be a priority.

Of course, that does bring into question why Turbine chooses to do events eg:

Foo.MouseClick = function (sender,args)

with the dot operator instead of the colon.
__________________

Lord of the Rings Online
75 Fourohfour | 75 Artemedis | 60 Whiskeytango Foxtrot | 50 Mistah Boombastic | 56 Appetizer | 25 Aggromi
61 Onepointtwentyone Gigawatts


World of Warcraft
90 Downlo 85 Gravetaxi 85 Ümad 85 Artemedis 85 Guthuros
Reply With Quote
  #15  
Unread 10-08-2010, 11:07 AM
Kryso Kryso is offline
The Undefeated
 
Join Date: Oct 2010
Posts: 8
If that class would be singleton (only one instance across whole application), then it would create only one function. However it is still better to use self.Foo = function( self ) so you don't have to remember whether you must call it with "." or ":" and always call every function on instance with ":". Also I'm not saying that you shouldn't create functions with "." operator, I'm talking about creating functions inside of function (which is not always bad.. sometimes it's neccessary, but if you don't have to then don't do it) and using always "self" when that function is going to be member of class.

Code:
Foo = class();
Foo.Constructor = function( self )

end

Foo.Bar = function( self, arg )

end
is exactly the same as
Code:
Foo = class();
function Foo:Constructor = function()

end

function Foo:Bar( arg )

end
and would work same as
Code:
Foo = class();
function Foo:Constructor()
    self.Bar = function( self, arg )

    end
end
or
Code:
Foo = class();
function Foo:Constructor()
    function self:Bar( arg )
        
    end
end
but the last 2 would eat more memory than the first 2 after creating more than 1 instance. The difference is small, but when you put 10000 small things together, they make one big thing so it's good to know how things work (try this http://www.lua.org/pil/16.html#ObjectSec )

Events are different thing. You need to do it like this, because you are changing function on another instance - so function foo:MouseClick( args ) would work too, just "sender" would be named "self" and you would loose "self" reference from parent scope.

Also note that lua has no support for events, so what we call events are just plain functions.

Last edited by Kryso : 10-08-2010 at 11:22 AM.
Reply With Quote
  #16  
Unread 10-08-2010, 11:59 AM
Digital_Utopia's Avatar
Digital_Utopia Digital_Utopia is offline
The Undying
Interface Author - Click to view interfaces
 
Join Date: Sep 2010
Posts: 207
Send a message via MSN to Digital_Utopia Send a message via Yahoo to Digital_Utopia
Quote:
Originally Posted by Kryso
If that class would be singleton (only one instance across whole application), then it would create only one function. However it is still better to use self.Foo = function( self ) so you don't have to remember whether you must call it with "." or ":" and always call every function on instance with ":". Also I'm not saying that you shouldn't create functions with "." operator, I'm talking about creating functions inside of function (which is not always bad.. sometimes it's neccessary, but if you don't have to then don't do it) and using always "self" when that function is going to be member of class.

Code:
Foo = class();
Foo.Constructor = function( self )

end

Foo.Bar = function( self, arg )

end
is exactly the same as
Code:
Foo = class();
function Foo:Constructor = function()

end

function Foo:Bar( arg )

end
and would work same as
Code:
Foo = class();
function Foo:Constructor()
    self.Bar = function( self, arg )

    end
end
or
Code:
Foo = class();
function Foo:Constructor()
    function self:Bar( arg )
        
    end
end
but the last 2 would eat more memory than the first 2 after creating more than 1 instance. The difference is small, but when you put 10000 small things together, they make one big thing so it's good to know how things work (try this http://www.lua.org/pil/16.html#ObjectSec )

Events are different thing. You need to do it like this, because you are changing function on another instance - so function foo:MouseClick( args ) would work too, just "sender" would be named "self" and you would loose "self" reference from parent scope.

Also note that lua has no support for events, so what we call events are just plain functions.
Okay, well that makes sense. Thanks for the explanation
__________________

Lord of the Rings Online
75 Fourohfour | 75 Artemedis | 60 Whiskeytango Foxtrot | 50 Mistah Boombastic | 56 Appetizer | 25 Aggromi
61 Onepointtwentyone Gigawatts


World of Warcraft
90 Downlo 85 Gravetaxi 85 Ümad 85 Artemedis 85 Guthuros
Reply With Quote
  #17  
Unread 10-08-2010, 06:14 PM
SanDBoX's Avatar
SanDBoX SanDBoX is offline
The Undying
Interface Author - Click to view interfaces
 
Join Date: Sep 2010
Location: Idaho
Posts: 40
Okay, that was a whole lot more exposition then I was expecting, but that is really good information! Defiantly something to remember!
As mentioned before, the “events” that Turbine built into the API, would it be better practice to assign them inside the class Constructor, or outside with the rest of the functions?
And On the topic of memory usage how likely are we going to run into a problem with our plugins eating too much memory? I know Digital Utopia has a very specific instance that it can and probably will have a problem, but what about the rest of us not working with image files? Because, yea, if it is likely I think my next "release" will be mostly just memory management cleanup.
Reply With Quote
  #18  
Unread 10-08-2010, 07:23 PM
Kryso Kryso is offline
The Undefeated
 
Join Date: Oct 2010
Posts: 8
As I posted earlier - it's really small thing. You probably won't run into problems with too high memory usage, unless you work with tons of images that are currently bugged. I personally prefer to create events within constructor because of "self" reference from parent scope. There won't be any problems with memory, until you create new function many times per second or create enormous amount of instances - but you generally want to keep your application as clean as you can. Also I don't know how often lotro client collects garbage in lua - in wow it was once a few minutes, so even non-statistical addons could easily eat megabytes of memory sometimes. Good example would be some bufftimer - if you are going to create new object with buttload new functions on every update and not cache anything you will eat huge amount of memory in some situations. Also creating function doesn't eat only memory, but also processor time, but again it's really small thing.

To sum it up, feel free use all features of language even at expense of some performance, but be smart. Good trade is when you get something back from the performance loss, bad thing is throw performance away and not get anything from it. As example take this: http://forums.lotro.com/showthread.p...proved-classes
Sure, there is some performance loss because of function call on __index and __newindex but hey, I won't spend hours of debugging because I forgot to call base constructor ever again ;p
Reply With Quote
  #19  
Unread 10-08-2010, 07:44 PM
SanDBoX's Avatar
SanDBoX SanDBoX is offline
The Undying
Interface Author - Click to view interfaces
 
Join Date: Sep 2010
Location: Idaho
Posts: 40
I wont look too deep into my memory management then, maybe a little next time I do a code cleanup.
Reply With Quote
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
graphics issue Jeremy3020 Interface Help (L) 0 09-21-2010 08:50 PM
Frosty! I cannot reposition any assets inside the Minimap_Window (Radar)! Supermax XML modification help (L) 11 05-27-2009 02:25 PM
Trait Panel Race/Class galenswerd Graphics modification help (L) 4 01-13-2009 12:32 PM
letterbox_bottom xp bar issue Aalwein General Authoring Discussion (L) 2 05-15-2007 08:55 AM
A anoying issue aegget Graphics modification help (L) 5 05-10-2007 06:20 AM


All times are GMT -5. The time now is 03:15 AM.


Our Network
EQInterface | EQ2Interface | Minion | WoWInterface | ESOUI | LoTROInterface | MMOUI | Swtorui