Sujet : Re: how to create a simple closure to create validators
De : et99 (at) *nospam* rocketship1.me (et99)
Groupes : comp.lang.tclDate : 20. Jun 2024, 19:59:38
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <v51u6q$2n0bl$1@dont-email.me>
References : 1
User-Agent : Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Thunderbird/102.6.1
On 6/20/2024 12:59 AM, Mark Summerfield wrote:
I can make a variable that has a specific validator quite easily using
trace add.
But I can't work out how to create a validator maker (i.e., a simple
closure).
I am using Tcl/Tk 9.0b2.
Here is the code:
#!/usr/bin/env tclsh9
proc valid_percent {varname elemname op} {
upvar 1 $varname var
if {$op eq "write"} {
if {$var < 0} {
set var 0
} elseif {$var > 100} {
set var 100
}
}
}
proc check {expected actual} {
if {$expected != $actual} {
puts "ERROR $expected != $actual"
} else {
puts "OK $expected == $actual"
}
}
trace add variable percent write valid_percent
set percent 50
check 50 $percent
set percent -5
check 0 $percent
set percent 492
check 100 $percent
# All the above works correctly; what's below fails with:
# can't read "min": no such variable
proc clamper {min max} {
proc clamp {varname elemname op} {
upvar 1 $varname var
if {$op eq "write"} {
if {$var < $min} {
set var $min
} elseif {$var > $max} {
set var $max
}
}
}
return clamp
}
trace add variable score write [clamper 0 20]
set score 15
check 15 $score
set score -5
check 0 $score
set score 25
check 20 $score
Here's how I might do this:
proc validateRange {min max name1 name2 op} {
if { $name2 eq "" } { ;# scalar
upvar 1 $name1 newValue
if { $newValue < $min } {
set newValue $min
} elseif { $newValue > $max } {
set newValue $max
}
} else { ;# array - left as exercise for reader
}
}
trace add variable my_percent write {validateRange 0 20 }
set my_percent 10
puts "my_percent= |$my_percent| was 10"
set my_percent 50
puts "my_percent= |$my_percent| was 50"
set my_percent -50
puts "my_percent= |$my_percent| was -50"
trace add variable my_percent100 write {validateRange 5 100 }
set my_percent100 10
puts "my_percent100= |$my_percent100| was 10"
set my_percent100 500
puts "my_percent100= |$my_percent100| was 500"
set my_percent100 -50
puts "my_percent100= |$my_percent100| was -50"
output:
my_percent= |10| was 10
my_percent= |20| was 50
my_percent= |0| was -50
my_percent100= |10| was 10
my_percent100= |100| was 500
my_percent100= |5| was -50