-2

Just a warning, this code is ugly. I know there are better ways of doing this but this is just an exercise.

I am poking around with the functional programming side of python, but I keep encountering an error when I try and nest a number of function calls:

LEN = 4
def calcentropy(i):
    entropy[i] = -1 * reduce(lambda x,y: x+y, map(lambda x: x*np.log2(x), map(lambda x: x * (float(1)/float(NUM)), map(count, range(0,LEN)))))
map(calcentropy, range(0,LEN))

I get an error message stating that I have a mismatch between types; float and None for the last call to range(): TypeError: unsupported operand type(s) for *: 'NoneType' and 'float'

When I do something like:

LEN = 4
def calcFreqs(i): do stuff to freqs
map(calcFreqs, range(0, LEN)
def calcentropy(i):
    entropy[i] = -1 * reduce(lambda x,y: x+y, map(lambda x: x*np.log2(x), map(lambda x: x * (float(1)/float(NUM)), freqs))))
map(calcentropy, range(0,LEN))

I don't have any issues.

I think the problem is that LEN is no longer in scope of the call to range(). Is there a way I can fix this, or have I exceeded some sort of limit, and if so, what was it?

Sorry for not adding enough code, my mistake:

import numpy as np
LEN = 4
freqs = np.zeros(4 * LEN, dtype = np.float64)
sites = np.array([0,1,2,3,0,1,2,3,0,1,2,3], dtype = np.int8)
A = np.int8(0)
C = np.int8(1)
G = np.int8(2)
T = np.int8(3)
def count(i):
    freqs[i * LEN + A] = E + reduce(lambda x,y:x+y, map(lambda x: 1 if x==A else 0, sites[i::LEN]))
    freqs[i * LEN + C] = E + reduce(lambda x,y:x+y, map(lambda x: 1 if x==A else 0, sites[i::LEN]))
    freqs[i * LEN + G] = E + reduce(lambda x,y:x+y, map(lambda x: 1 if x==A else 0, sites[i::LEN]))
    freqs[i * LEN + T] = E + reduce(lambda x,y:x+y, map(lambda x: 1 if x==A else 0, sites[i::LEN]))
entropy = np.zeros(LEN, dtype = np.float64)
def calcentropy(i):
    entropy[i] = -1 * reduce(lambda x,y: x+y, map(lambda x: x*np.log2(x), map(lambda x: x * (float(1)/float(NUM)), map(count, range(0,LEN)))))
map(calcentropy, range(0,LEN))
print entropy
info   = map(lambda x: 2-x, entropy)    
Joe
  • 320
  • 1
  • 4
  • 15
  • Always include the **exact** error message. – jordanm Dec 04 '12 at 16:58
  • possible duplicate of [Maximum recursion depth?](http://stackoverflow.com/questions/3323001/maximum-recursion-depth), hard to say without the exact error message. – Andy Hayden Dec 04 '12 at 17:01
  • I know you warned about ugly code, but do keep in mind that just because you are using functional programming techniques, this does not mean you have to nest like this. You can define your functions to keep your code cleaner. – RonaldBarzell Dec 04 '12 at 17:02
  • I added the error message, sorry about that. I omitted count because it is big and ugly, however, count also uses the constant LEN. – Joe Dec 04 '12 at 17:07
  • 1
    If I set `count = lambda x: 1`, `NUM = 1.0`, and `entropy = np.array([0] * LEN)` then your code runs fine. You need to post enough code to enable someone to reproduce your error. – Gareth Rees Dec 04 '12 at 17:51
  • `count` appears to be invoked for its side effects on the global array `freqs`. No amount of `map` and `lambda` will make your code "functional" if the core of what it's doing is something like that. – Ben Dec 05 '12 at 03:56

1 Answers1

3

They issue you're having is that your count function doesn't return anything. In Python that is the same as returning None.

So when you run your long nested statement, you're getting a list of None values back from the innermost map call: map(count, range(0, LEN)). The first None value then causes an exception when it gets passed to the innermost lambda expression and you try to multiply it by a float.

So, you either need to use something else as the innermost value for your big nested structure, or you need to fix up count to return something. It's not clear to me what you're intending to iterate over, so I can't really offer a solid suggestion. Perhaps freqs?

Also, I suggest avoiding map when you simply want to run a function a bunch of times but don't care about the results. Instead, write an explicit for loop. This matters in Python 3, where map returns a generator (which doesn't do anything until you iterate over it).

Blckknght
  • 100,903
  • 11
  • 120
  • 169