Functional programming thought processes. Functional programming (including the lambda calculus), is Turing complete. We have loops, we have ifs, we have arithmetic. And we have sophisticated storage. Dr. Poe learned programming via "iterative branch programming". Dr. Poe had to practice to learn other programming paradigms and so Dr. Poe when he's tired still thinks of programming as "iterative branch". Also Dr. Poe, when he's tired, refers to himself in the third person. Iterative branch: based on two constructs, conditional branch and unconditional branch. "Unconditional branch:" Jump directly to another part of the program. Do not pass GO. Do not collect $200. "Conditional branch:" if a certain condition is true, jump to another part of the program. If it isn't, just proceed from where you are. 1 PRINT "WELCOME TO ADVENTURE" 2 PRINT "YOU ARE IN A FOREST. WHAT DO YOU DO?" 3 PRINT "COMMAND: "; 4 INPUT A$ 10 LET X = RND(0) 20 IF X < 0.5 THEN 60 30 IF X > 0.5 THEN 80 40 PRINT "YOU WIN!" 50 GOTO 90 60 PRINT "I DON'T KNOW HOW TO ";A$ 70 GOTO 30 80 PRINT "YOU GOT KILLED" 90 END Structured block programming (another form of iterative programming). Use "blocks:" if-else blocks or while blocks. One "feature" of block programming is that a block must a have a single entry point and a single exit point. while (test) { stuff } The loop begins and ends with the test. Now, most programmers find this too restrictive. And we have "flow-of-control statements" that circumvent the rule of "one-entry-one-exit" In C, break, continue, return, exit(), _exit(), abort() Using these statements make your programs shorter...but it's adds complexity to the debug and expand process. It took me a long time to "get" the block programming paradigm. To get out of the habit of just GOTOing wherever I want to go. The same thing happens when you're learning the functional programming paradigm. Since you can use recursion to make loops work, it's very easy to fall back on this, to use "recursive loops" to emulate how you would solve the problem in a block interative language. So, there are techniques in functional programming that you should you should learn that makes unnecessary certain block programming paradigms. You can still emulate loops if you need them, and you still have recursion. OBVIATE = MOOTIFY One feature is the "map" feature. "Map" occurs when you take a function an apply it to every item in a collection (list, array, whatever). The map function obviates a loop in the case where you want to apply the same function to everything in the list. for (int i=0; i < A.length; i++) {Do stuff with A[i]} [36]> (defun cool (x) (+ (* x x) 5)) COOL [37]> (setf b (list 0 1 2 3 4 5 6 7 8 9)) (0 1 2 3 4 5 6 7 8 9) [38]> (mapc #'cool b) (0 1 2 3 4 5 6 7 8 9) [39]> (mapcar #'cool b) (5 6 9 14 21 30 41 54 69 86) Another common feature in functional programming languages is the "filter" feature. (In APL, we called this "compress"). The idea behind "filter" is that you create a new list (or array or whatever) that contains only those items in the original list that satisfy a certain requirement. If an original list were (1 2 3 4 5 6), if you wanted the list containing only those even elements, you would get (2 4 6). Instead of using a loop, and an if within that loop, you just do this. for (int i=0; i < A.length();i++) { if (A[i] satisfies some condition) {stuff} [46]> (setf orig (list 1 2 3 4 5 6 7 8 9 10)) (1 2 3 4 5 6 7 8 9 10) [47]> (remove-if #'oddp orig) (2 4 6 8 10) [48]> orig (1 2 3 4 5 6 7 8 9 10) [49]> (remove-if (complement #'oddp orig)) *** - EVAL: too many arguments given to COMPLEMENT: (COMPLEMENT #'ODDP ORIG) The following restarts are available: ABORT :R1 Abort main loop Break 1 [50]> abort [51]> (remove-if (complement #'oddp) orig) (1 3 5 7 9) [52]> If you combine map and filter, you apply a function to only those elements of a list (or array or whatever) that satisfy a certain condition map "cool" to filter of the even elements of A Then I would apply that function only those elements without having to write a loop. Another common functional programming feature is "fold". This is where you take a function that normally applies to 2 arguments and instead you apply it to the entire aggregate. For example, + is used to define the sum of two numbers, but you may to add up a whole thing. In LISP, this is called reduce. [52]> (setf A (list 1 2 3 4 5 6 7 8 9 10)) (1 2 3 4 5 6 7 8 9 10) [53]> (reduce #'+ A) 55 [54]> (defun one-less (a b) (- (+ a b) 1)) ONE-LESS [55]> (one-less 3 4) 6 [56]> (setf A (list 1 2 3 4)) (1 2 3 4) [57]> (reduce #'one-less A) 7 [58]> (one-less A) *** - EVAL/APPLY: Too few arguments (1 instead of at least 2) given to ONE-LESS The following restarts are available: ABORT :R1 Abort main loop Break 1 [59]> abort [60]> So, with these tools, doing a running sum is easy. You can do a (reduce #'+ some-list) and get easily, in one line, the sum. Running count: How many items list satisfy a certain condition? How would you do this in functional programming? (reduce #'+ (map #'one (remove-if #'some-cond our-list))) (length (remove-if #'some-cond our-list))