Higher-Order Functions


#Higer-Order Functionsとは
[reading](http://composingprograms.com/pages/16-higher-order-functions.html)より。簡潔に「関数を引数として取り値をアウトプットする関数」のこと。

>
*One of the things we should demand from a powerful programming language is the ability to build abstractions by assigning names to common patterns and then to work in terms of the names directly. Functions provide this ability.*

##Generalizing numbers
例えば以下の様なスクリプトがあったとする。

```
from math import sqrt, pi

def area_square(r):
	assert r > 0, "A length must be positive."
	return r * r

def area_circle(r):
	return r * r * pi

def area_hexagon(r):
	return r * r * 3 * sqrt(3) / 2
``` 

共通している部分を`area`関数として最初に作ってしまい、掛け合わせる際の微妙な違いは`shape_constant`として定義してしまえば後々同じ処理をする際に関数だけを呼べば良い。

```
from math import sqrt, pi

def area(r, shape_constant):
	assert r > 0, "A length must be positive."
	return r * r * shape_constant

def area_square(r):
	return area(r, 1)

def area_circle(r):
	return area(r, pi)

def area_hexagon(r):
	return area(r, 3 * sqrt(3) / 2)
```
##Generalizing over computational processes

```
def sum_naturals(n):
	"""Sum the first N natural numbers

	>>> sum_naturals(5)
	15
	
	"""
	total, k = 0, 1
	while k <= n:
		total, k = total + k, k + 1
	return total

def sum_cubes(n):
	"""Sum the first N cubes of natural numbers.

	>>> sum_cubes(5)
	225
	"""
	total, k = total + pow(k, 3), k + 1
	return total
```

というスクリプトがあったとする。気づいたかもしれないが上の2つの関数は`k`と`pow(k, 3)`を除いてほぼ似たような処理を行っている。

これらの関数を一般化すると以下のようになる。

```
def <name>(n):
    total, k = 0, 1
    while k <= n:
        total, k = total + <term>(k), k + 1
    return total
```

具体的な手順は<a href="http://www.pythontutor.com/visualize.html#code=def+summation(n,+term%29%3A%0A%09total,+k+%3D+0,+1%0A%09while+k+%3C%3D+n%3A%0A%09%09total,+k+%3D+total+%2B+term(k%29,+k+%2B+1+%0A%09return+total%0A%0Adef+cube(w%29%3A%0A%09return+pow(w,+3%29%0A%0Adef+sum_cubes(n%29%3A%0A%09return+summation(n,+cube%29%0A%0Aresult+%3D+sum_cubes(5%29&mode=display&origin=opt-frontend.js&cumulative=false&heapPrimitives=false&textReferences=false&py=3&rawInputLstJSON=%5B%5D&curInstr=0" target="_blank">こちら</a>を参考に

```
def identitiy(k):
	return k

def cube(k):
	return pow(k, 3)

def summation(n, term):
	"""Sum the first N terms of a sequence.

	>>> summation(5, cube)
	225
	"""
	total, k = 0, 1:
	while k <= n:
		total, k = total + term(k), k + 1 
	return total

def sum_naturals(n):
	"""Sum the first N natural numbers.

	>>> sum_naturals(5):
	15
	"""
	total, k = 0, 1
	while k <= n:
		total, k = total + k, k + 1
		return total

def sum_cubes(n):
	"""Sum the first N cubes of natural numbers.

	>>> sum_cubes(5)
	225
	"""
	total, k = 0, 1 
	while k <= n:
		total, k = total + pow(k, 3), k + 1
		return total

```

ざっくり言うと関数の中の処理一つ一つを分解して互いに共通している部分と異なる部分を分ける。共通している部分は一つの関数としてまとめ、異なる部分は別途関数を用意する。具体的なイメージとしては、

1. 複数の関数同士の中で共通している部分（同じ処理）を探し出し、その処理だけをしてくれる関数を作る。ここでいう`summation`関数がそれにあたる。
2. 異なる部分（ここでいう`total + k`と`total + power(k, 3)`）についても別途関数として作っておけば後でその関数を引数として使って`summation`関数内でまとめて処理が出来てしまうわけだ。

言葉で説明してもわかりづらいので具体例：

```
def identitiy(k):
	return k

def cube(w):
	return pow(w, 3)

def summation(n, term):
	"""Sum the first N terms of a sequence.

	>>> summation(5, cube)
	225
	"""
	total, k = 0, 1
	while k <= n:
		total, k = total + term(k), k + 1 
	print(total)

def sum_naturals(n):
	"""Sum the first N natural numbers.

	>>> sum_naturals(5):
	15
	"""
	return summation(n, cube)

def sum_cubes(n):
	"""Sum the first N cubes of natural numbers.

	>>> sum_cubes(5)
	225
	"""
	return summation(n, cube)

sum_cubes(5)

```

#追記:

<a href="https://www.youtube.com/watch?v=fVon4QaY4wo" target="_blank">このリンク</a>いい感じの解説を見つけた。

```
def outside():
    x = 5
    def printHam():
        print(x)
    return (printHam)

myFunc = outside()
myFunc()
``` 

#sortedを使ってhigher order function

`sorted([5,-2,-1], key=abs) #[-1,-2,5]`が一番分かりやすい例かもしれない。built-in functionである`abs`を使ってsorted()リストの中身の数字を絶対値として扱い、`sorted()`で低い順に変え、元の記号を付けて返すという関数。これは厳密には`key`関数という名で`built-in`関数である`abs`を引数として扱っているのでこれもHiger Order Functionの一部といえる。

>_its a function your gonna call to sort it along with the list of the stuff to be sorted And sorted() is in charge of looping through the list and calling your function to get the values to sort by._