Arjen Markus (31 march 2014) This may be the start of a new package, one to manipulate series of numerical data at a high level in pure Tcl. The code below is a humble experiment. Of course for large amounts of data it would be better to have a compiled extension and there are certainly packages around or in development that can/will do that, but it is also attractive to have a Tcl-only package.
# series.tcl -- # First attempt at creating a package to handle series of numerical data # namespace eval ::math::series { } # mexpr -- # Evaluate an expression with lists (series) of data # # Arguments: # expression String valid as a Tcl expression # # Returns: # List of the results of the expression evaluated with subsequent values # # Note: # Array elements $x($y) in these expressions do not yet work properly! # Also avoid variables whose name has the form "__...___" # # The current implementation may not be very efficient, because of # the expression being reparsed each iteration. # proc ::math::series::mexpr {expression} { # # Extract the variable names # set vars [lsort -unique [regexp -all -inline {\$[A-Za-z_]+} $expression]] set forvars {} foreach v $vars { set v [string range $v 1 end] upvar 1 $v __${v}__ if { [llength [set __${v}__]] > 1 } { lappend forvars $v [set __${v}__] } else { set $v [set __${v}__] } } # # Evaluate the expression via the list variables # if { [llength $forvars] > 0 } { set __result__ {} foreach {*}$forvars { lappend __result__ [expr $expression] } } else { set __result__ [expr $expression] } return $__result__ } # # procedure to compare the performance # proc test_expr {xlist ylist} { foreach x $xlist y $ylist { lappend result [expr {$x+$y}] } return $result } # # Simple test # set x {1 2 3 4 5 6 7 8 9} set y {2 3 4 5 6 7 8 9 10} set z 1 puts [::math::series::mexpr {$x+$y}] puts [::math::series::mexpr {$x+$z}] puts [test_expr $x $y] puts [::math::series::mexpr {1+2}] set x {} set y {} for {set i 0} {$i < 1000} {incr i} { lappend x $i lappend y $i } # Hm, mexpr is about 4 times as slow as test_expr puts "Time for mexpr: [time {::math::series::mexpr {$x+$y}} 1000]" puts "Time for test_expr: [time {test_expr $x $y} 1000]"