From: MartinLemburg on
Hi,

I just started to try TclOO and using OO until now only in C++, I
really miss the ability to define operators for "system internal
actions".

I didn't find until now the ability to define e.g. a "==" or "eq"
operator, so that an object can be tested for equality not using its
"address", but a kind of algorithm hided within the object.

Did I miss something or is something similar planed to be done in the
near future?

Or is my OO thinking too much influenced from my C++ work? (wouldn't
be that surprising!)

Best regards,

Martin
From: George Petasis on
στις 15/2/2010 13:38, O/H MartinLemburg(a)Siemens-PLM έγραψε:
> Hi,
>
> I just started to try TclOO and using OO until now only in C++, I
> really miss the ability to define operators for "system internal
> actions".
>
> I didn't find until now the ability to define e.g. a "==" or "eq"
> operator, so that an object can be tested for equality not using its
> "address", but a kind of algorithm hided within the object.
>
> Did I miss something or is something similar planed to be done in the
> near future?
>
> Or is my OO thinking too much influenced from my C++ work? (wouldn't
> be that surprising!)
>
> Best regards,
>
> Martin

Dear Martin,

Have you tried to define a method named == ?

package require TclOO

oo::class create A {

method == {obj} {
return false
}

export ==
}

set a [A new]
set b [A new]

puts [$a == $b]

George
From: MartinLemburg on
Hi George,

I don't mind calling a method "==" or "isEqual" or "foo"!

But I do mind, if I can use an object within an expression or other
contexts without doing too much work!

One thing coming to my mind was something like a class having several
"cast" methods ...

% oo::class create foo {
variable m_value;

constructor {value} {
my variable m_value;

set m_value $value;

if {[string is double -strict $value]} {
oo::objdefine [self] method AsDouble {} [list return
[expr {double($value)}]];

if {[string is integer -strict $value]} {
oo::objdefine [self] method AsInt {} [list return
[expr {int($value)}]];
oo::objdefine [self] method AsWide {} [list return
[expr {wide($value)}]];
} elseif {[string is wide -strict $value]} {
oo::objdefine [self] method AsWide {} [list return
[expr {wide($value)}]];
}
}

if {[string is boolean -strict $value]} {
oo::objdefine [self] method AsBool {} [list return
[string is true -strict $value]];
}

oo::objdefine [self] method AsString {} [list return
[string toupper $value]];
}
}
::foo
% foo create obj 3
::obj
% expr {int(obj)/double(obj)}; # bare word obj is not a function,
but an "object" having AsInt and AsDouble methods
1.0
% expr {int(obj)/int(obj)}
1
% foo create obj2 10
::obj2
% foo create obj3 1
::obj3
% lsort -integer [list obj obj2 obj3]
obj3 obj obj2
% lsort [list obj obj2 obj3]
obj3 obj2 obj
% lsort -dictionary [list obj obj2 obj3]
obj3 obj obj2

I know the example above is not really tcl'ish, but IMHO it would be
very nice to have data related behavior controlled by probably defined
and implicitly used "cast" methods.

Using the class/object from above more tcl'ish would be:

% expr {[obj AsInt]/[obj AsDouble]}
1.0
% expr {[obj AsInt]/[obj AsInt]}
1
% set sortCmd {apply {{cast o1 o2} {
if {[$o1 AsInt] < [$o2 AsInt]} {
return -1;
} elseif {[$o1 AsInt] > [$o2 AsInt]} {
return 1;
}

return 0;
}}}; puts ""
% lsort -command [list $sortCmd AsInt] {obj obj2 obj3}
obj3 obj obj2
% lsort -command [list $sortCmd AsString] {obj obj2 obj3}
obj3 obj2 obj
% lsort -command {apply {{o1 o2} {
set v1 [$o1 AsString];
set v2 [$o2 AsString];

if {$v1 eq $v2} {
return 0;
}

set sorted [lsort -dictionary [list $v1 $v2]];
set first [lindex $sorted 0];

if {$first eq $v1} {
return -1;
}

return 1;
}}} {obj obj2 obj3}
obj3 obj obj2

The more I write this, the more a german word (more slang word) comes
to my mind (meaning something like silly/crazy) "spinnert".
But on the other hand even in C++ I always liked cast operators! :(

Any opinions?

Best regards,

Martin Lemburg

George Petasis schrieb:
> στις 15/2/2010 13:38, O/H MartinLemburg(a)Siemens-PLM έγραψε:
> > Hi,
> >
> > I just started to try TclOO and using OO until now only in C++, I
> > really miss the ability to define operators for "system internal
> > actions".
> >
> > I didn't find until now the ability to define e.g. a "==" or "eq"
> > operator, so that an object can be tested for equality not using its
> > "address", but a kind of algorithm hided within the object.
> >
> > Did I miss something or is something similar planed to be done in the
> > near future?
> >
> > Or is my OO thinking too much influenced from my C++ work? (wouldn't
> > be that surprising!)
> >
> > Best regards,
> >
> > Martin
>
> Dear Martin,
>
> Have you tried to define a method named == ?
>
> package require TclOO
>
> oo::class create A {
>
> method == {obj} {
> return false
> }
>
> export ==
> }
>
> set a [A new]
> set b [A new]
>
> puts [$a == $b]
>
> George
From: Donal K. Fellows on
On 15 Feb, 11:38, "MartinLemburg(a)Siemens-PLM"
<martin.lemburg.siemens-...(a)gmx.net> wrote:
> I didn't find until now the ability to define e.g. a "==" or "eq"
> operator, so that an object can be tested for equality not using its
> "address", but a kind of algorithm hided within the object.
>
> Did I miss something or is something similar planed to be done in the
> near future?

I was not planning to do this. An equivalence comparison method could
be added, though given TclOO's state model it would have to default to
being equality of object names (or namespace names), but I don't
really see a lot of need since Tcl's objects are higher-level entities
anyway.

I'm definitely not going to work on plugging into the expression
operator system. That's a part of Tcl that currently requires hacking
inside tclExecute.c (or writing your own expression parser) to change
at all, so is not recommended for, well, anyone at all.

> Or is my OO thinking too much influenced from my C++ work? (wouldn't
> be that surprising!)

It is rather C++ish. :-) But we can steal a few leaves out of Java's
book here (and also use the fact that all classes are modifiable after
the fact). Here's an example to get you started:

oo::define oo::object {
method == object {string equal [self] [namespace which $object]}
# Does not start with lower-case letter, so not exported by
default
# Thus we must export it here for it to be part of public API
export ==
}

set o1 [oo::object new]
set o2 $o1
set o3 [oo::object new]
puts [$o1 == $o2],[$o1 == $o3],[oo::class == oo::object]
puts [[info object class $o1] == oo::object]

Note that the “==” method is just an ordinary method. Nothing special
at all. :-)

Donal.
From: Georgios Petasis on
Dear Martin,

I think that all these are doable, at least from the C level.
But you have to check whether implementing them justifies the effort.

The easier of all, it to modify the behavior of expr. Since all expr
functions are commands in the ::tcl::mathfunc namespace, they can be
modified:

rename ::tcl::mathfunc::int ::tcl::mathfunc::int_original

proc ::tcl::mathfunc::int {argument} {
## Check if argument is an object. If it is, return the proper value.
## If it is not, just return the original behavior:
return [::tcl::mathfunc::int_original]
}

If you want objects to be able to be casted to integers or strings, then
you need to create a custom tcl object type (from C), that can hold a
tcloo object. This way, when a conversion is requested by Tcl internals,
you can arrange to call a method from the object.

But what will be the added value of all these?

George

στις 15/2/2010 17:25, O/H MartinLemburg(a)Siemens-PLM έγραψε:
> Hi George,
>
> I don't mind calling a method "==" or "isEqual" or "foo"!
>
> But I do mind, if I can use an object within an expression or other
> contexts without doing too much work!
>
> One thing coming to my mind was something like a class having several
> "cast" methods ...
>
> % oo::class create foo {
> variable m_value;
>
> constructor {value} {
> my variable m_value;
>
> set m_value $value;
>
> if {[string is double -strict $value]} {
> oo::objdefine [self] method AsDouble {} [list return
> [expr {double($value)}]];
>
> if {[string is integer -strict $value]} {
> oo::objdefine [self] method AsInt {} [list return
> [expr {int($value)}]];
> oo::objdefine [self] method AsWide {} [list return
> [expr {wide($value)}]];
> } elseif {[string is wide -strict $value]} {
> oo::objdefine [self] method AsWide {} [list return
> [expr {wide($value)}]];
> }
> }
>
> if {[string is boolean -strict $value]} {
> oo::objdefine [self] method AsBool {} [list return
> [string is true -strict $value]];
> }
>
> oo::objdefine [self] method AsString {} [list return
> [string toupper $value]];
> }
> }
> ::foo
> % foo create obj 3
> ::obj
> % expr {int(obj)/double(obj)}; # bare word obj is not a function,
> but an "object" having AsInt and AsDouble methods
> 1.0
> % expr {int(obj)/int(obj)}
> 1
> % foo create obj2 10
> ::obj2
> % foo create obj3 1
> ::obj3
> % lsort -integer [list obj obj2 obj3]
> obj3 obj obj2
> % lsort [list obj obj2 obj3]
> obj3 obj2 obj
> % lsort -dictionary [list obj obj2 obj3]
> obj3 obj obj2
>
> I know the example above is not really tcl'ish, but IMHO it would be
> very nice to have data related behavior controlled by probably defined
> and implicitly used "cast" methods.
>
> Using the class/object from above more tcl'ish would be:
>
> % expr {[obj AsInt]/[obj AsDouble]}
> 1.0
> % expr {[obj AsInt]/[obj AsInt]}
> 1
> % set sortCmd {apply {{cast o1 o2} {
> if {[$o1 AsInt]< [$o2 AsInt]} {
> return -1;
> } elseif {[$o1 AsInt]> [$o2 AsInt]} {
> return 1;
> }
>
> return 0;
> }}}; puts ""
> % lsort -command [list $sortCmd AsInt] {obj obj2 obj3}
> obj3 obj obj2
> % lsort -command [list $sortCmd AsString] {obj obj2 obj3}
> obj3 obj2 obj
> % lsort -command {apply {{o1 o2} {
> set v1 [$o1 AsString];
> set v2 [$o2 AsString];
>
> if {$v1 eq $v2} {
> return 0;
> }
>
> set sorted [lsort -dictionary [list $v1 $v2]];
> set first [lindex $sorted 0];
>
> if {$first eq $v1} {
> return -1;
> }
>
> return 1;
> }}} {obj obj2 obj3}
> obj3 obj obj2
>
> The more I write this, the more a german word (more slang word) comes
> to my mind (meaning something like silly/crazy) "spinnert".
> But on the other hand even in C++ I always liked cast operators! :(
>
> Any opinions?
>
> Best regards,
>
> Martin Lemburg
>
> George Petasis schrieb:
>> στις 15/2/2010 13:38, O/H MartinLemburg(a)Siemens-PLM έγραψε:
>>> Hi,
>>>
>>> I just started to try TclOO and using OO until now only in C++, I
>>> really miss the ability to define operators for "system internal
>>> actions".
>>>
>>> I didn't find until now the ability to define e.g. a "==" or "eq"
>>> operator, so that an object can be tested for equality not using its
>>> "address", but a kind of algorithm hided within the object.
>>>
>>> Did I miss something or is something similar planed to be done in the
>>> near future?
>>>
>>> Or is my OO thinking too much influenced from my C++ work? (wouldn't
>>> be that surprising!)
>>>
>>> Best regards,
>>>
>>> Martin
>>
>> Dear Martin,
>>
>> Have you tried to define a method named == ?
>>
>> package require TclOO
>>
>> oo::class create A {
>>
>> method == {obj} {
>> return false
>> }
>>
>> export ==
>> }
>>
>> set a [A new]
>> set b [A new]
>>
>> puts [$a == $b]
>>
>> George