if 0 {[Richard Suchenwirth] 2005-04-02 - Say you want to make a multiplication table for an elementary school kid near you. Easily done in a few lines of Tcl code:} proc multable {rows cols} { set res "" for {set i 1} {$i <= $rows} {incr i} { for {set j 1} {$j <= $cols} {incr j} { append res [format %4d [expr {$i*$j}]] } append res \n } set res } if 0 {The code does not directly [puts] its results, but returns them as a string - you might want to do other things with it, e.g. save it to a file for printing. Testing: % multable 3 10 1 2 3 4 5 6 7 8 9 10 2 4 6 8 10 12 14 16 18 20 3 6 9 12 15 18 21 24 27 30 Here's a different way to do it à la [functional programming]: } proc multable2 {rows cols} { formatMatrix %4d [outProd * [iota 1 $rows] [iota 1 $cols]] } if 0 {The body is nice and short, but consists of all unfamiliar commands. They are however better reusable than the ''multable'' proc above. The first formats a matrix (a list of lists to Tcl) with newlines and aligned columns for better display:} proc formatMatrix {fm matrix} { join [lmap row $matrix {join [lmap i $row {format $fm $i}] ""}] \n } if 0 {Short again, and slightly cryptic, as is the "outer product" routine, which takes a function f and two vectors, and produces a matrix where f was applied to every pair of a x b - in APL they had special compound operators for this job, in this case "°.x":} proc outProd {f a b} { lmap i $a {lmap j $b {$f $i $j}} } if 0 {Again, [lmap] (the collecting [foreach]) figures prominently, so here it is in all its simplicity:} proc lmap {_var list body} { upvar 1 $_var var set res {} foreach var $list {lappend res [uplevel 1 $body]} set res } #-- We need multiplication from [expr] exposed as a function: proc * {a b} {expr {$a * $b}} #-- And finally, ''iota'' is an [integer range generator]: proc iota {from to} { set res {} while {$from <= $to} {lappend res $from; incr from} set res } if 0 {With these parts in place, we can see that ''multable2'' works as we want: % multable2 3 10 1 2 3 4 5 6 7 8 9 10 2 4 6 8 10 12 14 16 18 20 3 6 9 12 15 18 21 24 27 30 So why write six procedures, where one did the job already? A matter of style and taste, in a way - ''multable'' is 10 LOC and depends on nothing but Tcl, which is good; ''multable2'' describes quite concisely what it does, and builds on a few other procs that are highly reusable. Should you need a unit matrix (where the main diagonal is 1, and the rest is 0), just call ''outProd'' differently: % outProd == [iota 1 5] [iota 1 5] {1 0 0 0 0} {0 1 0 0 0} {0 0 1 0 0} {0 0 0 1 0} {0 0 0 0 1} which just requires [expr]'s equality to be exposed too: proc == {a b} {expr {$a == $b}} One of the fascinations of functional programming is that one can do the job in a simple and clear way (typically a one-liner), while using a collection of reusable building-blocks like [lmap] and ''iota''. And ''formatMatrix'' and ''outProd'' are so general that one might include them in some library, while the task of producing a multiplication table may not come up any more for a long time... ---- [Category Functional Programming] | [Arts and crafts of Tcl-Tk programming] }