.. index:: 
	single: 関数型プログラミング; はじめに

====================
関数型プログラミング
====================

以前の章では関数と再帰について学びました。

関数型プログラミング (FP) の概念についてより詳しく学びます。

* 純粋関数
* 第一級関数
* 高階関数
* 無名関数と入れ子関数
* 等式関数

.. index:: 
	pair: 関数型プログラミング; 純粋関数


純粋関数
========

代入演算子により、関数への参照で渡される元データを処理する代わりに、
変数の値 (リストとオブジェクト)をコピーして新しい変数を作成することで
純粋関数 (状態を変更しない関数) を作成できます。


用例:

.. code-block:: ring

	Func Main
		aList = [1,2,3,4,5]
		aList2 = square(aList)
		see "aList" + nl
		see aList
		see "aList2" + nl
		see aList2

	Func Square aPara
		a1 = aPara		# リストのコピー
		for x in a1
			x *= x
		next
		return a1		# 新しいリストを返します。
		
実行結果:

.. code-block:: ring

	aList
	1
	2
	3
	4
	5
	aList2
	1
	4
	9
	16
	25


.. index:: 
	pair: 関数型プログラミング; 第一級関数

第一級関数
==========

Ring の関数は第一級オブジェクトです。関数を仮引数として渡したり、
変数として格納、または値を返せます。

例えば、関数名を "関数名" または :関数名 のようにリテラルとして記述することで、関数の渡したり、返せます。

関数名を有する変数を用いると、関数を渡したり返せます。

Call 命令で関数名を有する変数から関数を呼び出します。

文法:

.. code-block:: ring

	[関数の返値を代入するための変数] = Call 変数名([仮引数])

用例:

.. code-block:: ring

	Func Main
		see "before test2()" + nl
		f = Test2(:Test)
		see "after test2()" + nl
		call f()

	Func Test
		see "Message from test!" + nl

	Func Test2 f1
		call f1()
		See "Message from test2!" + nl
		return f1	

実行結果:

.. code-block:: ring

	before test2()
	Message from test!
	Message from test2!
	after test2()
	Message from test!

.. index:: 
	pair: 関数型プログラミング; 高階関数

高階関数
========

高階関数は、ほかの関数を仮引数として扱う関数です。

用例:

.. code-block:: ring

	Func Main
		times(5,:test)

	Func Test
		see "Message from the test function!" + nl

	Func Times nCount,F

		for x = 1 to nCount
			Call F()
		next	

実行結果:

.. code-block:: ring

	Message from the test function!
	Message from the test function!
	Message from the test function!
	Message from the test function!
	Message from the test function!

.. index:: 
	pair: 関数型プログラミング; 無名関数と入れ子関数

無名関数と入れ子関数
====================

無名関数は、名前を持たない関数であり、ほかの関数へ仮引数として渡したり、変数へ格納できます。

文法:

.. code-block:: ring

	Func [仮引数] { [ステートメント] }

用例:

.. code-block:: ring

	test( func x,y { 
				see "hello" + nl
				see "Sum : " + (x+y) + nl
		       } )

	new great { f1() }

	times(3, func { see "hello world" + nl } )

	func test x
		call x(3,3)
		see "wow!" + nl

	func times n,x
		for t=1 to n
			call x()
		next

	Class great
		func f1
			f2( func { see "Message from f1" + nl } )

		func f2 x
			call x()

実行結果:

.. code-block:: ring

	hello
	Sum : 6
	wow!
	Message from f1
	hello world
	hello world
	hello world

用例:

.. code-block:: ring

	Func Main
		aList = [1,2,3,4]
		Map (aList , func x { 
					return x*x 
				    } )
		see aList
		aList = [4,9,14,25]
		Map(aList, :myfilter )
		see aList
		aList = [11,12,13,14]
		Map (aList , func x {
			if x%2=0
				return "even"
			else
				return "odd"
			ok
		})
		see aList

	Func myfilter x
		if x = 9
			return "True"
		else
			return "False"
		ok

	Func Map aList,cFunc
		for x in aList
			x = call cFunc(x)
		next

実行結果:

.. code-block:: ring

	1
	4
	9
	16
	False
	True
	False
	False
	odd
	even
	odd
	even

.. index:: 
	pair: 関数型プログラミング; 等式関数

等式関数
========

if 関数 = 関数、または演算子‘=’や‘!=’を用いずにテストできます (この機能は関数の等価性、あるいは Equality of functions とも言います)。

用例:

.. code-block:: ring

	f1 = func { see "hello" + nl }

	f2 = func { see "how are you?" + nl }

	f3 = f1

	call f1()
	call f2()
	call f3()

	see (f1 = f2) + nl
	see (f2 = f3) + nl
	see (f1 = f3) + nl

実行結果:

.. code-block:: ring

	hello
	how are you?
	hello
	0
	0
	1

.. index:: 
	pair: 関数型プログラミング; 参考文献

参考文献
========

* How is the equality of functions defined? - Quora : https://www.quora.com/How-is-the-equality-of-functions-defined
