Subject: Re: Tcl "expr" command change suggestion - DN [1]
Bryan Oakley <oakley@channelpoint.com> - 06 Jul 1999 - comp.lang.tcl
Joe English wrote:
>
> Costas Menico <costas_menico@mindspring.com> wrote:
> >
> >It seems to me that the "expr" Tcl command is pretty annoying to have
> >to type it in everytime you want to do some math. I believe it can be
> >made optional if Tcl would be smart enough to see that when a command
> >starts with a digit or a + or -, or a left parenthesis to mean you
> >want to do math.
>
> Hm... The thing I don't like about 'expr' (and 'if', 'while',
> and 'for') is that they use a completely different syntax
> than the rest of Tcl.
Interesting. That thought never occured to me. It seems to me that the
way it works now is the right way to do it. Nevertheless...
> I'd like to see:
>
> Change: [expr { ($x + $y + $z) / abs($w) <= 1.0} ]
> to: [<= [/ [+ $x $y $z] [abs $w]] 1.0]
Prefix notation is almost embarassingly easy to do in tcl (though,
performance suffers a bit). Here's one such example (not a particularly
elegant or fast implementation, but it proves the point and passes the
above little challenge):
# ideally this would use a namespace and one would have
# to do something like "import prefix::*" or something.
# I'll save that as an exercise for the reader...
proc handlePrefix {operation args} {
# note the rather weird syntax of an operator followed by
# a dash followed by an operator, etc. This is probably better
# expressed with each operator on a separate line, but I've
# condensed them to save a little space (which I promptly
# filled up with this comment!)
switch -exact -- $operation {
- - + - * - / {
# simple operations that can handle a list of values
set expression [join $args $operation]
set result [expr $expression]
}
== - <= - >= - < - > {
# equality operations which can take a list, but
# must be processed carefully...
if {[llength $args] < 2} {
error "$operation: wrong number of args"
}
set result 1
set current [lindex $args 0]
foreach operand [lrange $args 1 end] {
if "$current $operation $operand" {
set current $operand
continue
} else {
set result 0
break
}
}
}
abs - double - int {
# functions which require only one argument
if {[llength $args] != 1} {
error "$operation: wrong number of args"
}
set result [expr ${operation}([lindex $args 0])]
}
}
# arrange for result to be returned
set result
}
# define the commands/operators we are prepared to deal with
# of course, one could all all the operators they wish here...
foreach operation [list / + * - < <= == >= > abs int double] {
proc $operation {args} "eval handlePrefix $operation \$args"
}
# a simple test:
set w 15.0
set x 10.0
set y 20.0
set z 30.0
puts -nonewline "this test should return false: "
if {[<= [/ [+ $x $y $z] [abs $w]] 1.0]} {
puts "true"
} else {
puts "false"
}
# another simple test...
set w 60.0
puts -nonewline "this test should return true: "
if {[<= [/ [+ $x $y $z] [abs $w]] 1.0]} {
puts "true"
} else {
puts "false"
}
--
Bryan Oakley mailto:oakley@channelpoint.com
ChannelPoint, Inc. http://purl.oclc.org/net/oakley
Education is full of oversimplified lies which can be
refined into the truth later.
Last modified
1999-09-27
1999-09-27
(195.108.246.50)
Note: you are looking at
the snapshot of an old wiki
- much of this information
is likely to be very outdated
