View · Search · Index
No registered users in community xowiki
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
-- 
Univ.Prof. Dr.Gustaf Neumann
Abteilung für Wirtschaftsinformatik
WU-Wien, Augasse 2-6, 1090 Wien