Updated 2014-05-31 18:06:51 by pooryorick

Richard Suchenwirth 2002-05-05: Reading chapter 1.3 of SICP, a highly educational introduction to programming based on the LISP dialect Scheme, I felt challenged to try to reproduce the Scheme examples for summation of a series in Tcl, for example:
``` b
---
\
/   f(n) = f(a) + ... + f(b)
---
n=a```

Here's what I have so far (both f and next are "functional objects", which in Tcl just means "strings that happen to be the name of a proc":
```proc sum {f a next b} {
expr {\$a>\$b? 0 : [\$f \$a] + [sum \$f [\$next \$a] \$next \$b]}
}
# --------------------------- small building blocks:
proc cube x {expr {\$x*\$x*\$x}}
proc inc  x {incr x} ;# argument x is value, instead of name
proc lambda {argl body} {
set   name [info level 0]
proc \$name \$argl \$body
set   name
}```

This handful of code allows us to reproduce the Scheme results from SICP. For more info, see there.

• sum the cubes of 1..10:
```sum cube 1 inc 10 ==> 3025, or:
sum cube 1 [lambda x {incr x}] 10```

• sum the integers from 1 to 10:
```proc identity x {set x}
sum identity 1 inc 10 ==> 55; or:
sum [lambda x {set x}] 1 [lambda x {incr x}] 10```

• approximate Pi one slow way:
```proc pi-term x {expr {1.0 / (\$x * (\$x+2))}}
proc pi-next x {expr {\$x + 4}}
expr {[sum pi-term 1 pi-next 1000] *8 } ==> 3.1395926555897828```

whose run limit could be increased from 1000 until 2756 before raising the "too many nested calls..." error ;-( and still gave a less precise approximation than the good old atan(1)*4...

• integrate a function f between limits a and b:
```proc integral0 {f a b dx} {
set ::globaldx \$dx
expr {[sum \$f [expr {\$a + \$::globaldx / 2}] add-dx \$b] * \$dx}
}
% integral0 cube 0 1 .0016 ==> 0.2499996800000055```

Here however I had to start to compromise: instead of Scheme's lexical scoping, where dx is visible everywhere inside integral's body, including the add-dx function, I had to elevate dx to global status, which is ugly; and Tcl's recursion depth limit caught me before I could try SICP's dx value of 0.001 - the result is still close (but no cigar) to the correct result of 0.25. Oh wait, at least in this case we can emulate lexical scoping more closely, by embodying \$dx into a "live proc body" of add-dx:
```proc integral {f a b dx} {
expr {[sum \$f [expr {\$a+\$dx/2}] add-dx \$b] * \$dx}
}
% integral cube 0 1 .00146 ==> 0.25009974849771255```

A cleaner way to implement this "closure" would be an added default argument, like they do in Python - the body can remain braced, but the argument list of add-dx now "inherits" from outside:
```proc integral {f a b dx} {
proc add-dx "x {dx \$dx}" {expr {\$x+\$dx}}
expr {[sum \$f [expr {\$a+\$dx/2}] add-dx \$b] * \$dx}
}```

Slightly off-topic, but as all building blocks are there, here's a stint on the derivative of a function, using the default args method, inheriting one argument from deriv, and one from global namespace:
```proc deriv g {
lambda [list x [list g \$g] [list dx \$::dx]] \
{expr {([\$g [expr {\$x+\$dx}]] - [\$g \$x])/\$dx}}
}
% set dx 0.00001 ;# well, in SICP they have it global too...
% [deriv [lambda x {expr \$x*\$x*\$x}]] 5 ==> 75.0001499966```

Anyway, I'm again surprised how many steps towards functional programming are possible with Tcl .. and more to come.