(short 'FP') A programming model, compare [imperative programming] - the one which Tcl and most other languages use. (*) In functional programming rather than presenting a program as a series of steps, it's represented with interdependent math-style functions, where you set one value, say, a variable, and all the contingent values snap into place, like a spreadsheet. Programs are viewed as descriptions of problems rather than instructions. ''(*) [RS]: I'd say that Tcl is often used imperatively, but at bare-bones it's fully functional - just by the fact that every command returns a result - take it or leave it...'' puts stdout [join [lsort [split [read stdin] \n]] \n] ; # Functional Tcl one-liner for Unix 'sort' Since explicit sequential execution isn't provided, branching structures like loops don't exist, so the favored method for, say, repeating an action is recursion. Languages written in this paradigm tend to be fairly slow compared to imperative ones, since the actual underlying machine code of computers is much more step-by-step and there's a big loss in the translation. See also * [Steps towards functional programming] * [Functional programming (Backus 1977)] * [Playing with recursion] * [Functional imaging] * [TV]: [BWise functional graphs] * [Multiplication tables] Functional languages include [Lisp]/[Scheme], [Haskell], [OCaml], etc. -[FW] ---- [RS]: In what respect is [Lisp] more functional than [Tcl]? As far as I know, both languages evaluate a sequence of expressions ("commands" in Tcl) in order - in Lisp this is called "implicit PROG", and yes, they even had a GOTO :). I'd say functional programming is a style that you can have in many languages, including Tcl, if you * write functions whose return value depends only on their arguments input * don't use side effects (including assigning to variables) * allow functions as values that can be arguments to, and return values of, other functions, or both (e.g. in [functional composition]) * use nested function calls instead of command sequences, so functions are just one-liners Example, imperative (using two local variables, and [return]): proc readfile name { set fp [open $name] set data [read $fp] close $fp return $data } Example, functional (no variables except function arguments), using the classic helpers [K] and [lambda]: proc readfile name {[lambda fp {K [read $fp] [close $fp]}] [open $name]} proc K {a b} {set a} proc lambda {argl body} {proc [info level 0] $argl $body; info level 0} See also [RPN] where the non-use of variables is driven to a high degree, even for function arguments. Example from [RPN again] (still valid Tcl :-). No variables used at all, except for the implicit stack, the Big Variable - code inspection shows that it takes a filename from the stack, and leaves the file contents as a string on the stack: rpn /readfile {open dup read swap close drop} def In [Pocket Joy 2005] that would be : readfile open (read) (close) cleave pop [FW]: I implied (IMO) that the functional model isn't only possible with "functional languages," they're just designed with that in mind. I also realize Lisp is really pretty imperative, but it is generally called a "functional" language for whatever reason, and a lot of functional programming is done in it. [Haskell] is used as the standard "purely" functional language - but it still has monads and such. [OAC] Monads are functional, that's the point of using them: you really can't do anything with side effects in Haskell. Monads are an extremely fancy work-around for that. :) [RHS] I'd say one way Lisp is "more functional" (geared towards FP, rather than has more function) than Tcl is the fact that it generally has optimizations like [Tail call optimization], which makes programming w/o variables much easier. ---- There must be something incredibly interesting and fascinating about this, as [RS] seems to be so fond of it. But [LES] fails to see any advantage in a style that makes code so convoluted and hard to read afterwards. [RS]: One can write very convoluted code in FP, yes; but it can be beautifully simple (see [filter]): proc intersection {set1 set2} {filter $set1 {in $set2}} In my opinion FP offers powerful abstractions that allow for simpler code - and who types less, can't make so many bugs... :) Another example: Someone asked on the Chat how to rewrite part of a line in a file, say change "20 11" to something different. Here's how to do this in FP spirit: proc >> {name data} {set f [open $name w]; puts -nonewline $f $data; close $f} proc << name {K [read [set f [open $name]]] [close $f]} proc K {a b} {set a} >> $filename [regsub "20 11" [<< $filename] $someOtherValue] [RHS] Personally, I find the above (file operations) to be a bad choice for an example of functional programming. While some things are more natural done functionality (ie, fibonacci), other things are more natural done imperatively (file operations). For example, I find the following to read much better: proc << {name} { set fd [open $name] set text [read $fd] close $fd return $text } File operations are, by nature, "do this, then that, then this other thing". I tend to think that the above is a prime example of why Lisp/Scheme/etc are considered "ugly" languages by some. When you want to do something that would be more naturally done in an imperative style, you likely wind up jumping through hoops and having lots of parens. [RS]: I agree that << and >> are not the best of examples. My point was more to show their application, >> $filename [regsub "20 11" [<< $filename] $someOtherValue] which expresses pretty clearly the intended operation, without having to administer intermediate variables, but with nested functions instead. On re-thinking, << can be implemented more functionally by introducing ''fmap'' (influenced by ApplyAll in Backus' FP; [Joy] has a comparable operator in ''cleave'') which maps a list of functions on one argument, as variant to [lmap] which maps a function to a list of arguments: proc fmap {functions x} {lmap f $functions {$f $x}} #-- slight sugaring proc first list {lindex $list 0} #-- Then we can write << like this: proc << filename {first [fmap {read close} [open $filename]]} The advantage is that no local variable is needed, except for the formal parameter ''filename''. This crystalline conciseness isn't everybody's taste, but I at least like it :) ---- [RS]: More functional fun on a Sunday evening: A classic FP operation is ''fold'' which reduces a list of values to one. The neutral element of the operation is the first argument, so I just call that "res" to save one assignment: proc fold {res op list} { foreach e $list {set res [$op $res $e]} set res } This requires [expr] operators exposed as Polish function names: foreach op {+ - * /} {proc $op {a b} "expr {\$a $op \$b}"} Two typical uses of ''fold'' can now just be curried: interp alias {} sum {} fold 0 + interp alias {} product {} fold 1 * and used in something useful: proc laverage list {expr {1.*[sum $list]/[llength $list]}} [Functional composition] is of course a must-have: proc o {f g x} {$f [$g $x]} And another flavor of [integer range generator], [[iota1 5]] -> {1 2 3 4 5}: proc iota1 n { set res {} for {set i 1} {$i<=$n} {incr i} {lappend res $i} set res } So now we can compose [factorial], instead of the boring recursion: interp alias {} ! {} o product iota1 Testing: % sum {1 2 3 4 5} 15 % product {1 2 3 4 5} 120 % laverage {1 2 3 4} 2.5 % ! 5 120 ---- [Category Concept] | [Category Functional Programming] | [Arts and crafts of Tcl-Tk programming]