関数型に関する説明について

#初めに
私自身、関数型言語に興味があって色々なサイトを見ています
関数型言語のメリットが丁寧に書いてあって”関数型言語っていいな”と思わせるサイトもあれば、逆に”うーん、これでは関数型言語のメリットを感じさせないな”というサイトもあります
今回、書いてみたいことは、”関数型言語のメリットを感じさせないサイト”の特徴についてです
#具体的なサイトの例
サンプルとして挙げさせてもらうのは[コードIQのサイト](http://getnews.jp/archives/1419566)です
上記のサイトの趣旨は配列の処理を命令型言語(C言語)と関数型言語(Haskell)で書き、両者を比較して、関数型言語(Haskell)が分かりやすいよね、ということのようです
#何が問題か
関数型言語(Haskell)の記述がとても簡潔であるということには心から同意しますが、命令型言語の例として挙げられているC言語のロジックにいささか問題があると、個人的に考えています。そのため、サイトの最後の関数型言語(Haskell)のメリットと言われていることが、本当にメリットがあるのかどうかわかりません。
例えば、このサイトで関数型言語のメリットと言われているreduceやmapが、命令型言語で実装した時、大した手間がかかるものでなければ、真にメリットがあるといえないでしょうから。
#サンプルプログラムの問題点
以下、個人的に感じたサンプルプログラムの問題点を挙げてみます
###問題点１　変数名が何を意味しているのか分からない
サンプルプログラムのiとかNって一体、何を表しているのでしょうか？
私は変数名が何を表しているかわからなかったので、プログラムを一読しただけでは何のためのロジックかわかりませんでした
少なくとも、iはcounter,NはARRAY_LIMITTED_NUMBERとして、変数が持つ役割を明確化するべきでしょう
###問題点２　配列の宣言方法が変
配列を初期化するとき初期化子を使うのだったら、配列の要素数の設定はいらないのでは？
###問題点３　配列へのアクセスが変
変というと語弊があるかもしれませんが、配列へのアクセスは添え字ではなくポインタを使ったほうが処理は簡潔に書けるのではないでしょうか？
ポインタでアクセスすれば、少なくとも変数iは不要になるはずです
###問題点３　配列のデータ構造
問題点というより、こうしたほうがいいのでは？という提案です。
配列の終わりを表すためにNULLを導入したほうがよさそうです
そうすれば、ループ脱出条件を判定するときに添え字と配列の最大要素数を比較する必要がなくなります。
まぁ、この場合、配列の途中でNULLが挿入されたらどうすんだ、という問題がありますが、C言語を使う以上、配列の終端は何らかの決まりを作る必要がありますしね
サンプルプログラムもdefineでこっそり配列の要素数の最大を5で定義していますし。
###問題点４　データ処理とデータ制御が混在している点について
オリジナルのプログラムではデータの制御(ループ処理)とデータの処理(蛇とカエルのシミュレーション)を一か所で行っています。
でも、これって、関数型言語以前にもう何十年前から言われている構造化プログラミングに反しているのではないでしょうか？
今どきの開発を行っているのであれば、どんな言語を使おうが、データの制御とデータの処理は別々の関数に切り出すべきです

#具体的なC言語のソース
以下、自分なりに改良したC言語のコードを掲載してみます
##改良後のソース
```c:sample.c
#include "stdafx.h"

//生き残るカエルの数を計算します
int calc(int snakes, int flogs) {
	if (flogs >= snakes) return flogs - snakes;
	else return 0;
}

//カエルと蛇の配列を操作する関数です
int execute(int snakes[], int flogs[]) {
	int survivors = 0; //生き残ったカエルの総数
	while (true) {
		//配列の終端まで来たらループを脱出する
		if (*snakes == NULL) break;
		survivors += calc(*snakes++, *flogs++);
	}
	return survivors;
}

int main()
{
	int snakes[] = { 5,4,3,2,1,NULL };//蛇
	int flogs[] = { 7,6,1,2,2 ,NULL };//カエル
	printf("生き残ったカエルの数 %5d", execute(snakes, flogs));
	getchar();
	return 0;
}
```
プロトタイプ宣言を使って、関数型言語のreduceやmapっぽい動作もできるようにしました
##改良後のソース(map,reduce版)
```c:sample.c
#include "stdafx.h"
typedef int(*FUNCPTR)(int a, int b);

//カエルと蛇の配列を操作する関数です
//FUNCPTRにはカエルと蛇の生存競争をシミュレートした関数ポインタを渡します
int zip_and_reduce(int snakes[], int flogs[],FUNCPTR func) {
	int survivors = 0; //生き残ったカエルの総数
	while (true) {
		//配列にNULLがあらわれたらループを脱出する
		if (*snakes == NULL) break;
		survivors += func(*snakes++, *flogs++);
	}
	return survivors;
}

//生き残るカエルの数を計算します
int calc(int snakes, int flogs) {
	if (flogs >= snakes) return flogs - snakes;
	else return 0;
}

//カエルと蛇が共存した時の数を計算します
int calc_kyouzon(int snakes, int flogs) {
	return flogs + snakes;
}

int main()
{
	int snakes[] = { 5,4,3,2,1,NULL };//蛇
	int flogs[] = { 7,6,1,2,2 ,NULL };//カエル
	printf("生き残ったカエルの数 %5d", zip_and_reduce(snakes, flogs,&calc));
	printf("蛇とカエルが共存した時の数 %5d", zip_and_reduce(snakes, flogs, &calc_kyouzon));
	getchar();
	return 0;
}
```
ついでにJavaで実装したVerも掲載します

```sample.java
package test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

public class MyTest {
    public static void main(String args[]){
		List<Integer>snakes = new ArrayList<Integer>();
		Collections.addAll(snakes, 1,2,3,20);
		List<Integer>flogs = new ArrayList<Integer>();
		Collections.addAll(flogs, 10,2,3,4,5);
		System.out.println(execute(snakes,flogs));
	}
	//外部に公開する関数
	//引数に蛇とカエルの引数を渡す
	public static int execute(List<Integer>snaeks,List<Integer>flogs){
		//最初の合計値は0
		return execute(snaeks.iterator(),flogs.iterator() ,0);
	}
    //内部で使用する関数
	//Iterator<Integer>snakes　:　snakesの列挙型
	//Iterator<Integer>　:　flogsの列挙型
	//sum　:　flogsの合計値
	private static int execute(Iterator<Integer>snakes,Iterator<Integer>flogs ,int sum){
		//蛇もカエルもいなくなったら、処理を完了する
		if(!snakes.hasNext() && !flogs.hasNext())return sum;
		//蛇とカエル、いずれかが存在する場合は処理を続ける
		else return execute(snakes,flogs,sum + calc(ifExists(snakes),ifExists(flogs) ) );
	}	
	//カエルの数を求めます
	//カエルが蛇より多いとき、カエルの数から蛇の数を引いた値を返します
	//int snakes　： 蛇の数
	//int flogs ：　カエルの数
	private static int calc(int snakes,int flogs){
		if(snakes<= flogs) return flogs - snakes;
		else return 0;
	}
    //列挙子に要素がある場合はその要素を返し、なければ0を返します
	private static int ifExists(Iterator<Integer>ite){
		if(ite.hasNext())return ite.next();
		else return 0;
	}
}
```
#終わりに
改善後の命令型言語のソースと関数型言語のソースをみて、思うことは人それぞれだと思います
私自身は関数型言語(Haskell) について、さほど使いこなしているわけではありませんが

- C言語と比較すると配列の扱いが楽
- Javaと比較するとCでいうところの関数ポインタ(のようなもの)の扱いやすいことと、型の定義に柔軟性がある

というメリットがあるなと感じています

逆に、reduceやmapが使えるから便利という説明は、うーん、どうかな？と思ってしまったりします