0

This simple piece of code works perfectly fine. What I'm about to ask is completely unnecessary; however, I'm trying to learn more about the functional programming approach to doing things.

p=[0, 1, 0, 0, 0]
pHit = 0.6
pMiss = 0.2
pExact = 0.8
pOvershoot = 0.1
pUndershoot = 0.1


def move(p, U):
    q = []
    # A functional approach could be used here as well, but focusing on the outer loop at the moment.
    for i in range(len(p)):
        s = pExact * p[(i-U) % len(p)]
        s = s + pOvershoot * p[(i-U-1) % len(p)]
        s = s + pUndershoot * p[(i-U+1) % len(p)]
        q.append(s)
    return q

#Instead of this for loop here, is there a more functional approach to doing the same thing?
for i in range(0,1000):
    p = move(p,1)

print move(p,1)

This person asked a similar question, but the difference is that he/she is applying the recursive function to the actual object being iterated over. Using recursion with map in python

My case seems different because I am not iterating over the object (the list "p") that I am applying the recursive function to. The "for loop" handles this pretty well because I want to do the recursive operation range(0,1000) times, but I've seen this issue come up a few times now, and I'm very interested in seeing the functional programming solution to this problem.

I've tried to use reduce() a few times, but I find it difficult to pass the output of the X iteration to the X+1 iteration.

Community
  • 1
  • 1
Raymond Carl
  • 368
  • 4
  • 13
  • The entire point of `reduce` is to pass the result of the x iteration to the x+1 iteration. I recommend looking over reductions again add they can be very useful. – Carcigenicate Oct 23 '16 at 13:26
  • Your completely right, but the examples I've seen of reduce() are iterating over the object(s) on which the operation is performed upon. I've seen a few combinations of reduce() & map(), but they didn't quite apply to this situation. – Raymond Carl Oct 23 '16 at 14:28
  • Reductions can be used even when you don't care about the items in the collection being iterated. Reducing over a `range` can be used to apply the reduction many times over and over again. Consider `reduce(lambda acc n: return acc + 1), range(100), 0)`. Sorry if there are any syntax errors. It's been awhile since I've written Python. – Carcigenicate Oct 23 '16 at 14:32

1 Answers1

3

To replace that loop at the bottom, you could do something like:

reduce(lambda q,_: move(q, 1), range(1000), p)

Notice how the values of the range are never even used, so they're indicated as being irrelevant using a _.

The reduction automatically passes the result of move to the next iteration.

Carcigenicate
  • 43,494
  • 9
  • 68
  • 117
  • needs a comma between `q` and `n` there – Tore Eschliman Oct 23 '16 at 14:48
  • @ToreEschliman Whoops. Shows how long it's been since I've written Python :/. Thanks. – Carcigenicate Oct 23 '16 at 14:49
  • I think to indicate that `n` is never used you should replace it with `_` (Not 100% sure if that convention is used in Python as well, I know it from other languages) – UnholySheep Oct 23 '16 at 15:00
  • @UnholySheep Ya, that's how we do it in Clojure. I can't recall if a _ is a valid name in Python. I'll look into it. Thanks. – Carcigenicate Oct 23 '16 at 15:04
  • @Carcigenicate I think the critical piece I was missing was (like you pointed) on the last part of the documentation for reduce(): "If the optional initializer is present, it is placed before the items of the iterable in the calculation, and serves as a default when the iterable is empty." In this example, is it fair to say that "p" is the "initializaer"? – Raymond Carl Oct 23 '16 at 15:07
  • @nordicray Yes. The initializer is what the accumulator of the reduction is *before* `move` (in this case) is ever called. If you were using a reduction/fold to sum a list of numbers, what do you think the initial accumulator would be? – Carcigenicate Oct 23 '16 at 15:16
  • @nordicray Shameless self promotion, but read my answer here: http://softwareengineering.stackexchange.com/a/331624/139925. It does a very good job of going over folds and maps (if I do say so myself). – Carcigenicate Oct 23 '16 at 15:19