shanchen # Functional Programming in Python Ch3: Lazy Evaluation, Note

This chapter is mainly about iterator. For a collection that can be traversed, if you pass the whole collection into somewhere else, in Python, it will evaluate every element. It seems unreasonable if every statement needs some calculation, so that is why lazy evaluation comes in. I found out that functional language tends have lazy tag in initialization, but not for normal(OOP) language.

If you initialize a list

`a = [fib(0), fib(1), …, fib(35),fib(36)]`

The fibonacci methods cost a lot. If you don’t want these calculation delay your program initialization, you have to use "generator".(In Scala, that would be "Stream”)

In this example, you could use

`b = gen(36)`

In this way, the program would return immediately. It would do the calculation until real usage.

Iterator protocol: 若要讓一個物件iterable, 主要你要實作__iter__()跟__next__()。 第一個回傳本身，第二個傳回下一個元素。__iter__()這函數是idempotent的意思是，iter(A)==A==iter(iter(A))，(線性代數裡的矩陣運算有提過)

Iterator protocol: To make an object iterable, you have to implement __iter__() and __next__(). The former one should return itself, and for the latter one, return the next element. By the way, __iter__() should be idempotent, which means iter(A)==A==iter(iter(A)), (This term should be mentioned in matrix computaion in Linear Algerbra)
Example:

In the following, the book illustrated the built-in lib: itertools which is used commonly. Normally, programmer use this lib instead of inventing a new wheel. This chapter talked about 5 methods, which are tee, accumulate,chain, chain.from_iterable, count

tee主要接收一個iterable，並將它換成n個iterables。像是[[1,2], [3,4]]，本來iterable取第一第二個list變成取兩個int的iterable。
tee takes an iterable as argument and will return n iterables. Like [[1,2], [3,4]], the original iterable would return the first and second list, after tee, you would get two iterables that return Int from two list.

accumlate: 很像Scala的scan，只是不需要初始值。回傳同樣長度的list,第一個元素是你給的運算式跟初始值，第二個是前一個與原本資料的第二個做運算式裡面的運算，以此類推
accumlate: It resemble “scan” in Scala, but without initial value. It would return the list with same length. The first element would be the operation you give on the initial value, the second one would be the operation on former element and second element from original list, and so on.

`>>> data = [3, 4, 6, 2, 1, 9, 0, 7, 5, 8]>>> list(accumulate(data, operator.mul))     # running product[3, 12, 72, 144, 144, 1296, 0, 0, 0, 0]`

Scala的話
As for Scala

`val d = List(3, 4, 6, 2, 1, 9, 0, 7, 5, 8)println(d.scan(1)(_*_).tail)//List(3, 12, 72, 144, 144, 1296, 0, 0, 0, 0)//res1: Unit = ()`

chain的話，直接看例子，回傳一個iterator可以遍歷所有iterables中間的元素
“chain” is much easier to understand by example. It would return an iterator to traverse all elements from all iterables you give.

`b = chain([1,2],[3,4])for i in b:    print i    1234`

from_iterable，跟chain很像，只是python3才有
from_iterable is like chain. It is only in python3.

`a = chain.from_iterable([[1,2],[3,4]])for i in a:    print(i)     1234`

count，給定初始值跟差值，可以給出序列，像是generator 一樣
count: Given initial value and increment, it would return a list if you traverse. Like generator.

Like count(10), it would return an iterator. If you call __next__(), you would get element 1 larger that previous element. Compared to range(10, n) which evaluates every element immediately, it is lazy and you don’t need to give the maximum value.

`# count(10) --> 10 11 12 13 14 ...# count(2.5, 0.5) -> 2.5 3.0 3.5 ...`

The examples on the book are less easier to understand, so I would not put them here.

CC BY-NC-ND 2.0

Like my work?
Don't forget to support or like, so I know you are with me..