Python 3: Map with Side Effect Doesn't Work If Result is Not Used

By Xah Lee. Date: . Last updated: .

in Python 3, map with side effect doesn't work if you don't use the result.

# python 3

# in python 3, map returns a “iterator”. If you use map with side effects, it doesn't work if you don't use the result

a = 0

def ff(n):
global a
a = a+n
return n+1

map(ff, [1,1,1])
print(a)   # 0

b = map(ff, [1,1,1])
print(a)   # 0

list(map(ff, [1,1,1]))
print(a)   # 3

Here's Python 2:

# -*- coding: utf-8 -*-
# python 2

a = 0

def ff(n):
global a
a = a+n
return n+1

map(ff, [1,1,1])
print a # 3

Why is the Python 3 Iterator Way Bad?

The interesting point here is that, Python 3 introduced complexity.

in lisp, perl, Mathematica, you can map a function to a list.

; emacs lisp
(mapcar 'f mylist)」
# perl
map {f \$_} @mylist
(* Mathematica  *)
Map[f, mylist]

their semantics is simple. Apply f to each element of list, return the new list. The language doesn't care if your f has side effects. If it does, you wrote it that way, you have control of what you want. The semantics remains systematic and simple.

But in python 3, this is not so, due to its introduction of compiler engineering by-product concept of “iterator” and “generator”. For example, in python, when you do:

for x in myhash.keys():
if x == 10: break

and suppose myhash is 10 billion elements. It's not efficient, because python creates a huge list first. Python solves this by introducing “iterator”, as in

for x in myhash.iterkeys():
if x == 10: break

the issue here, is, for x in myhash.keys() should do the right thing without introducing a concept of iterator. The “iterator” is a by-product of computer engineering of object oriented programing. A extra layer of concept between the programer who needs to specify algorithms, and the compiler/machine that do the computation. It is created to solve compiler problem (speed, memory footprint), by shoving the problem to human.