Thread from comp.lang.tcl (7 replies)

oo::class - my variable vs variable
Posted by Mark Summerfield <mark@qtrac.eu> 3 months ago

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]"

Click on article to view all threads in comp.lang.tcl
Re: oo::class - my variable vs variable
Posted by Petro Kazmirchuk <vivid.tree7955@fastmail.com> 2 months 4 weeks ago

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 {}
     }
}

Click on article to view all threads in comp.lang.tcl
Re: oo::class - my variable vs variable
Posted by Schelte <nospam@wanadoo.nl> 2 months 4 weeks ago

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.

Click on article to view all threads in comp.lang.tcl
Re: oo::class - my variable vs variable
Posted by greg <gregor.ebbing@gmx.de> 2 months 4 weeks ago

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

Click on article to view all threads in comp.lang.tcl
Re: oo::class - my variable vs variable
Posted by Mark Summerfield <mark@qtrac.eu> 2 months 4 weeks ago

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.)



Click on article to view all threads in comp.lang.tcl
Re: oo::class - my variable vs variable
Posted by et99 <et99@rocketship1.me> 2 months 3 weeks ago

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.

Click on article to view all threads in comp.lang.tcl
Re: oo::class - my variable vs variable
Posted by greg <gregor.ebbing@gmx.de> 2 months 3 weeks ago

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

}





Click on article to view all threads in comp.lang.tcl
Re: oo::class - my variable vs variable
Posted by et99 <et99@rocketship1.me> 2 months 3 weeks ago

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

Click on article to view all threads in comp.lang.tcl