Recursive Fibonacci in text WebAssembly - recursion

I've been playing around with text WebAssembly and wanted to write a recursive Fibonacci number calculator.
I got a version that works but it uses a single branch if statement to check for the base case:
(module
(export "fib" (func $fib))
(func $fib (param $0 i32) (result i32)
(if
(i32.lt_s
(get_local $0)
(i32.const 2)
)
(return
(i32.const 1)
)
)
(return
(i32.add
(call $fib
(i32.sub
(get_local $0)
(i32.const 2)
)
)
(call $fib
(i32.sub
(get_local $0)
(i32.const 1)
)
)
)
)
)
)
I tested this in wabt here: https://webassembly.github.io/wabt/demo/wat2wasm/
I tried to rewrite this using select conditional:
(module
(export "fib" (func $fib))
(func $fib (param $0 i32) (result i32)
(select
(return
(i32.const 1)
)
(return
(i32.add
(call $fib
(i32.sub
(get_local $0)
(i32.const 2)
)
)
(call $fib
(i32.sub
(get_local $0)
(i32.const 1)
)
)
)
)
(i32.lt_s
(get_local $0)
(i32.const 2))))
)
This compiles to .wasm, but it does not run as expected, just returning the base case. I tried similar versions with if-then-else, but to no avail. Why would the result of a single-branch if be any different from a two-branch conditional?

You just gave me a reason to learn wasm. I can't yet answer your question about the single-branch if, but I can show you a working fib function.
(module
(func $fib2 (param $n i32) (param $a i32) (param $b i32) (result i32)
(if (result i32)
(i32.eqz (local.get $n))
(then (local.get $a))
(else (call $fib2 (i32.sub (local.get $n)
(i32.const 1))
(local.get $b)
(i32.add (local.get $a)
(local.get $b))))))
(func $fib (param i32) (result i32)
(call $fib2 (local.get 0)
(i32.const 0) ;; seed value $a
(i32.const 1))) ;; seed value $b
(export "fib" (func $fib)))
Copy/paste to demo it here
const wasmInstance =
new WebAssembly.Instance (wasmModule, {})
const { fib } =
wasmInstance.exports
for (let x = 0; x < 10; x = x + 1)
console.log (fib (x))
Output
0
1
1
2
3
5
8
13
21
34
For what it's worth, the implementation here is quite different than yours. Your program requires exponential computational time and space whereas the above program's requirements are linear.
This is evident by examining your use of (call $fib ...). In your program, a single call to $fib has the possibility to spawn two additional calls to $fib, which each have the possibility to spawn two more calls to $fib, and on and on. Above $fib2 only has potential to call itself once, at most.
Although it has a lesser performance, of course it is still possible to implement the exponential process
(module
(func $fib (param $n i32) (result i32)
(if (result i32)
(i32.lt_s (local.get $n)
(i32.const 2))
(then (local.get $n))
;; recursive branch spawns _two_ calls to $fib; not ideal
(else (i32.add (call $fib (i32.sub (local.get $n)
(i32.const 1)))
(call $fib (i32.sub (local.get $n)
(i32.const 2)))))))
(export "fib" (func $fib)))

The problem with your code is that select is not a conditional: it always evaluates all its operands first, and then decides which value to pick. In your case, the first operand contains a return, however, so the function is immediately terminated.
Such a select is a special instruction in CPUs to avoid branches. You only want to use it when determining both results is cheaper than performing a branch, like if would. Usually, that is the case only when you already have both values, i.e., the first two operands are very simple expressions, like constants or variable reads.

Related

How to type DO variables in common lisp?

I know you can declare function parameter types like
(defun add-integer (a b)
(declare (integer a b))
(the integer (+ a b)))
But what about DO variables? For example, I want to type passes:
(defun bench ()
(do ((end (+ (get-internal-real-time) (* 5 internal-time-units-per-second)))
(passes 0 (+ 1 passes)))
((> (get-internal-real-time) end)
passes)
(sieve 1000000)))
When I try to compile with (declaim (optimize (speed 2) (safety 0))), I get
; in: DEFUN BENCH
; (1+ PASSES)
;
; note: forced to do full call
; unable to do inline fixnum arithmetic (cost 2) because:
; The first argument is a UNSIGNED-BYTE, not a FIXNUM.
; The result is a (VALUES (INTEGER 1) &OPTIONAL), not a (VALUES FIXNUM
; &REST T).
; unable to do inline (unsigned-byte 64) arithmetic (cost 5) because:
; The first argument is a UNSIGNED-BYTE, not a (UNSIGNED-BYTE 64).
; The result is a (VALUES (INTEGER 1) &OPTIONAL), not a (VALUES
; (UNSIGNED-BYTE 64)
; &REST T).
I tried
(defun bench ()
(declare (type (unsigned-byte 64) passes))
(do ((end (+ (get-internal-real-time) (* 5 internal-time-units-per-second)))
(passes 0 (+ 1 passes)))
((> (get-internal-real-time) end)
passes)
(sieve 1000000)))
But then I get
; Undefined variable:
; PASSES
I cannot find anything on this in the type chapters of the HyperSpec, e.g. (http://clhs.lisp.se/Body/04_bc.htm). A working example would be extremely helpful! Thanks!
You put the declaration at the beginning of the loop body.
(defun bench ()
(do ((end (+ (get-internal-real-time) (* 5 internal-time-units-per-second)))
(passes 0 (+ 1 passes)))
((> (get-internal-real-time) end)
passes)
(declare (type (unsigned-byte 64) passes))
(sieve 1000000)))
This is shown in the specification of DO:
do ({var | (var [init-form [step-form]])}*) (end-test-form result-form*) declaration* {tag | statement}*
See declaration after (end-test-form result-form*)

My code signals the error "application: not a procedure" or "call to non procedure"

During the execution of my code I get the following errors in the different Scheme implementations:
Racket:
application: not a procedure;
expected a procedure that can be applied to arguments
given: '(1 2 3)
arguments...:
Ikarus:
Unhandled exception
Condition components:
1. &assertion
2. &who: apply
3. &message: "not a procedure"
4. &irritants: ((1 2 3))
Chicken:
Error: call of non-procedure: (1 2 3)
Gambit:
*** ERROR IN (console)#2.1 -- Operator is not a PROCEDURE
((1 2 3) 4)
MIT Scheme:
;The object (1 2 3) is not applicable.
;To continue, call RESTART with an option number:
; (RESTART 2) => Specify a procedure to use in its place.
; (RESTART 1) => Return to read-eval-print level 1.
Chez Scheme:
Exception: attempt to apply non-procedure (1 2 3)
Type (debug) to enter the debugger.
Guile:
ERROR: In procedure (1 2 3):
ERROR: Wrong type to apply: (1 2 3)
Chibi:
ERROR in final-resumer: non procedure application: (1 2 3)
Why is it happening
Scheme procedure/function calls look like this:
(operator operand ...)
Both operator and operands can be variables like test, and + that evaluates to different values. For a procedure call to work it has to be a procedure. From the error message it seems likely that test is not a procedure but the list (1 2 3).
All parts of a form can also be expressions so something like ((proc1 4) 5) is valid syntax and it is expected that the call (proc1 4) returns a procedure that is then called with 5 as it's sole argument.
Common mistakes that produces these errors.
Trying to group expressions or create a block
(if (< a b)
((proc1)
(proc2))
#f)
When the predicate/test is true Scheme assumes will try to evaluate both (proc1) and (proc2) then it will call the result of (proc1) because of the parentheses. To create a block in Scheme you use begin:
(if (< a b)
(begin
(proc1)
(proc2))
#f)
In this (proc1) is called just for effect and the result of teh form will be the result of the last expression (proc2).
Shadowing procedures
(define (test list)
(list (cdr list) (car list)))
Here the parameter is called list which makes the procedure list unavailable for the duration of the call. One variable can only be either a procedure or a different value in Scheme and the closest binding is the one that you get in both operator and operand position. This would be a typical mistake made by common-lispers since in CL they can use list as an argument without messing with the function list.
wrapping variables in cond
(define test #t) ; this might be result of a procedure
(cond
((< 5 4) result1)
((test) result2)
(else result3))
While besides the predicate expression (< 5 4) (test) looks correct since it is a value that is checked for thurthness it has more in common with the else term and whould be written like this:
(cond
((< 5 4) result1)
(test result2)
(else result3))
A procedure that should return a procedure doesn't always
Since Scheme doesn't enforce return type your procedure can return a procedure in one situation and a non procedure value in another.
(define (test v)
(if (> v 4)
(lambda (g) (* v g))
'(1 2 3)))
((test 5) 10) ; ==> 50
((test 4) 10) ; ERROR! application: not a procedure
Undefined values like #<void>, #!void, #<undef>, and #<unspecified>
These are usually values returned by mutating forms like set!, set-car!, set-cdr!, define.
(define (test x)
((set! f x) 5))
(test (lambda (x) (* x x)))
The result of this code is undetermined since set! can return any value and I know some scheme implementations like MIT Scheme actually return the bound value or the original value and the result would be 25 or 10, but in many implementations you get a constant value like #<void> and since it is not a procedure you get the same error. Relying on one implementations method of using under specification makes gives you non portable code.
Passing arguments in wrong order
Imagine you have a fucntion like this:
(define (double v f)
(f (f v)))
(double 10 (lambda (v) (* v v))) ; ==> 10000
If you by error swapped the arguments:
(double (lambda (v) (* v v)) 10) ; ERROR: 10 is not a procedure
In higher order functions such as fold and map not passing the arguments in the correct order will produce a similar error.
Trying to apply as in Algol derived languages
In algol languages, like JavaScript and C++, when trying to apply fun with argument arg it looks like:
fun(arg)
This gets interpreted as two separate expressions in Scheme:
fun ; ==> valuates to a procedure object
(arg) ; ==> call arg with no arguments
The correct way to apply fun with arg as argument is:
(fun arg)
Superfluous parentheses
This is the general "catch all" other errors. Code like ((+ 4 5)) will not work in Scheme since each set of parentheses in this expression is a procedure call. You simply cannot add as many as you like and thus you need to keep it (+ 4 5).
Why allow these errors to happen?
Expressions in operator position and allow to call variables as library functions gives expressive powers to the language. These are features you will love having when you have become used to it.
Here is an example of abs:
(define (abs x)
((if (< x 0) - values) x))
This switched between doing (- x) and (values x) (identity that returns its argument) and as you can see it calls the result of an expression. Here is an example of copy-list using cps:
(define (copy-list lst)
(define (helper lst k)
(if (null? lst)
(k '())
(helper (cdr lst)
(lambda (res) (k (cons (car lst) res))))))
(helper lst values))
Notice that k is a variable that we pass a function and that it is called as a function. If we passed anything else than a fucntion there you would get the same error.
Is this unique to Scheme?
Not at all. All languages with one namespace that can pass functions as arguments will have similar challenges. Below is some JavaScript code with similar issues:
function double (f, v) {
return f(f(v));
}
double(v => v * v, 10); // ==> 10000
double(10, v => v * v);
; TypeError: f is not a function
; at double (repl:2:10)
// similar to having extra parentheses
function test (v) {
return v;
}
test(5)(6); // == TypeError: test(...) is not a function
// But it works if it's designed to return a function:
function test2 (v) {
return v2 => v2 + v;
}
test2(5)(6); // ==> 11

Possible to do this without using eval in Common Lisp?

In my little project I have two arrays, lets call them A and B. Their values are
#(1 2 3) and #(5 6 7). I also have two lists of symbols of identical length, lets call them C and D. They look like this: (num1 num2 num3) and (num2 num3 num4).
You could say that the symbols in lists C and D are textual labels for the values in the arrays A and B. So num1 in A is 1. num2 in A is 2. num2 in B is 5. There is no num1 in B, but there is a num3, which is 6.
My goal is to produce a function taking two arguments like so:
(defun row-join-function-factory (C D)
...body...)
I want it to return a function of two arguments:
(lambda (A B) ...body...)
such that this resulting function called with arguments A and B results in a kind of "join" that returns the new array: #(1 5 6 7)
The process taking place in this later function obtained values from the two arrays A and B such that it produces a new array whose members may be represented by (union C D). Note: I haven't actually run (union C D), as I don't actually care about the order of the symbols contained therein, but lets assume it returns (num1 num2 num3 num4). The important thing is that (num1 num2 num3 num4) corresponds as textual labels to the new array #(1 5 6 7). If num2, or any symbol, exists in both C and D, and subsequently represents values from A and B, then the value from B corresponding to that symbol is kept in the resulting array rather than the value from A.
I hope that gets the gist of the mechanical action here. Theoretically, I want row-join-function-factory to be able to do this with arrays and symbol-lists of any length/contents, but writing such a function is not beyond me, and not the question.
The thing is, I wish the returned function to be insanely efficient, which means that I'm not willing to have the function chase pointers down lists, or look up hash tables at run time. In this example, the function I require to be returned would be almost literally:
(lambda (A B)
(make-array 4
:initial-contents (list (aref A 0) (aref B 0) (aref B 1) (aref B 2))))
I do not want the array indexes calculated at run-time, or which array they are referencing. I want a compiled function that does this and this only, as fast as possible, which does as little work as possible. I do not care about the run-time work required to make such a function, only the run-time work required in applying it.
I have settled upon the use of (eval ) in row-join-function-factory to work on symbols representing the lisp code above to produce this function. I was wondering, however, if there is not some simpler method to pull off this trick that I am not thinking of, given one's general cautiousness about the use of eval...
By my reasoning, i cannot use macros by themselves, as they cannot know what all values and dimensions A, B, C, D could take at compile time, and while I can code up a function that returns a lambda which mechanically does what I want, I believe my versions will always be doing some kind of extra run-time work/close over variables/etc...compared to the hypothetical lambda function above
Thoughts, answers, recommendations and the like are welcome. Am I correct in my conclusion that this is one of those rare legitimate eval uses? Apologies ahead of time for my inability to express the problem as eloquently in english...
(or alternatively, if someone can explain where my reasoning is off, or how to dynamically produce the most efficient functions...)
From what I understand, you need to precompute the vector size and the aref args.
(defun row-join-function-factory (C D)
(flet ((add-indices (l n)
(loop for el in l and i from 0 collect (list el n i))))
(let* ((C-indices (add-indices C 0))
(D-indices (add-indices D 1))
(all-indices (append D-indices
(set-difference C-indices
D-indices
:key #'first)))
(ns (mapcar #'second all-indices))
(is (mapcar #'third all-indices))
(size (length all-indices)))
#'(lambda (A B)
(map-into (make-array size)
#'(lambda (n i)
(aref (if (zerop n) A B) i))
ns is)))))
Note that I used a number to know if either A or B should be used instead of capturing C and D, to allow them to be garbage collected.
EDIT: I advise you to profile against a generated function, and observe if the overhead of the runtime closure is higher than e.g. 5%, against a special-purpose function:
(defun row-join-function-factory (C D)
(flet ((add-indices (l n)
(loop for el in l and i from 0 collect (list el n i))))
(let* ((C-indices (add-indices C 0))
(D-indices (add-indices D 1))
(all-indices (append D-indices
(set-difference C-indices
D-indices
:key #'first)))
(ns (mapcar #'second all-indices))
(is (mapcar #'third all-indices))
(size (length all-indices))
(j 0))
(compile
nil
`(lambda (A B)
(let ((result (make-array ,size)))
,#(mapcar #'(lambda (n i)
`(setf (aref result ,(1- (incf j)))
(aref ,(if (zerop n) 'A 'B) ,i)))
ns is)
result))))))
And validate if the compilation overhead indeed pays off in your implementation.
I argue that if the runtime difference between the closure and the compiled lambda is really small, keep the closure, for:
A cleaner coding style
Depending on the implementation, it might be easier to debug
Depending on the implementation, the generated closures will share the function code (e.g. closure template function)
It won't require a runtime license that includes the compiler in some commercial implementations
I think the right approach is to have a macro which would compute the indexes at compile time:
(defmacro my-array-generator (syms-a syms-b)
(let ((table '((a 0) (b 0) (b 1) (b 2)))) ; compute this from syms-a and syms-b
`(lambda (a b)
(make-array ,(length table) :initial-contents
(list ,#(mapcar (lambda (ai) (cons 'aref ai)) table))))))
And it will produce what you want:
(macroexpand '(my-array-generator ...))
==>
#'(LAMBDA (A B)
(MAKE-ARRAY 4 :INITIAL-CONTENTS
(LIST (AREF A 0) (AREF B 0) (AREF B 1) (AREF B 2))))
So, all that is left is to write a function which will produce
((a 0) (b 0) (b 1) (b 2))
given
syms-a = (num1 num2 num3)
and
syms-b = (num2 num3 num4)
Depends on when you know the data. If all the data is known at compile time, you can use a macro (per sds's answer).
If the data is known at run-time, you should be looking at loading it into an 2D array from your existing arrays. This - using a properly optimizing compiler - should imply that a lookup is several muls, an add, and a dereference.
By the way, can you describe your project in a wee bit more detail? It sounds interesting. :-)
Given C and D you could create a closure like
(lambda (A B)
(do ((result (make-array n))
(i 0 (1+ i)))
((>= i n) result)
(setf (aref result i)
(aref (if (aref use-A i) A B)
(aref use-index i)))))
where n, use-A and use-index are precomputed values captured in the closure like
n --> 4
use-A --> #(T nil nil nil)
use-index --> #(0 0 1 2)
Checking with SBCL (speed 3) (safety 0) the execution time was basically identical to the make-array + initial-contents version, at least for this simple case.
Of course creating a closure with those precomputed data tables doesn't even require a macro.
Have you actually timed how much are you going to save (if anything) using an unrolled compiled version?
EDIT
Making an experiment with SBCL the closure generated by
(defun merger (clist1 clist2)
(let ((use1 (list))
(index (list))
(i1 0)
(i2 0))
(dolist (s1 clist1)
(if (find s1 clist2)
(progn
(push NIL use1)
(push (position s1 clist2) index))
(progn
(push T use1)
(push i1 index)))
(incf i1))
(dolist (s2 clist2)
(unless (find s2 clist1)
(push NIL use1)
(push i2 index))
(incf i2))
(let* ((n (length index))
(u1 (make-array n :initial-contents (nreverse use1)))
(ix (make-array n :initial-contents (nreverse index))))
(declare (type simple-vector ix)
(type simple-vector u1)
(type fixnum n))
(print (list u1 ix n))
(lambda (a b)
(declare (type simple-vector a)
(type simple-vector b))
(let ((result (make-array n)))
(dotimes (i n)
(setf (aref result i)
(aref (if (aref u1 i) a b)
(aref ix i))))
result)))))
runs about 13% slower than an hand-written version providing the same type declarations (2.878s instead of 2.529s for 100,000,000 calls for the (a b c d)(b d e f) case, a 6-elements output).
The inner loop for the data based closure version compiles to
; 470: L2: 4D8B540801 MOV R10, [R8+RCX+1] ; (aref u1 i)
; 475: 4C8BF7 MOV R14, RDI ; b
; 478: 4C8BEE MOV R13, RSI ; source to use (a for now)
; 47B: 4981FA17001020 CMP R10, 537919511 ; (null R10)?
; 482: 4D0F44EE CMOVEQ R13, R14 ; if true use b instead
; 486: 4D8B540901 MOV R10, [R9+RCX+1] ; (aref ix i)
; 48B: 4B8B441501 MOV RAX, [R13+R10+1] ; load (aref ?? i)
; 490: 4889440B01 MOV [RBX+RCX+1], RAX ; store (aref result i)
; 495: 4883C108 ADD RCX, 8 ; (incf i)
; 499: L3: 4839D1 CMP RCX, RDX ; done?
; 49C: 7CD2 JL L2 ; no, loop back
The conditional is not compiled to a jump but to a conditional assignment (CMOVEQ).
I see a little room for improvement (e.g. using CMOVEQ R13, RDI directly, saving an instruction and freeing a register) but I don't think this would shave off that 13%.

Scheme - do iterative - return value

I trying to write a function which gets an integer number , represented by string , and check if all his chars are digits and return #t \ #f accordingly . Thats the code -
(define (splitString str) (list->vector (string->list str)))
(define myVector 0)
(define flag #t)
(define (checkIfStringLegal str) (
(set! myVector (splitString str))
(do ( (i 0 (+ i 1)) ) ; init
((= i (vector-length myVector)) flag) ; stop condition
(cond ((>= 48 (char->integer (vector-ref myVector i)) ) (set! flag #f))
((<= 57 (char->integer (vector-ref myVector i)) )(set! flag #f))
)
)
)
)
Few explanations -
(list->vector (string->list str)) - convert string the char list .
(vector-ref myVector i) - char from the myVector at place i .
Its run OK , but when I try to use this func , like (checkIfStringLegal "444") I get -
application: not a procedure;
expected a procedure that can be applied to arguments
given: #<void>
arguments...:
#t
Try this:
(define (checkIfStringLegal str)
(andmap char-numeric?
(string->list str)))
This is how the procedure works:
It transforms the string into a list of characters, using string->list
It validates each character in the list to see if it's a number, applying the predicate char-numeric? to each one
If all the validations returned #t, andmap will return #t. If a single validation failed, andmap will return #f immediately
That's a functional-programming solution (and after all, this question is tagged as such), notice that your intended approach looks more like a solution in a C-like programming language - using vectors, explicit looping constructs (do), mutation operations (set!), global mutable definitions ... that's fine and it might eventually work after some tweaking, but it's not the idiomatic way to do things in Scheme, and it's not even remotely a functional-programming solution.
EDIT:
Oh heck, I give up. If you want to write the solution your way, this will work - you had a parenthesis problem, and please take good notice of the proper way to indent and close parenthesis in Scheme, it will make your code more readable for you and for others:
(define (splitString str) (list->vector (string->list str)))
(define myVector 0)
(define flag #t)
(define (checkIfStringLegal str)
(set! myVector (splitString str))
(do ((i 0 (+ i 1)))
((= i (vector-length myVector)) flag)
(cond ((>= 48 (char->integer (vector-ref myVector i)))
(set! flag #f))
((<= 57 (char->integer (vector-ref myVector i)))
(set! flag #f)))))
Even so, the code could be further improved, I'll leave that as an exercise for the reader:
Both conditions can be collapsed into a single condition, using an or
The exit condition should be: end the loop when the end of the vector is reached or the flag is false

For-loop in scheme

I want to define a for-n function in scheme that takes 3 parameters, start and stop are integers and fn is a function. I want the for-n function to call fn with start then start+1 ... and in the end with stop.
Also I want to store all the values fn returns in a list. Please help me get started. I am an experienced programmer but have just starting learning scheme.
This is the function definition I got:
[edit]
(define (fn a)
a
)
(define (for-n start stop fn)
(cond
((> start stop) (quote ()))
((= start stop) (list(fn start)))
(else (list(for-n (+ start 1) stop fn)))
)
)
> (for-n 3 5 fn)
(list (list (list 5)))
When (for-n 3 5 fn) is called, I want it to return
(3 4 5), what am I doing wrong?
[edit-2]
Thanks for the help everyone. I got function working now. Here is what I got:
(define (for-n start stop fn)
(cond
((> start stop) (quote ()))
((= start stop) (list(fn start)))
(else (cons (fn start) (for-n (+ start 1) stop fn)))
)
)
You seldom want to use list to recursively construct lists. Lists are built with cons and null (aka '()); list is just a convenience function to create a fixed sized list.
(list 1 2 3) = (cons 1 (cons 2 (cons 3 null)))
You should only have two cases in your cond clause: either you're done or you aren't.
Examples help. In particular, pick examples that are related by your recursive calls. You included the example (for-n 3 5 fn). What about (for-n 4 5 fn); what should it return? Now, given start = 3, stop = 5, and (for-n 4 5 fn) = whatever you think it should produce, how can you construct the answer you think (for-n 3 5 fn) should produce?
I highly recommend How to Design Programs (text available online) as an introduction to functional programming.
Here's a solution that uses SRFI 1:
(define (for-n start stop fn)
(map fn (iota (- stop start) start)))
If this is for homework, then it's up to you to define iota, and perhaps map also. :-D
Another solution using a different strategy (also uses SRFI 1):
(define (for-n start stop fn)
(unfold-right (lambda (x) (< x start))
fn sub1 (sub1 stop)))
where sub1 == (lambda (x) (- x 1)). Of course, you have to implement unfold-right yourself, in this case.
Hopefully from the above two example solutions, you have enough ideas to build your own from-scratch solution. :-)
I'm new to scheme too, but here's what I came up with for a generic for loop that seems to work for me:
(define (for i end-cond end-fn fn var)
(if (end-cond i)
var
(for (end-fn i) end-cond end-fn fn (fn var))
)
)
So the canonical:
for (i=0; i > 5; i++) {
print i;
}
return i;
Can be written as:
(define i 0) (for i (lambda (x) (> 5 x)) (lambda (y) (+ 1 y)) display i)
...and you can see why the paradigm doesn't translate well, though you can replace those lambdas with named functions to make it more readable.
--
Self-edit 2015:
This is awful, and the wrong way to do functional programming. A 'map' or 'fold' based approach is much better.

Resources