array_mapと部分適用

[PHP - 部分適用ってなんだ](http://qiita.com/tadsan/items/cec2851f70838e42be46)に続くポエムですが、どうしてもPHPで`array_map`とか`array_reduce`とかを駆使して宣言的に書きたいんだ! って人向けです。

前回のポエムでは「`foreach`があれば、別に部分適用とか要らないし」と結論を出しました。この記事は蛇足もいいところで、まったくおすすめしません。読まなくていいです。

<br><br><br><br><br><hr><br><br><br><br><br>


これが前回のポエムの最終的な結論でした。

```php
$a = [];
foreach (range(1, $n) as $m) {
    $a[] = area_trapezoid($height, 3, 5)；
}

$result = $a;
```

しかし一時変数を作って破壊的操作してくのは嫌だ! って感じかたもありそうです。

嫌なのは仕方ないので、`foreach`はやめよう。そうです、`array_map()`です。

> ## array_map
>
> `array_map` — 指定した配列の要素にコールバック関数を適用する
>
> ```php
> array array_map ( callable $callback , array $array1 [, array $... ] )
> ```
>
> `array_map()` は、`array1` の各要素に `callback` 関数を適用した後、 その全ての要素を含む配列を返します。 `callback` 関数が受け付けるパラメータの数は、 `array_map()` に渡される配列の数に一致している必要があります。
>
> *[PHP: array_map - Manual](http://php.net/manual/ja/function.array-map.php) より抜萃*

なるほど。`callback`に渡す`callable`とは何かについては [PHP: コールバック / Callable - Manual](http://php.net/manual/ja/language.types.callable.php) を読んでください。

## 適用って何だっけ

「関数を適用」とは耳馴染みがないかもしれませんが、例を示します。

```php
/**
 * 値を2倍にする
 */
function Nx2($n)
{
    return $n * 2;
}


$data = [1, 2, 3, 4, 5];
$result = array_map("Nx2", $data);
//=> [2, 4, 6, 8, 10]
```

配列に「値を2倍にする」函数を適用することで、全ての値が2倍になりました。

では次に「値を*m*倍にする」函数を適用してやりたい。

```php
/**
 * 値をM倍にする
 */
function NxM($n, $m)
{
    return $n * $m;
}
```

これを`array_map`を使って、全ての値を**3倍**に適用するにはどうすればいいか。

`NxM`は引数を二つ要求するので、配列を二つ渡してやればいいですね。

```php
$data1 = [1, 2, 3, 4, 5];
$data2 = [3, 3, 3, 3, 3];

$result = array_map("NxM", $data1, $data2);
//=> [3, 6, 9, 12, 15]
```

`$data`の要素が`$n`に、`$data2`の要素が`$m`に入ります。

これはちょっとめんどくさい… いや、`array_fill(0, count($data), 3)`とかで`data`と同じ要素数の配列を作ることはできるけど、`$data`が100万要素あったとしたら、100万個の`3`だけが並んだ配列を生成するのは、いくらなんでも無駄すぎるだろ。

「`array_map`から*n*個の引数を渡すには*n*個の配列」が必要なので、わざわざ2個の配列を作りました。

しかし、「`array_map`から1個の引数だけ渡されれば良い」ようにすれば、配列は1個で済みますね。前回のポエムで長々と部分適用の種類を紹介したのは何のためだったか。

```php
$data = [1, 2, 3, 4, 5];
$Nx3 = function($a) { return NxM($a, 3); };

$result = array_map($Nx3, $data);
//=> [3, 6, 9, 12, 15]
```

やった、配列がひとつで済んだ! だらだらとしたポエムで、ようやく「`foreach`」以外の部分適用を活用できましたね。

これで引数がいくつあっても怖くない。

<br><br><hr><br><br>

## 話を戻す

```php
$a = [];
foreach (range(1, $n) as $m) {
    $a[] = area_trapezoid($height, 3, 5)；
}

$result = $a;
```

```php
$t3_5 = function ($height) {
    return area_trapezoid($height, 3, 5);
};
$result = array_map($t3_5, range(1, $n));
```

短くなった…? わかりやすい…?

いや、どっちも意図は明確ではあるんだけど、`foreach`が`array_map`になっても別に嬉しくはないだろ、ってのが前回の記事を強引にまとめた理由です。

しかし、「短くしたい」「コードを明確にしたい」 が大差ない以上、もっと宣言的に書きたくなるのが人情です。

そのために[PartialCallable.php](https://github.com/zonuexe/php-functools/blob/master/src/PartialCallable.php)を用意したよ。

```php
$t3_5 = new PartialCallable("area_trapezoid", [1 => 3, 2 => 5], 0);
$result = array_map($t3_5, range(1, 10));
```

`new PartialCallable`の第一引数は[callable](http://php.net/manual/ja/language.types.callable.php)、第二引数は部分適用する引数を配列で指定、第三引数は`array_map`から渡された引数をどの位置に部分適用するかの指定です。

PHPの配列は0オリジンなのでわかりにくいですが、`0`が第一引数、`1`が第二引数、`2`が第三引数… とずれます。

よかったよかった。これで人類に平和が訪れます。

## 結論

`foreach`でいいじゃん。

## 完全な蛇足

日本語で「部分適用」で検索すると、たいていカレー料理の話が出てきて読者を混乱させます。 *PHPにカリー化の出番は一切ありません*。

どうしても、どうしてもカリー化とは何か気になる人は「[カリー化ってなぁに? をRubyから。](http://d.hatena.ne.jp/zonu_exe/20110910/1315669228)」と、「[Rubyでのカリー化、をまじめに。](http://d.hatena.ne.jp/zonu_exe/20110911/1315754365)」を読んで、 **二度とPHPの話題でカリー化を持ち込まない方がいいです** 。

得るものは特にないから読まなくていいし、何度でも言ふけどPHPに *カリー化の出番は一切ない* から忘れてください。