Skip to content

Backwards compatibility for oo.tcl #293

@prpr19xx

Description

@prpr19xx

Following on from #248...

Before 5af9d6a, this worked without complaint:

. package require oo
1.0
. class t {v1 0 v2 0}
t
. set v [t new {v1 1 v3 3}]
::<reference.<t______>.00000000000000000002>
. $v get v1
1
. $v get v2
0

Since then, it generates an error:
t defaultconstructor, v3 is not a class variable

I don't care about v3, I just don't want it to cause any errors (this is a much simplified test-case whereas in reality there are many variables I'm not interested in, but it's huge work to sort in our existing code).
As a workaround, I have been manually patching out the "return -code error..." statement that causes it to fail, restoring previous behaviour.
But I'd rather not have to patch at all, and it would seem that this is fairly easily fixed by adding something like the following change to allow selectable behaviour:

diff --git a/oo.tcl b/oo.tcl
index 4fefa9c..96fca14 100644
--- a/oo.tcl
+++ b/oo.tcl
@@ -1,4 +1,5 @@
 # OO support for Jim Tcl, with multiple inheritance
+set ::oo::ignore_invalid_vars false

 # Create a new class $classname, with the given
 # dictionary as class variables. These are the initial
@@ -81,11 +82,14 @@ proc class {classname {baseclasses {}} classvars} {
        $classname method defaultconstructor {{__vars {}}} {
                set __classvars [$self classvars]
                foreach __v [dict keys $__vars] {
-                       if {![dict exists $__classvars $__v]} {
-                               # level 3 because defaultconstructor is called by new
-                               return -code error -level 3 "[lindex [info level 0] 0], $__v is not a class variable"
+                       if {[dict exists $__classvars $__v]} {
+                               set $__v [dict get $__vars $__v]
+                       } else {
+                               if {!$::oo::ignore_invalid_vars} {
+                                       # level 3 because defaultconstructor is called by new
+                                       return -code error -level 3 "[lindex [info level 0] 0], $__v is not a class variable"
+                               }
                        }
-                       set $__v [dict get $__vars $__v]
                }
        }
        alias "$classname constructor" "$classname defaultconstructor"

This maintains the current behaviour, but allows regression to the previous e.g.

. package require oo
1.0
. puts $::oo::ignore_invalid_vars
false
. class t {v1 0 v2 0}
t
. set v [t new {v1 1 v3 3}]
t defaultconstructor, v3 is not a class variable
[error] . 
. set ::oo::ignore_invalid_vars true
true
. set v [t new {v1 1 v3 3}]
::<reference.<t______>.00000000000000000002>
. $v get v1
1
. $v get v2
0

There may be a better way, but this works for me.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions