Search code examples
tclitcl

Itcl configure method: How to use public variables with a config script?


What is the proper way of using config scripts of public variables in Itcl?

I mean, this is what I want to do:

class MyClass {

    private variable myVar

    public method setMyVar {arg} {
        if {![string is integer -strict $arg]} {
            return -code error "argument $arg is not an integer"
        }
        set myVar $arg
    }
}

At least, this is how I would write a setter method in, say, C++. First, check the argument, and if it validates, assign it to the private variable. If the argument is not valid, leave the object state unchanged.

Now, instead of writing getter and setter methods for every internal status variable I have, I decided to rewrite the code using Itcl's configure mechanism. (I like doing things The Standard Way.)

class MyClass {
    public variable myVar 10 {
        if {![string is integer -strict $myVar]} {
            return -code error "new value of -myVar is not an integer: $myVar"
        }
    }
}

myObj configure -myVar "some string"

The problem with this approach is that the variable gets assigned even if the argument is not valid! And there is no (easy) way to revert it back to its previous value.

What is the correct way of using Itcl configure scripts? I understand they were designed for Tk widgets as a means to update the GUI when the value changes, but Tk widgets need to validate their arguments as well, don't they?


Solution

  • I suggest you upgrade to Tcl 8.6 and Itcl 4.0, where it Just Worked™ when I tried:

    % package req Itcl
    4.0.2
    % itcl::class MyClass {
        public variable myVar 10 {
            if {![string is integer -strict $myVar]} {
                # You had a minor bug here; wrong var name
                return -code error "argument $myVar is not an integer"
            }
        }
    }
    % MyClass myObj
    myObj
    % myObj cget -myVar
    10
    % myObj configure -myVar "some string"
    argument some string is not an integer
    % puts $errorInfo
    argument some string is not an integer
        (error in configuration of public variable "::MyClass::myVar")
        invoked from within
    "myObj configure -myVar "some string""
    % myObj cget -myVar
    10