Itcl - the [incr Tcl] extension

View Ticket
Login
Ticket Hash: 15f7db53b9f36d978ce732685ac868ee06fbb216
Title: Different behavior for Itcl 4 and Itcl 3
Status: Open Type: Code_Defect
Severity: Important Priority: Immediate
Subsystem: Resolution: Open
Last Modified: 2019-10-15 12:53:18
Version Found In: 4.1.1
User Comments:
anonymous added on 2018-03-17 20:52:42:
Hi! Appears that the following code behaves differently in Itcl 3 and 4:

itcl::class a {
    constructor {args} {}
    public method a {}
}

itcl::body a::constructor {args} {
    puts "a::constructor $args"
    b ::newb
}

itcl::body a::a {} {
    puts "a::a"
}

itcl::class b {
    constructor {args} {}
}

itcl::body b::constructor {args} {
    puts "b::constructor $args"
    a::a
}

a newa

(it's a minimal example which reproduces the problem). Specifically, in Itcl 3 the code works fine and prints

a::constructor 
b::constructor 
a::a

but in Itcl 4 it emits the error:

a::constructor 
b::constructor 
bad option "a": should be one of...
  newb cget -option
  newb configure ?-option? ?value -option value...?
  newb isa className
    while executing
"a::a"
    while constructing object "::newb" in ::b::constructor (body line 4)
    invoked from within
"::itcl::parser::handleClass b ::b ::newb"
    invoked from within
"b ::newb"
    while constructing object "::newa" in ::a::constructor (body line 4)
    invoked from within
"::itcl::parser::handleClass a ::a newa"
    invoked from within
"a newa"
    (file "test.tcl" line 28)

For some reason a::a tries to find method a in class b and fails.

dgp added on 2018-03-20 13:23:06:
This code example makes no sense to me.

What does an Itcl 3 programmer expect a 
command [a::a] to do in that context?

Best I can guess this is an ill-conceived
attempt to reach into and abuse the particular
implementation of Itcl 3, which Itcl 4 does not
reproduce.

I could be wrong though, I'm not a user of Itcl 3,
and don't know the full set of programming
expectations its users have.

dgp added on 2018-03-20 13:25:00:
That said, the Itcl 4 reaction is at best a
confusing and completely wrong error message,
so there's something to look into.

dgp added on 2018-03-20 13:38:39:
If you want objects of class b to have a
usable method a that is the same as the
method a of class a, seems to me the
proper Itcl programming tool to use is
inherit to get same behavior in Itcl 3 and 4.

class b {
    inherit a
    ...
}

dgp added on 2018-03-20 13:43:08:
It appears that both Itcl 3 and Itcl 4 have
this command access to a method in place.
In Itcl 4, though, every Itcl object is a
TclOO object and every Itcl method is a
TclOO method, so when you try to invoke a
TclOO method (even through a command backdoor access)
on a TclOO object that lacks that method, the
access restrictions of TclOO catch that and
report the error.

I don't have a strong sense whether this is
stopping something that was never a good idea
to begin with, or whether it is exposing that
TclOO and Itcl have even more deeply fundamental
disagreements about their very models of operation
than was ever appreciated, and that in a deep
sense the Itcl 4 project of building Itcl on top
of a TclOO foundation is just unworkable.

schmitzu added on 2019-10-15 12:53:18:
IMHO it's all OK with Itcl4 and Itcl3 is weak here.
What "a::a" in "b::constructor" does is calling a *method*
without an object context. This is an error. 
Either call "a" with an object, like "$obj a". Or
make "a" a *proc* of class "a". Then it's possible 
to call "a" with a class context "a::a".
I think, Itcl3 was too lenient in this case.