Hello,
Thank for all your help so far. I have two more questions:
1. Is it less efficient if I expand a list before providing it as an argument for init?
set myList [list 1 2 3 4]
MyClass myObject $myList
vs
eval MyClass myObject $myList
2. When do I need to create a custom destructor? I create objects inside init - do I have to do that in this case, or will those object be destroyed automatically when I destroy their parent?
MyClass instproc init args {
my contains { MySecondClass innerObject } }
Best Regards, Krzysztof
Krzysztof,
- Is it less efficient if I expand a list before providing it as an
argument for init?
set myList [list 1 2 3 4]
MyClass myObject $myList
vs
eval MyClass myObject $myList
well, it depends on what you want to achieve. Is it just about boxing the arguments in a list and then, for further processing unboxing it (e.g., in the init body?). Or are the values treated as a list in follow-up steps?
the script below sheds some light on various scenarios (you can run it to reproduce on your machine; timing in microsecs per iteration, 10000 iterations each):
t.001: 26.2 mms, MyClass myObject $myList; set ::out t.002: 32.6 mms, eval MyClass myObject $myList; set ::out t.003: 26.9 mms, MyClass myObject 1 2 3 4; set ::out t.004: 26.0 mms, MyClass myObject {*}$myList; set ::out
from this bird eye perspective (and without knowing the details of your scenario), you might want to consider avoiding the [eval] overhead by using the {*} operator in 8.5+ for the boxing case ...
(t.003 is a kind of baseline measurement and appears slightly more expensive because the values in the argument vector must be turned into Tcl_Objs first etc., a conversion which has already been achieved if dealing with a [list] and its values).
- When do I need to create a custom destructor? I create objects inside
init - do I have to do that in this case, or will those object be destroyed automatically when I destroy their parent?
MyClass instproc init args {
my contains { MySecondClass innerObject } }
The deletion of parents cascades. So there is no need for a custom destructor on a parent to deal with its kids.
//stefan
Best Regards, Krzysztof
Xotcl mailing list Xotcl@alice.wu-wien.ac.at http://alice.wu-wien.ac.at/mailman/listinfo/xotcl
Hello Stefan,
On 02/08/2011 09:58 AM, Stefan Sobernig wrote:
t.001: 26.2 mms, MyClass myObject $myList; set ::out t.002: 32.6 mms, eval MyClass myObject $myList; set ::out t.003: 26.9 mms, MyClass myObject 1 2 3 4; set ::out t.004: 26.0 mms, MyClass myObject {*}$myList; set ::out
from this bird eye perspective (and without knowing the details of your scenario), you might want to consider avoiding the [eval] overhead by using the {*} operator in 8.5+ for the boxing case ...
(t.003 is a kind of baseline measurement and appears slightly more expensive because the values in the argument vector must be turned into Tcl_Objs first etc., a conversion which has already been achieved if dealing with a [list] and its values).
Thank you for this example. I forgot to mention that my application will, in some cases, create argument list that may be long (few thousand integer values). I expect it to handle up to 7200 values that are integers (2 digits maximum). Is it a bad idea to expand that list and pass 7200 arguments to init?
In this example it appears that it is actually better to expend the list using {*}, than to pass it as a value?
Best regards,
On 02/08/2011 09:58 AM, Stefan Sobernig wrote:
t.001: 26.2 mms, MyClass myObject $myList; set ::out t.002: 32.6 mms, eval MyClass myObject $myList; set ::out t.003: 26.9 mms, MyClass myObject 1 2 3 4; set ::out t.004: 26.0 mms, MyClass myObject {*}$myList; set ::out
from this bird eye perspective (and without knowing the details of your scenario), you might want to consider avoiding the [eval] overhead by using the {*} operator in 8.5+ for the boxing case ...
(t.003 is a kind of baseline measurement and appears slightly more expensive because the values in the argument vector must be turned into Tcl_Objs first etc., a conversion which has already been achieved if dealing with a [list] and its values).
Thank you for this example. I forgot to mention that my application will, in some cases, create argument list that may be long (few thousand integer values). I expect it to handle up to 7200 values that are integers (2 digits maximum).
This changes the picture. If you look at my examples, they assume that you want to turn each list value a value to a proper method parameter and so into a local variable in the init body ($a, $b, $c, ...). This is certainly not the case here ...
What is going to happen to with this data vector in init? Why do you want to treat each value of this vector as a method parameter of init?
Is it a bad idea to expand that list and pass 7200 arguments to init?
Let me rephrase the question: Is it a bad idea to have a method with 7200 method parameters :) Besides: The # of method parameter of init would have to change which each call, depending on the size of your data vector.
One might think of using args on init, but args simply boxes a variable argument vector into a single Tcl list. So why not pass the data vector as a single list value right from the beginning?
In this example it appears that it is actually better to expend the list using {*}, than to pass it as a value?
Only and only *iff* you want to treat each list value as a method parameter. In your scenario, it is more likey a data vector which is to be addressed by a single handle:
MyClass instproc init {v} { foreach value $v { # do sth. to each of the 7200 values } }
//stefan