NEM 19 May 2004 - A little experiment on achieving infix arithmetic using an OO extension (in this case, XOTcl) and some cunning unknown handlers. Not particularly efficient, but it works, and is quite fun:
# ooinfix.tcl -- # # An experiment in doing infix arithmetic using object (XOTcl) and a cunning # unknown command handler to auto-convert numbers to objects (auto-boxing). # Then uses an even more cunning class-level unknown handler to rewrite # expressions into a format suitable for [expr]. # # Neil Madden, 2004. # Public Domain. package require XOTcl namespace import -force ::xotcl::* # Use a single class for all numbers (rather than separate Integer and Real # subclasses). Just makes things easier. Class Number Number instproc init {{val 0}} { my set val $val } Number instproc unknown {cmd args} { set expr [linsert $args 0 [my set val] $cmd] return [expr $expr] } # Unknown handler to do auto-conversion if {[string length [info commands ::_ooinfix_unknown_orig]] == 0} { rename ::unknown ::_ooinfix_unknown_orig proc ::unknown {cmd args} { # Does it look like a number? if {[string is double -strict $cmd]} { Number ::$cmd $cmd # Retry uplevel 1 $cmd $args } else { # Pass on to original unknown uplevel 1 [list ::_ooinfix_unknown_orig $cmd] $args } } }
Here's a little demo of it in action:
(neilmadden) 50 % source ooinfix.tcl (neilmadden) 51 % 1 + 2 + 3 6 (neilmadden) 52 % 1 + 2 * 7 15 (neilmadden) 53 % set ans [12 * 15 / 22] 8 (neilmadden) 54 % 24.5 * 15 367.5
It uses Tcl's built in [expr] command to do all the operator precedence and type conversions (integer/double stuff). All you need is a space before the first number and the operator - you can leave out any further spaces. Also, you can define new constants:
(neilmadden) 55 % 24 *15/9 40 (neilmadden) 56 % Number pi 3.14159265 ::pi (neilmadden) 57 % pi * 2 6.2831853 (neilmadden) 58 % set r 25 25 (neilmadden) 59 % set area [pi * $r ** 2] 1963.49540625