• oo::class - my variable vs variable

    From Mark Summerfield@21:1/5 to All on Thu Jul 4 07:17:35 2024
    I am trying to learn TclOO. I have created two classes P and Q which
    appear to have identical behavior. Class P uses "my variable" and Q uses "variable". Can someone explain the difference between them. (I am
    familiar with Python and Go if that's any help with explaining.)

    oo::class create P {
    constructor {{x 0} {y 0}} {
    my variable x_
    my variable y_
    set x_ $x
    set y_ $y
    }

    method x {} {
    my variable x_
    return $x_
    }

    method set_x {x} {
    if {![string is integer -strict $x]} {
    throw NOT_AN_INT "x must be an int not \"$x\""
    }
    my variable x_
    set x_ $x
    }

    method y {} {
    my variable y_
    return $y_
    }
    }

    oo::class create Q {
    constructor {{x 0} {y 0}} {
    variable x_
    variable y_
    set x_ $x
    set y_ $y
    }

    method x {} {
    variable x_
    return $x_
    }

    method set_x {x} {
    if {![string is integer -strict $x]} {
    throw NOT_AN_INT "x must be an int not \"$x\""
    }
    variable x_
    set x_ $x
    }

    method y {} {
    variable y_
    return $y_
    }
    }

    puts "P"
    set p1 [P new]
    puts "p1 x=[$p1 x] y=[$p1 y]"
    $p1 set_x 5
    puts "p1 x=[$p1 x] y=[$p1 y]"
    try {$p1 set_x "invalid"} trap {} err { puts $err }
    set p2 [P new 0 -8]
    puts "p2 x=[$p2 x] y=[$p2 y]"
    $p2 set_x 17
    puts "p2 x=[$p2 x] y=[$p2 y]"
    puts "p1 x=[$p1 x] y=[$p1 y]"

    puts "Q"
    set q1 [Q new]
    puts "q1 x=[$q1 x] y=[$q1 y]"
    $q1 set_x 5
    puts "q1 x=[$q1 x] y=[$q1 y]"
    try {$q1 set_x "invalid"} trap {} err { puts $err }
    set q2 [Q new 0 -8]
    puts "q2 x=[$q2 x] y=[$q2 y]"
    $q2 set_x 17
    puts "q2 x=[$q2 x] y=[$q2 y]"
    puts "q1 x=[$q1 x] y=[$q1 y]"

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Petro Kazmirchuk@21:1/5 to Mark Summerfield on Fri Jul 5 21:47:06 2024
    On 04/07/2024 09:17, Mark Summerfield wrote:
    I am trying to learn TclOO. I have created two classes P and Q which
    appear to have identical behavior. Class P uses "my variable" and Q uses "variable". Can someone explain the difference between them. (I am
    familiar with Python and Go if that's any help with explaining.)

    oo::class create P {
    constructor {{x 0} {y 0}} {
    my variable x_
    my variable y_
    set x_ $x
    set y_ $y
    }

    method x {} {
    my variable x_
    return $x_
    }

    method set_x {x} {
    if {![string is integer -strict $x]} {
    throw NOT_AN_INT "x must be an int not \"$x\""
    }
    my variable x_
    set x_ $x
    }

    method y {} {
    my variable y_
    return $y_
    }
    }

    oo::class create Q {
    constructor {{x 0} {y 0}} {
    variable x_
    variable y_
    set x_ $x
    set y_ $y
    }

    method x {} {
    variable x_
    return $x_
    }

    method set_x {x} {
    if {![string is integer -strict $x]} {
    throw NOT_AN_INT "x must be an int not \"$x\""
    }
    variable x_
    set x_ $x
    }

    method y {} {
    variable y_
    return $y_
    }
    }

    puts "P"
    set p1 [P new]
    puts "p1 x=[$p1 x] y=[$p1 y]"
    $p1 set_x 5
    puts "p1 x=[$p1 x] y=[$p1 y]"
    try {$p1 set_x "invalid"} trap {} err { puts $err }
    set p2 [P new 0 -8]
    puts "p2 x=[$p2 x] y=[$p2 y]"
    $p2 set_x 17
    puts "p2 x=[$p2 x] y=[$p2 y]"
    puts "p1 x=[$p1 x] y=[$p1 y]"

    puts "Q"
    set q1 [Q new]
    puts "q1 x=[$q1 x] y=[$q1 y]"
    $q1 set_x 5
    puts "q1 x=[$q1 x] y=[$q1 y]"
    try {$q1 set_x "invalid"} trap {} err { puts $err }
    set q2 [Q new 0 -8]
    puts "q2 x=[$q2 x] y=[$q2 y]"
    $q2 set_x 17
    puts "q2 x=[$q2 x] y=[$q2 y]"
    puts "q1 x=[$q1 x] y=[$q1 y]"

    Sorry, can't give an exact answer, but my preference is to put member
    variables in the oo::class definition, so that in methods they are
    available automatically:

    oo::class create MyClass {
    # private member variables should be CamelCase
    variable Var1 Var2 Var3

    constructor {} {
    # initialize according to their types:
    set Var1 [list]
    set Var2 [dict create]
    array set Var3 {}
    }
    }

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Schelte@21:1/5 to Mark Summerfield on Fri Jul 5 22:26:16 2024
    On 04/07/2024 09:17, Mark Summerfield wrote:
    I am trying to learn TclOO. I have created two classes P and Q which
    appear to have identical behavior. Class P uses "my variable" and Q uses "variable". Can someone explain the difference between them. (I am
    familiar with Python and Go if that's any help with explaining.)

    When only passing one argument to each of the commands, there is no
    functional difference. I normally use "my variable" if I just want to
    access one or more instance variables in a method. I use "variable" when
    I want to initialize the variables.

    So, in the constructor of your example I would use "variable", while I'd
    use "my variable" in the methods:

    oo::class create P {
    constructor {{x 0} {y 0}} {
    variable x_ $x y_ $y
    }

    method x {} {
    my variable x_
    return $x_
    }
    }


    Schelte.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From greg@21:1/5 to All on Fri Jul 5 23:01:46 2024
    Am 04.07.24 um 09:17 schrieb Mark Summerfield:
    I am trying to learn TclOO. I have created two classes P and Q which
    appear to have identical behavior. Class P uses "my variable" and Q uses "variable". Can someone explain the difference between them. (I am
    familiar with Python and Go if that's any help with explaining.)

    oo::class create P {
    constructor {{x 0} {y 0}} {
    my variable x_
    my variable y_
    set x_ $x
    set y_ $y
    }

    method x {} {
    my variable x_
    return $x_
    }

    method set_x {x} {
    if {![string is integer -strict $x]} {
    throw NOT_AN_INT "x must be an int not \"$x\""
    }
    my variable x_
    set x_ $x
    }

    method y {} {
    my variable y_
    return $y_
    }
    }

    oo::class create Q {
    constructor {{x 0} {y 0}} {
    variable x_
    variable y_
    set x_ $x
    set y_ $y
    }

    method x {} {
    variable x_
    return $x_
    }

    method set_x {x} {
    if {![string is integer -strict $x]} {
    throw NOT_AN_INT "x must be an int not \"$x\""
    }
    variable x_
    set x_ $x
    }

    method y {} {
    variable y_
    return $y_
    }
    }

    puts "P"
    set p1 [P new]
    puts "p1 x=[$p1 x] y=[$p1 y]"
    $p1 set_x 5
    puts "p1 x=[$p1 x] y=[$p1 y]"
    try {$p1 set_x "invalid"} trap {} err { puts $err }
    set p2 [P new 0 -8]
    puts "p2 x=[$p2 x] y=[$p2 y]"
    $p2 set_x 17
    puts "p2 x=[$p2 x] y=[$p2 y]"
    puts "p1 x=[$p1 x] y=[$p1 y]"

    puts "Q"
    set q1 [Q new]
    puts "q1 x=[$q1 x] y=[$q1 y]"
    $q1 set_x 5
    puts "q1 x=[$q1 x] y=[$q1 y]"
    try {$q1 set_x "invalid"} trap {} err { puts $err }
    set q2 [Q new 0 -8]
    puts "q2 x=[$q2 x] y=[$q2 y]"
    $q2 set_x 17
    puts "q2 x=[$q2 x] y=[$q2 y]"
    puts "q1 x=[$q1 x] y=[$q1 y]"

    Hello
    if the website is not known:

    https://wiki.tcl-lang.org/page/Variables+in+TclOO

    Gregor

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Mark Summerfield@21:1/5 to Schelte on Sat Jul 6 08:54:38 2024
    On Fri, 5 Jul 2024 22:26:16 +0200, Schelte wrote:

    [snip]
    So, in the constructor of your example I would use "variable", while I'd
    use "my variable" in the methods:

    oo::class create P {
    constructor {{x 0} {y 0}} {
    variable x_ $x y_ $y
    }

    method x {} {
    my variable x_
    return $x_
    }
    }

    What I still don't understand is that in method x, _both_ "my variable"
    _and_ plain "variable" seem to work.

    In fact the only time I've needed "my" so far is in a method call. (But
    I'll read the web page that was recommended and am still working my way
    through reading Tip 257.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From et99@21:1/5 to Mark Summerfield on Sat Jul 6 18:44:04 2024
    On 7/6/2024 1:54 AM, Mark Summerfield wrote:
    On Fri, 5 Jul 2024 22:26:16 +0200, Schelte wrote:

    [snip]
    So, in the constructor of your example I would use "variable", while I'd
    use "my variable" in the methods:

    oo::class create P {
    constructor {{x 0} {y 0}} {
    variable x_ $x y_ $y
    }

    method x {} {
    my variable x_
    return $x_
    }
    }

    What I still don't understand is that in method x, _both_ "my variable"
    _and_ plain "variable" seem to work.

    In fact the only time I've needed "my" so far is in a method call. (But
    I'll read the web page that was recommended and am still working my way through reading Tip 257.)





    I don't understand this either. It appears that the my command, which comes from oo::object treats its first argument as a method, and variable like new and create are some inherited methods. The my command seems to in effect replace "my" with the obj
    you are currently running. The description in oo::object then treats that obj as the "obj" in its documentation.

    The effect seems to be that the same sort of thing occurs, a linking of the variables from a namespace into the current context. And I've read that in several places. Syntactically, however, one takes a list of variables, while the other I don't know.
    The key paragraph on the wiki is:

    "They differ importantly in how multiple arguments are treated, so be careful."

    Unfortunately, the list of hyperlinks ends there, so I don't know how they differ. At first I guessed it meant that using variable alone, one could also set values, as in the normal variable command inside a namespace. But when I tried that, it made the
    2nd argument a variable also.

    I'm afraid this overloading of the variable command has me stumped.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From greg@21:1/5 to All on Sun Jul 7 15:21:39 2024
    Am 04.07.24 um 09:17 schrieb Mark Summerfield:
    I am trying to learn TclOO. I have created two classes P and Q which
    appear to have identical behavior. Class P uses "my variable" and Q uses "variable". Can someone explain the difference between them. (I am
    familiar with Python and Go if that's any help with explaining.)


    Hello Mark,
    I have replaced your demo, hope that's OK.
    Different when there are multiple variables as arguments. Originally I
    expected the opposite behavior. I had misunderstood that until now.




    #DemoClass1 and DemoClass2
    # difference constructor with variable individually or together
    # difference output for instanceVar2, no initialization with 15 (DemoClass1) #DemoClass3 and DemoClass4
    # no difference with my variable individually or together
    # in example:
    # objx1 with my variable, x for DemoClass
    # objx2 with variable, x for DemoClass

    oo::class create DemoClass1 {
    constructor {val1 val2} {
    variable instanceVar1 instanceVar2
    set instanceVar1 $val1
    set instanceVar2 $val2
    }
    method incrementInstanceVarsWithMy {} {
    my variable instanceVar1 instanceVar2
    incr instanceVar1
    incr instanceVar2
    }
    method incrementInstanceVarsWithVariable {} {
    variable instanceVar1
    variable instanceVar2
    incr instanceVar1
    incr instanceVar2
    }
    method getInstanceVarsWithMy {} {
    my variable instanceVar1 instanceVar2
    return "instanceVar1: $instanceVar1, \
    instanceVar2: $instanceVar2"
    }
    method getInstanceVarsWithVariable {} {
    variable instanceVar1
    variable instanceVar2
    return "instanceVar1: $instanceVar1, \
    instanceVar2: $instanceVar2"
    }
    }
    oo::class create DemoClass2 {
    constructor {val1 val2} {
    variable instanceVar1
    variable instanceVar2
    set instanceVar1 $val1
    set instanceVar2 $val2
    }
    method incrementInstanceVarsWithMy {} {
    my variable instanceVar1 instanceVar2
    incr instanceVar1
    incr instanceVar2
    }
    method incrementInstanceVarsWithVariable {} {
    variable instanceVar1
    variable instanceVar2
    incr instanceVar1
    incr instanceVar2
    }
    method getInstanceVarsWithMy {} {
    my variable instanceVar1 instanceVar2
    return "instanceVar1: $instanceVar1, \
    instanceVar2: $instanceVar2"
    }
    method getInstanceVarsWithVariable {} {
    variable instanceVar1
    variable instanceVar2
    return "instanceVar1: $instanceVar1, \
    instanceVar2: $instanceVar2"
    }
    }
    oo::class create DemoClass3 {
    constructor {val1 val2} {
    my variable instanceVar1 instanceVar2
    set instanceVar1 $val1
    set instanceVar2 $val2
    }
    method incrementInstanceVarsWithMy {} {
    my variable instanceVar1 instanceVar2
    incr instanceVar1
    incr instanceVar2
    }
    method incrementInstanceVarsWithVariable {} {
    variable instanceVar1
    variable instanceVar2
    incr instanceVar1
    incr instanceVar2
    }
    method getInstanceVarsWithMy {} {
    my variable instanceVar1 instanceVar2
    return "instanceVar1: $instanceVar1, \
    instanceVar2: $instanceVar2"
    }
    method getInstanceVarsWithVariable {} {
    variable instanceVar1
    variable instanceVar2
    return "instanceVar1: $instanceVar1, \
    instanceVar2: $instanceVar2"
    }
    }

    oo::class create DemoClass4 {
    constructor {val1 val2} {
    my variable instanceVar1
    my variable instanceVar2
    set instanceVar1 $val1
    set instanceVar2 $val2
    }
    method incrementInstanceVarsWithMy {} {
    my variable instanceVar1
    my variable instanceVar2
    incr instanceVar1
    incr instanceVar2
    }
    method incrementInstanceVarsWithVariable {} {
    variable instanceVar1
    variable instanceVar2
    incr instanceVar1
    incr instanceVar2
    }
    method getInstanceVarsWithMy {} {
    my variable instanceVar1
    my variable instanceVar2
    return "instanceVar1: $instanceVar1, \
    instanceVar2: $instanceVar2"
    }
    method getInstanceVarsWithVariable {} {
    variable instanceVar1
    variable instanceVar2
    return "instanceVar1: $instanceVar1, \
    instanceVar2: $instanceVar2"
    }
    }

    puts "DemoClass1"
    puts " obj11"
    set obj11 [DemoClass1 new 5 1]
    $obj11 incrementInstanceVarsWithMy
    puts "obj11: [$obj11 getInstanceVarsWithMy]"
    puts " obj12"
    set obj12 [DemoClass1 new 15 10]
    $obj12 incrementInstanceVarsWithVariable
    puts "obj12: [$obj12 getInstanceVarsWithVariable]"

    puts \n
    puts "DemoClass2"
    puts " obj21"
    set obj21 [DemoClass2 new 5 1]
    $obj21 incrementInstanceVarsWithMy
    puts "obj21: [$obj21 getInstanceVarsWithMy]"
    puts " obj22"
    set obj22 [DemoClass2 new 15 10]
    $obj22 incrementInstanceVarsWithVariable
    puts "obj22: [$obj22 getInstanceVarsWithVariable]"

    puts \n
    puts "DemoClass3"
    puts " obj31"
    set obj31 [DemoClass3 new 5 1]
    $obj31 incrementInstanceVarsWithMy
    puts "obj31: [$obj31 getInstanceVarsWithMy]"
    puts " obj32"
    set obj32 [DemoClass3 new 15 10]
    $obj32 incrementInstanceVarsWithVariable
    puts "obj32: [$obj32 getInstanceVarsWithVariable]"

    puts \n
    puts "DemoClass4"
    puts " obj41"
    set obj41 [DemoClass4 new 5 1]
    $obj41 incrementInstanceVarsWithMy
    puts "obj41: [$obj41 getInstanceVarsWithMy]"
    puts " obj42"
    set obj42 [DemoClass4 new 15 10]
    $obj42 incrementInstanceVarsWithVariable
    puts "obj42: [$obj42 getInstanceVarsWithVariable]"


    if {0} {
    Output:
    DemoClass1
    obj11
    obj11: instanceVar1: 6, instanceVar2: 1
    obj12
    obj12: instanceVar1: 16, instanceVar2: 1

    DemoClass2
    obj21
    obj21: instanceVar1: 6, instanceVar2: 2
    obj22
    obj22: instanceVar1: 16, instanceVar2: 11

    DemoClass3
    obj31
    obj31: instanceVar1: 6, instanceVar2: 2
    obj32
    obj32: instanceVar1: 16, instanceVar2: 11

    DemoClass4
    obj41
    obj41: instanceVar1: 6, instanceVar2: 2
    obj42
    obj42: instanceVar1: 16, instanceVar2: 11

    }

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From et99@21:1/5 to greg on Sun Jul 7 15:28:06 2024
    On 7/7/2024 6:21 AM, greg wrote:
    Am 04.07.24 um 09:17 schrieb Mark Summerfield:
    I am trying to learn TclOO. I have created two classes P and Q which
    appear to have identical behavior. Class P uses "my variable" and Q uses
    "variable". Can someone explain the difference between them. (I am
    familiar with Python and Go if that's any help with explaining.)


    Hello Mark,
    I have replaced your demo, hope that's OK.
    Different when there are multiple variables as arguments. Originally I expected the opposite behavior. I had misunderstood that until now.




    #DemoClass1 and DemoClass2
    # difference constructor with  variable individually or together
    # difference output for instanceVar2, no initialization with 15 (DemoClass1) #DemoClass3 and DemoClass4
    # no difference with my variable individually or together
    # in example:
    # objx1 with my variable, x for DemoClass
    # objx2 with variable, x for DemoClass

    oo::class create DemoClass1 {
        constructor {val1 val2} {
            variable instanceVar1 instanceVar2
            set instanceVar1 $val1
            set instanceVar2 $val2
        }

    <snip>


    Greg:

    Just to (hopefully) clarify with my own findings (Forgive me if this is what you were trying to say in your posting) :

    I've stepped this through, and what is happening is that the command in the constructor:

    variable instanceVar1 instanceVar2

    does indeed do what I thought it was supposed to do (but I must have messed up earlier) and both creates instanceVar1 and initializes it to the string "instanceVar2".

    I had wondered why it wouldn't get an error on the increment of a non-integer, until I also saw that it is immediately overwritten by the value of $val1, which is an integer.

    instanceVar2 in this constructor is thus merely a local variable that is set to $val2 and then disappears when the constructor returns.



    et

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)