スクリプト言語 KINX/関数とクロージャ

# はじめに

[前回](https://qiita.com/Kray-G/items/926dffbf9ee52334f7d5)の続き。過去の解説は以下を参照。概要は以下の初回記事[「スクリプト言語 KINX（ご紹介）」](https://qiita.com/Kray-G/items/ca08b6fb40d15dd0ec76)を参照してください。

*   [スクリプト言語 KINX（ご紹介）](https://qiita.com/Kray-G/items/ca08b6fb40d15dd0ec76)
*   [Kinx 基本編（1） - プログラム基礎・データ型](https://qiita.com/Kray-G/items/f1f891fe799fcc757834)
*   [Kinx 基本編（2） - 制御構造](https://qiita.com/Kray-G/items/926dffbf9ee52334f7d5)
*   Kinx 要素 - 関数とクロージャ（今回）

とりあえず「**見た目は JavaScript**、**頭脳(中身)は Ruby**、（**安定感は AC/DC**）」な**スクリプト言語 KINX**、というキャッチフレーズを書いておかないと、なぜこの記事に JavaScript とか Ruby とかのタグが付いているかの説明ができないな。AC/DC は付ける必要ないけど。もちろん某作品へのオマージュを含んでいるので、正式なキャッチフレーズには使えなさそうですが。

# 関数とクロージャ

**見た目は JavaScript** の代表。ただ、最近の JavaScript はこんな感じじゃなくなってきているな。変わりすぎだよ。

## 関数

### 通常の関数

構造化プログラミングの時代から、共通の処理はひとつにまとめることは行われてきた。オブジェクト指向全盛の今でもそれは変わらない。

```javascript
function add(a, b) {
    return a + b;
}
System.println(add(1, 2));  // 3
```

引数を受け取り、色々とホゲホゲして値を返すことができる。

引数は、今どきの JavaScript で超絶便利になったスプレッド演算子によって分解、統合が可能。まるで JavaScript の話をしているみたいだが、Kinx の話だ。この機能によって可変引数なんかも実現できる。

```javascript
function toArray(...a) {
    var b = [...a]; // copy
    return b + [3];
}
System.println(toArray(1, 2).join(', '));  // "1, 2, 3"
```

ちなみにこのサンプルでやっていることに意味は無いので...、機能説明用。

再帰呼び出しも可能。ただし、末尾再帰の最適化はやってない。やるのは簡単だと思う。尚、実際やるとしても実行時にしか判断できないのと、スタックトレースが正しく取得できない問題がある（そういうものだと思えばいいのかもしれない）。

```javascript
function fib(n) {
    if (n < 3) return n;
    return fib(n-2) + fib(n-1);
}

System.println("fib(34) = ", fib(34));  // fib(34) = 9227465
```

さらに、現代の関数は単に処理が共通化できるだけではないのがミソだ。

関数は静的スコープ（レキシカル・スコープ）を持ち、クロージャが実現可能。クロージャに関しては後述する。

### 無名関数

無名関数として式中に直接関数定義を書ける。関数を別の関数の引数にもできる。

```javascript
var calc = function(func, a, b) {
    return func(a, b);
};
System.println(calc(function(a, b) { return a + b; }, 2, 3));   // 5
```

### ラムダ式

上記の無名関数をより簡潔に書けるようにしたのがラムダ式。`function` の代わりに `&` を、ブロックの代わりに `=> expression` の形をとる。上記サンプルを書き換えるとこうなる。

```javascript
var calc = &(func, a, b) => func(a, b);
System.println(calc(&(a, b) => a + b, 2, 3));   // 5
```

実は、`expression` の部分はブロックも取れるので、何か複数の処理を記載したい場合は `&(args) => { ... }` の形で記載することができる。逆にこの機能のため、`expression` に直接オブジェクトを書くことができない点に注意。オブジェクトを直接返したい場合は、`({ a: 100 })` とかっこで括ることで回避する。

### ブロック・オブジェクト

派生して、ブロック・オブジェクトを定義できるようにした。以下のように `&{...}` の形でブロックを引数として渡すことができる。

```javascript
var a = 10;
var doit = &(block) => block();
System.println(doit(&{
    return a + 100;
}));
```

中身は引数無しの無名関数でしかないのだが、ブロックを渡してる感じが出ていいかなと思って。単純に `&() => { ... }` をさらに簡潔に記述できるようにしただけ。

話はそれるが、`&(a,b) => {...}` を `&{|a,b| ... }` とか書けるようにすると多少 Ruby っぽくなる...かな。意味があるかどうかは別として。実装は簡単。**見た目は JavaScript** のポリシーからするとやってはいけないのかもしれないが、**思想は Ruby** で何でもありな世界観だと思えばやっていいのかもしれない。

時を戻そう。

## クロージャ

クロージャとは静的スコープを持つ関数オブジェクトのこと。よくあるサンプルは以下。

```javascript
function newCounter() {
    var i = 0;          // a lexical variable.

    return function() { // an anonymous function.
        ++i;            // a reference to a lexical variable.
        return i;
    };
}

var c1 = newCounter();
System.println(c1()); // 1
System.println(c1()); // 2
System.println(c1()); // 3
System.println(c1()); // 4
System.println(c1()); // 5
```

静的スコープを持つことによって、関数呼び出しに対して状態を持つことができる所がポイント。ん？クラス・インスタンスみたいだって？正解。実際、ある意味 JavaScript のクラスの概念はここから派生している。そして、Kinx のクラスはまさにその **延長線上** にある。

# おわりに

ということで、次はクラス。モジュールも実装したので、合わせてお届けしよう。

例によって★欲しさのための宣伝。ちょっとずつ増えているのが非常にうれしい。皆さん、ありがとうございます。

* [ここ (https://github.com/Kray-G/kinx)](https://github.com/Kray-G/kinx)。