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

(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