TIP #174 Version 1.11: Math Operators as Commands

This is not necessarily the current version of this TIP.


TIP:174
Title:Math Operators as Commands
Version:$Revision: 1.11 $
Authors: Kristoffer Lawson <setok at altparty dot org>
Donal K. Fellows <donal dot k dot fellows at man dot ac dot uk>
David S. Cargo <escargo at skypoint dot com>
Peter Spjuth <peter dot spjuth at space dot se>
Kevin B. Kenny <kennykb at acm dot org>
State:Draft
Type:Project
Tcl-Version:8.5
Vote:Pending
Created:Monday, 15 March 2004

Abstract

This TIP describes a proposal for math operators in Tcl as separate commands, acting much like the equivalent in the Lisp language. This would make simple usage of mathematics much clearer.

Rationale

While the expr command works fairly well for longer mathematical expressions, it is extremely tedious for the most common uses, such as handling indices. Take the following examples:

 set newList [lrange $list [expr {$idx - 5}] [expr {$idx + 5}]]
 .c create oval [expr {$x - $r}] [expr {$y - $r}] [expr {$x + $r}] [expr {$y + $r}]

Many find this particular aspect of Tcl unappealing. It gets increasingly difficult to read as more and more simple mathematical expressions build up.

Proposed Change

  1. A group of Tcl commands are added which would handle mathematical operations without the need to use expr. Most commands would take a variable amount of arguments and would work such that the operator is applied to the combination of the first and second arguments. The result of this combination is then used with the operator for the third argument, etc. If only one argument is given, it is returned as is. See below for details for each operator. A sample implementation of the + command in Tcl follows:

     proc ::tcl::mathop::+ {args} {
         set r 0
         foreach operand $args {
             set r [expr {$r + $operand}]
         }
         return $r
     }
    
  2. All operator commands will be kept in the ::tcl::mathop (in line with ::tcl::mathfunc from TIP #232) namespace, from which they would most commonly be imported to the global namespace.

  3. The commands are not connected to their corresponding expr operator. Overloading or adding any command in ::tcl::mathop does not affect operators in expr or any other command that calls Tcl_ExprObj.

Operator Commands Details

Unary operators ~ and ! always take one argument.

Operators that naturally allow 0 or more arguments do so:

Op/argc  0   1   2     3-
+        0   a   a+b   a+b+c...
*        1   a   a*b   a*b*c...
&       -1   a   a&b   a&b&c...
^        0   a   a^b   a^b^c...
|        0   a   a|b   a|b|c...

Other left or right associative operators. Operator ** is right associative, which needs to be noted clearly.

Op/argc  0   1   2     3-
**       1   a   a**b  a**(b**(c...))

Nonassociative operators must always be binary.

Op/argc  0   1   2      3-
<<       err err a<<b   err
>>       err err a>>b   err
%        err err a%b    err
!=       err err a!=b   err
ne       err err a ne b err

Unary minus is negation. Unary divide is inversion.

Op/argc  0   1     2    3-
-        err -a    a-b  ((a-b)-c)...
/        err 1.0/a a/b  ((a/b)/c)...

Comparison operators other than != and ne test for ordering:

Op/argc   0   1     2      3+
<         1   1     a<b    ((a<b)&&(b<c)&&...)
<=        1   1     a<=b   ((a<=b)&&(b<=c)&&...)
>         1   1     a>b    ((a>b)&&(b>c)&&...)
>=        1   1     a>=b   ((a>=b)&&(b>=c)&&...)
==        1   1     a==b   ((a==b)&&(b==c)&&...)
eq        1   1     a eq b ((a eq b)&&(b eq c)&&...)

List operators "in" "ni" always take two args.

Op/argc   0   1     2       3+
in        err err   a in b  err
ni        err err   a ni b  err

The operators that do conditional evaluation of their arguments (&&, || and ?:) are not included. This is because their characteristic evaluation laziness is best modelled using the existing if command.

Example

As an example use, let us change the lines from above:

 set newList [lrange $list [- $idx 5] [+ $idx 5]]
 .c create oval [- $x $r] [- $y $r] [+ $x $r] [+ $y $r]

This is clearly shorter and much easier on the eyes. There is no need to consider the effects of bracing expressions.

Sum of a list becomes

 set sum [+ {expand}$list]

Implementation

Efficiency

These commands can naturally be compiled and thus as efficient as their corresponding expr operators. The following lines should probably result in the same byte codes.

set x [expr {$a * $b + $c}]
set x [+ [* $a $b] $c]

Reference Implementation

Available online at SourceForge [1]. The patch is for this TIP as it stood several versions ago; in particular, it does not implement the ordering comparators and gets associativity wrong in a couple of other cases. Nevertheless, the authors of this TIP believe it to be an adequate proof that the ideas of the TIP are implementable with good performance.

Copyright

This document has been placed in the public domain.


Powered by TclThis is not necessarily the current version of this TIP.

TIP AutoGenerator - written by Donal K. Fellows