No registered users in community xowiki
in last 10 minutes
in last 10 minutes
Re: [Xotcl] Bug or feature in 1.1.1. Access to subobjects
From: Gustaf Neumann <neumann_at_wu-wien.ac.at>
Date: Tue, 30 Dec 2003 18:19:04 +0100
On Tuesday 30 December 2003 12:25, Artur Trzewik wrote:
> Hi!
>
> I have discovered some interesting change in 1.1.1 that I could not find in
> ChangeLog.
Artur, you discovered this change not in version 1.1.1, but in the
pre-release of version 1.1.2, that i have sent to you a few days ago.
The change is documented in the Changelog of 1.1.2
> In 1.1.1 one can access to subobject as method call
> Example
> b::a
> can be produced as
> b a
> My problem is that I have "a" as method and as subobject from b.
There are several rationales for this:
* Background:
In general Tcl distinguishes between procs and commands,
where the fist ones are defined in tcl and the others in C.
If you define a proc/command, then you are overwriting
potentially a command/proc.
Objects and classes are commands in xotcl. Every
Object builds a namespace (not necessarily a
tcl-namespace) in xotcl , in which the procs, subcommands
and subobjects of the object are stored.
The situation in versions up to 1.1.1 was a follows
Object o
o proc a {} {puts "i am proc a"}
o a ;# prints i am proc a
Object o::a
o a ;# error message: o: unable to dispatch method 'a'
The created Object has overwritten the proc a, since it occupies
slot "a" in the command table of object o. The same happens
as well when a proc is overwriting an object, the same situation
happens as well with other subcommands (not only procs) of
the object.
So the situation is quite bad, since the sub-object
- can delete procs/commands
- it cannot be called directly
- it breaks in invariant: an (sub)object is a (sub)command and
can be called exactly like it.
There are several useful scenarios for the new behavior.
* one can use xotcl objects to define commands with subcommands,
where the object forms the "main command" and the procs/commands
define the subcommands. For example one can defined a specialized
version of Tcl's file-command (say ns::file) like in the following:
namespace eval ns {
Object file
file proc tail name {
set tail [file tail $name]
regexp {[^/\\]+$} $tail tail
return $tail
}
file proc unknown {subcmd args} {
return eval ::file $subcmd $args
}
}
The neat thing is that it is possible
- to redefine sub-commands via procs (instead of a large
and hard-to-extend switch statement)
- to use interceptors (filters/mxins) for certain subcommands (maybe you
are only interested in "file delete")
- to extend command on the fly by defining new subcommands
- to use the unknown mechanism to produce dynamic error message
about valid subcommands.
This was possible since a long time in XOTcl; what's new in the prerelease
of 1.1.2 is that the same can be used now with sub-subcommands and so
on in a uniform way. This makes it possible, for example, to use this
mechanism for xotcl's info command as well, which is already a subcommand
of the object/class (e.g. [Object info instances].
* In many cases the programs become syntactically cleaner than
before. One can also write now instead of
Http::Wrk instproc init .... {
...
[self]::connection translation binary
....
the invocation of the subobject without [self] by:
Http::Wrk instproc init .... {
...
my connection translation binary
....
Interesting enough, in many situations the new variant
is faster as well (Artur, check out speedtest.xotcl of the 1.1.2 prerelease).
> Can I force "b" to invoke method "a" and not return subobject "a"?
The calling order is mixins before instmixins before procs/cmds
before instprocs from the classes. Therefore, the object a
shadows in your example the instprocs, which is the problem you
are facing.
well, we have currently following options implemented:
a) if you call an object by it name (without method), it returns
the name of the object. e.g.:
Class C
C instproc a {} {puts instproc-a}
C o; C o::a
puts [o::a] ;# outputs ::o::a
This is implemented via a method "defaultmethod",
puts [o::a defaultmethod] ;# outputs ::o::a
which can be redefined by the user (e.g. via proc). This method
can call other things as needed and return finally [self].
you can not do is to call the instproc a of class C via next (since
the active object is alreday ::o::a).
You can, however call from defaultmethod
::xotcl::classes::C::a directly, but this is not recommended, since
you will have the "wrong" self, etc.
b) you can define an interceptor for method a, e.g. via mixin class
c) use different nameing conventions for sub-objects, e.g.
C o; C o::_at_a
Sorry for being long, but i hope this explains the rational for the change.
best regards and all the best in the new year
-gustaf neumann
Date: Tue, 30 Dec 2003 18:19:04 +0100
On Tuesday 30 December 2003 12:25, Artur Trzewik wrote:
> Hi!
>
> I have discovered some interesting change in 1.1.1 that I could not find in
> ChangeLog.
Artur, you discovered this change not in version 1.1.1, but in the
pre-release of version 1.1.2, that i have sent to you a few days ago.
The change is documented in the Changelog of 1.1.2
> In 1.1.1 one can access to subobject as method call
> Example
> b::a
> can be produced as
> b a
> My problem is that I have "a" as method and as subobject from b.
There are several rationales for this:
* Background:
In general Tcl distinguishes between procs and commands,
where the fist ones are defined in tcl and the others in C.
If you define a proc/command, then you are overwriting
potentially a command/proc.
Objects and classes are commands in xotcl. Every
Object builds a namespace (not necessarily a
tcl-namespace) in xotcl , in which the procs, subcommands
and subobjects of the object are stored.
The situation in versions up to 1.1.1 was a follows
Object o
o proc a {} {puts "i am proc a"}
o a ;# prints i am proc a
Object o::a
o a ;# error message: o: unable to dispatch method 'a'
The created Object has overwritten the proc a, since it occupies
slot "a" in the command table of object o. The same happens
as well when a proc is overwriting an object, the same situation
happens as well with other subcommands (not only procs) of
the object.
So the situation is quite bad, since the sub-object
- can delete procs/commands
- it cannot be called directly
- it breaks in invariant: an (sub)object is a (sub)command and
can be called exactly like it.
There are several useful scenarios for the new behavior.
* one can use xotcl objects to define commands with subcommands,
where the object forms the "main command" and the procs/commands
define the subcommands. For example one can defined a specialized
version of Tcl's file-command (say ns::file) like in the following:
namespace eval ns {
Object file
file proc tail name {
set tail [file tail $name]
regexp {[^/\\]+$} $tail tail
return $tail
}
file proc unknown {subcmd args} {
return eval ::file $subcmd $args
}
}
The neat thing is that it is possible
- to redefine sub-commands via procs (instead of a large
and hard-to-extend switch statement)
- to use interceptors (filters/mxins) for certain subcommands (maybe you
are only interested in "file delete")
- to extend command on the fly by defining new subcommands
- to use the unknown mechanism to produce dynamic error message
about valid subcommands.
This was possible since a long time in XOTcl; what's new in the prerelease
of 1.1.2 is that the same can be used now with sub-subcommands and so
on in a uniform way. This makes it possible, for example, to use this
mechanism for xotcl's info command as well, which is already a subcommand
of the object/class (e.g. [Object info instances].
* In many cases the programs become syntactically cleaner than
before. One can also write now instead of
Http::Wrk instproc init .... {
...
[self]::connection translation binary
....
the invocation of the subobject without [self] by:
Http::Wrk instproc init .... {
...
my connection translation binary
....
Interesting enough, in many situations the new variant
is faster as well (Artur, check out speedtest.xotcl of the 1.1.2 prerelease).
> Can I force "b" to invoke method "a" and not return subobject "a"?
The calling order is mixins before instmixins before procs/cmds
before instprocs from the classes. Therefore, the object a
shadows in your example the instprocs, which is the problem you
are facing.
well, we have currently following options implemented:
a) if you call an object by it name (without method), it returns
the name of the object. e.g.:
Class C
C instproc a {} {puts instproc-a}
C o; C o::a
puts [o::a] ;# outputs ::o::a
This is implemented via a method "defaultmethod",
puts [o::a defaultmethod] ;# outputs ::o::a
which can be redefined by the user (e.g. via proc). This method
can call other things as needed and return finally [self].
you can not do is to call the instproc a of class C via next (since
the active object is alreday ::o::a).
You can, however call from defaultmethod
::xotcl::classes::C::a directly, but this is not recommended, since
you will have the "wrong" self, etc.
b) you can define an interceptor for method a, e.g. via mixin class
c) use different nameing conventions for sub-objects, e.g.
C o; C o::_at_a
Sorry for being long, but i hope this explains the rational for the change.
best regards and all the best in the new year
-gustaf neumann
-- Univ.Prof. Dr.Gustaf Neumann Abteilung für Wirtschaftsinformatik WU-Wien, Augasse 2-6, 1090 Wien