Re: Functional programming?

*To*: mathgroup at smc.vnet.net*Subject*: [mg92032] Re: Functional programming?*From*: Jean-Marc Gulliet <jeanmarc.gulliet at gmail.com>*Date*: Thu, 18 Sep 2008 06:10:47 -0400 (EDT)*Organization*: The Open University, Milton Keynes, UK*References*: <200809130957.FAA03536@smc.vnet.net> <gal3dg$dql$1@smc.vnet.net> <gapf5u$nvq$1@smc.vnet.net> <gaqf3r$dno$1@smc.vnet.net>

David Bailey wrote: > Jean-Marc Gulliet wrote: >> peter lindsay wrote: >> >>> as an old-timer myself - I'd be very interested in this too, >>> particularly - as you say - with reference to engineering problems. >>> I'm afraid my favorite construct was the REPEAT - UNTIL loop, which >>> should finally ruin any shreds of credibility that I may once have >>> had... >>> Peter >>> >>> 2008/9/13 AES <siegman at stanford.edu>: >>>> I suggest it might be instructive if some of the functional programming >>>> proponents on this group could provide us DO-looping old timers with a >>>> brief summary or tutorial as to what is really meant by, or involved in, >>>> "functional programming"? >>>> >>>> --- especially as this concept might relate to building programs to do >>>> calculations involving multi-stage real-world engineering or technical >>>> problems >>>> >>>> --- and especially as it might relate to programs that are going to be >>>> developed in an evolutionary process and that in the end, rather than >>>> being built into some long-term library, are maybe only going to be run >>>> or executed a few times before the person involved (e.g., an engineer, >>>> or scientist, or other real-world individual, not a "programmer") moves >>>> on to some other totally different task or assignment. >> >> Say we want to compute the mean (average) of all non-zero values for >> each row of a two dimensional array. The code must not crash when fed >> with data of incorrect format as well as it must handle nicely such >> things like divisions by zero. >> >> (* Functional / Pattern matching code *) >> >> myMean2[array_?VectorQ] := Mean[Select[array, # != 0 &]] >> myMean2[array_?MatrixQ] := Map[myMean2, array] >> >> >> (* Procedural code *) >> >> myMean1[array_] := >> Module[{iter, len, cnt, sum, mean}, >> sum = 0; >> mean = 0; >> cnt = 0; >> len = Length[array]; >> If[len != 0, >> For[iter = 1, iter <= len, iter = iter + 1, >> If[array[[iter]] != 0, sum = sum + array[[iter]]; cnt = cnt + 1]; >> ]; >> If[cnt != 0, >> mean = sum/cnt; >> , mean = "NA"; >> ]; >> , mean = "NA"; >> ]; >> Return[mean] >> ] >> >> meanArray[array_] := >> Module[{res, len, dim}, >> res = {}; >> len = Length[array]; >> dim = Depth[array] - 1; >> If[dim != 2, >> Return["NA"]]; >> For[iter = 1, iter <= len, iter = iter + 1, >> AppendTo[res, myMean1[array[[iter]]] >> ]; >> ]; >> Return[res] >> ] >> >> >> (* Some data and some tests *) >> >> data = {{}, {1, 2, 3, 4, 5, 0, 0, 0}, {0, 0, 0}, {1, 2, -10, >> 3, 4}, {a, b, c}}; >> >> meanArray[{1, 2, 3, 4, 5, 0, 0, 0}] >> meanArray[{{1, 2, 3, 4, 5, 0, 0, 0}}] >> meanArray[data] >> meanArray[{{{1, 2, 3, 4}, {5, 0, 0, 0}}}] >> >> (* >> Out[6]= "NA" >> >> Out[7]= {3} >> >> Out[8]= {"NA", 3, "NA", 0, "NA"} >> >> Out[9]= "NA" >> *) >> >> myMean2[{1, 2, 3, 4, 5, 0, 0, 0}] >> myMean2[{{1, 2, 3, 4, 5, 0, 0, 0}}] >> Map[myMean2, data] >> Map[myMean2, {{{1, 2, 3, 4}, {5, 0, 0, 0}}}] >> >> (* >> Out[10]= 3 >> >> Out[11]= {3} >> >> Out[12]= {Mean[{}], 3, Mean[{}], 0, Mean[{}]} >> >> Out[13]= {{5/2, 5}} >> *) >> >> >> Regards, >> -- Jean-Marc >> > I think you have chosen a rather favourable example here. Suppose > instead that you need to remove every zero together with the preceding > element (sweeping from left to right). Realistically, you also probably > want to do something, rather than output Mean[{}] for myMean2[{0,0,0}]. Fair enough! Below, I have added a function called "avg" that computes the mean, since I did not use the built-in function Mean[] in the procedural code. Also, myMean2 now returns "NA" rather than "Mean[{}]" to be consistent w/ the procedural version. In[1]:= avg[ lst_ /; VectorQ[lst, NumericQ] && Positive[Length[lst]]] := (Plus @@ lst)/Length[lst] avg[___] = "NA"; myMean2[array_?VectorQ] := avg[Select[array, # != 0 &]] myMean2[array_?MatrixQ] := Map[myMean2, array] data = {{}, {1, 2, 3, 4, 5, 0, 0, 0}, {0, 0, 0}, {1, 2, -10, 3, 4}, {a, b, c}}; myMean2[{1, 2, 3, 4, 5, 0, 0, 0}] myMean2[{{1, 2, 3, 4, 5, 0, 0, 0}}] Map[myMean2, data] Map[myMean2, {{{1, 2, 3, 4}, {5, 0, 0, 0}}}] Out[6]= 3 Out[7]= {3} Out[8]= {"NA", 3, "NA", 0, "NA"} Out[9]= {{5/2, 5}} > I would say that users should not be scared away from using procedural > code when faced with ad hoc problems of this sort. I second that. Best regards, -- Jean-Marc

**References**:**Functional programming?***From:*AES <siegman@stanford.edu>