[Richard Suchenwirth] (whose favorite is the New Orleans function [http://www.satchmo.net/board/messages/419.html]) -- Every Tcler does some functional programming sometimes - when he writes, and calls, a proc that returns a result ;-) But in my concept of functional as opposed to iterative programming, most if not all actions are called in functions, so every really ''functional'' program would be a (sometimes long) one-liner. See [Lambda in Tcl] for more functional programming components. Tcl lends itself pretty well to functional programming just with the proc command. We would go even more functional if some frequent iterations are wrapped in functions. One such case is ''foreach'', where a list is walked. I often set up an empty result list and append something for each foreach pass. This functionality can be factored out: given an iterator name, an input list, and a body (which mostly will refer to the iterator somehow), return a list of the results from applying (mapping) body to the input list, as follows: proc lforeach {_i list body} { upvar $_i i set res [list] foreach i $list { lappend res [uplevel 1 $body] } set res ;# or return $res, if you prefer } lforeach i {a bb ccc dddd} {string length $i} % 1 2 3 4 set foo .5 % .5 lforeach i {a bb ccc dddd} {expr [string length $i]+$foo} % 1.5 2.5 3.5 4.5 ;# just to show that foo is visible to body Another frequent iteration is reading lines from a file. Functionally wrapped, we give a filename and receive a list of the lines in that file: proc lines-of fn { set f [open $fn r] set t [read $f [file size $fn]] close $f split $t \n } ;# but see below for a more functional one-liner... and here's a little averager that uses its input twice: proc laverage L {expr ([join $L +])/[llength $L]} where ''expr [[join $L +]]'' is the functional equivalent of adding the elements of a list in a loop (see [Sample math programs] for detailed discussion). Having these components ready, here's a functional demo: determine the average line length in a file, all in one line: laverage [lforeach i [lines-of $file] {string length $i}] Yes, this is still Tcl, though it looks quite different again... People often talk about wishes for Tcl 9.0, but my major wish is I could fully utilize what's in Tcl since 7.4 (when I started ;-) ---- [Salt and Sugar] note: for better looks, we might rewrite the top line of ''lforeach'' and ''laverage'' with some sugar arguments like this: proc all {list "for" _i "get" body} { and then the example could be average of: [all [lines-of $file] for: i get: {string length $i}] Matter of taste, though. Sometimes memories of COBOL (or was that Smalltalk?) come up... Or how is average [of {string length $i} for: i in: [lines-of $file]] Somehow this is drifting off into natural languages... if it weren't for them brac[[k]]e[[t]]s!% ---- Afterthoughts: (1) Maybe Tcl's ''foreach'' command could be enhanced (e.g. with a switch) to return a list of its results like ''lforeach'' above. Right now it just returns an empty string. (2) If in ''lforeach'' we changed ''body'' into a partial command (like in traces and scrollbar bindings), we could get rid of an explicit iterator: proc lmap {pcmd "to" list} { set res [list] foreach i $list { lappend res [uplevel 1 $pcmd [list $i]] } set res } average [lmap {string length} to: [lines-of $file]] But this would limit the flexibility as shown in the ''...+$foo'' example. ---- APL is a heavily functional language. See [Playing APL] on a partial reimplementation in Tcl... ---- Functional programs tend to have deeply recursive calls, because they depend on recursion for variable binding. Efficient functional programming therefore often depends on [Tail call optimization]. ---- Here's a more functional goodie (it has to resort to one intermediate variable) to get the list of lines from a text file: proc lines-of name {split [read [set f [open $name]]][close $f] \n} The trick is the invisible concatenation of ''read''s and ''close''s results (where the latter is an empty string - [RS]) ---- Another nice functional wrapper, which filters a list according to a condition, was given in [More graph theory]: proc inducedCycles3 g { each cycle in [cycles $g] where {isInducedCycle $cycle $g} } proc each {*i "in" list "where" cond} { set res {} upvar ${*i} i foreach i $list { if {[uplevel 1 expr $cond]} {lappend res $i} } set res } ---- See also [Playing Haskell] - [Functional composition] - [Custom curry] ---- In 2002, it might be that the functional language most often associated with Tcl is [XSLT] (!). Certainly [XML] processing remains a growth industry, and Tcl is particularly apt for this kind of work [[give references]]. ---- [Arts and crafts of Tcl-Tk programming]