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