uncurryThis

## はじめに

q.jsの[ソースコード](https://github.com/kriskowal/q/blob/v1/q.js#L250-L270)中で見つけた、`uncurryThis`という関数。

```js:q.js&nbsp;250行-270行

// Attempt to make generics safe in the face of downstream
// modifications.
// There is no situation where this is necessary.
// If you need a security guarantee, these primordials need to be
// deeply frozen anyway, and if you don’t need a security guarantee,
// this is just plain paranoid.
// However, this **might** have the nice side-effect of reducing the size of
// the minified code by reducing x.call() to merely x()
// See Mark Miller’s explanation of what this does.
// http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming
var call = Function.call;
function uncurryThis(f) {
    return function () {
        return call.apply(f, arguments);
    };
}
// This is equivalent, but slower:
// uncurryThis = Function_bind.bind(Function_bind.call);
// http://jsperf.com/uncurrythis

var array_slice = uncurryThis(Array.prototype.slice);

```

コメント部分を訳してみる。

> 後の改変に対して安全に汎用化することを試みる。
> これがなくてはならない場所はない。
> 安全性を担保する必要があるのなら、これらの基本原理はどこか深くに凍結する必要があり、もし安全性を担保する必要がないのなら、これは単なる妄想である。
> しかしながらこれは`x.call()`を単に`x()`にすることによってミニファイされたコードのサイズを縮小する良い副作用をもたらす。
> これらが何をするのかはMark Millerの説明を参照せよ。

翻訳がいまいちなせいもおそらくあると思うけど、今一つ理解できない。

2つ目のコメント部分のコードはほぼ Mark Millerさんのドキュメントにある`uncurryThis`のコードである。q.jsの`uncurryThis`はこのコメントに書かれてあるコードのパフォーマンス改良版だそうだ。

ただこの`uncurryThis()`って必要なの？と思う。下のように単なるエイリアスで済むのでないかと私のようなJSビギナーだと思うよね。

```js:
var array_slice = Array.prototype.slice.call;
```

何か利点があるはずだと思いMark Millerさんのドキュメントを読むとずばり書いてあった。そのことを書く前にMark Millerさんの`uncurryThis`を見てみることにする。

## Mark MillerさんのuncurryThis

Mark Millerさんの`uncurryThis`のコードを引用すると以下の通りであった。

[conventions:safe_meta_programming [ES Wiki]](http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming)

```js:
 var addAll;
  (function() {
    "use strict";
 
    var bind = Function.prototype.bind;
    var uncurryThis = bind.bind(bind.call);
 
    // not needed for this example, but often useful
    var applyFn = uncurryThis(bind.apply);
 
    var sliceFn = uncurryThis([].slice);
 
 
    addAll = function(var_args) {
      var args = sliceFn(arguments, 0);
      //...as above
    };
  })();
```

この`uncurryThis`のコードの実装は非常に興味深いものとなっている。`uncurryThis`そのものは下記の2行である。

```js:
var bind = Function.prototype.bind;
var uncurryThis = bind.bind(bind.call);
```

`bind`変数の中身で`uncurryThis`変数の中身を置き換えると下のコードとなる。

```js:
var uncurryThis = Function.prototype.bind.bind(Function.prototype.bind.call);
```

`Function.prototype.bind`の`this`に`Function.prototype.bind.call`を束縛している。つまりこれは

```js:
// 擬似的な表現であるこということに注意すること。あくまでイメージ。
var uncurryThis = Function.prototype.bind.call.bind;
```

ということである。
ここでのポイントは`Function.prototype.bind.call.bind`の`bind`は実際には`Function.prototype.bind.call.bind`メソッドが呼ばれるのではなく、**`Function.prototype.bind`メソッドが呼ばれる**ということである。
続いて`uncurryThis`を引数`[].slice`で呼び出してみると、これは

```js:
// 擬似的な表現であるこということに注意すること。
//
uncurryThis([].slice);
//↓
Function.prototype.bind.call.bind([].slice);
//↓Function.prototype.bind部分がthisなので、そこが[].sliceに置き換わるイメージ
[].slice.call;// ただしこのcallはFunction.prototype.bind.callである。
```

となる。注意点としては`[].slice.call`の`call`は`[].slice`の`call`メソッドではなく、**`Function.prototype.bind.call`メソッドである**ということだ。
実に巧妙だが、ほかの書き方もできそうな気がする。おそらくこれが一番短い実装とかなんだろうな。q.js版のほうはパフォーマンス改良版となるのだろうか。

（それにしてもこのあたりを理解するときの脳の使われ方がC++のtemplateを使ったメタ関数を理解するときとてもよく似ている気がする。）

## uncurryThisの必要性

[Safe Meta Programming](http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming)を読むと、`uncurryThis`がなぜ必要なのかがわかる。`uncurryThis`の必要性は、ビルトイン・オブジェクトのメソッドを確実に呼び出すことができるという点にある。この点が「Safe」なのであった。

例えば`[].slice.call`の`call`が改変・削除されていても正しく動作させることができる。

具体的には`uncurryThis`を使用すれば、`Function.prototype.call`が確実に呼び出されることが保証される。（これもまた`Function.prototype.call`が正常に動作することが前提であるのだが。それと`uncurryThis`の実際のコードでは`Function.prototype.bind.call`となっているが、まあそれはそれとして）
さらにMark Millerさんの`uncurryThis`は`Function.prototype.bind.call.bind`が改変されることを想定して、`Function.prototype.bind`も確実に呼ぶようになっている。

私が最初のほうで書いた

```js:
var array_slice = Array.prototype.slice.call;
```

だと、あとでどこかで`call`が改変されると動作しなくなってしまうのだ。

さらにその副作用として、コードサイズの縮小があるわけだ。q.jsのコメントの意味がようやく理解できた。
意図したように動作するように、（ビルトイン）オブジェクトの動作を固定するのである。

## そもそもuncurryThisとは何か

Axel Rauschmayerさんのドキュメントにあるリンク「[Uncurrying `this` in JavaScript](http://www.2ality.com/2011/11/uncurrying-this.html)」を読むと以下のことが書いてあった。以下引用し翻訳すると、

>Uncurrying thisとは与えられたシグネチャ付きのメソッドを
>`obj.foo(arg1, arg2)`
>シグネチャを持つ関数に変換することである。
>`foo(obj, arg1, arg2)`

と書いてあった。

しかしカリー化の逆という意味ではなさそうだな。なぜこれを`uncurryThis`と名付けたのかね。。

## Brendan EichさんのuncurryThis 

Axel Rauschmayerさんのドキュメントには、かのBrendan EichさんのuncurryThisに関してのTweetへのリンクがある。
Tweetされた`uncurryThis`コードを引用しておく。
[https://twitter.com/BrendanEich/status/471391353536921600](https://twitter.com/BrendanEich/status/471391353536921600)

```js:
Function.prototype.uncurryThis=function(){var f = this; return function(){return f.call.apply(f,arguments)}} 
```

## 最後に

JSはいつでもオブジェクトの構造や内容が改変できてしまうので、そのことも考慮しなくてはいけないのだということがよく分かった。それが頭に入っていないと今回の`uncurryThis`も理解できないよね。