print.apply(null, [x.toSource() for (x in ([i, j] for (i in enumFromTo(1, 4)) for (j in enumFromTo(1, 4)) if (i < j)))]); // => [1, 2] [1, 3] [1, 4] [2, 3] [2, 4] [3, 4]
正規表現の先頭固定オプションは、字句解析のときなどに使えるんじゃないかと思っています。ほかの言語を使ったりほかの手法を使ったりした場合に比べて、速度的にどうこうというのは調べていません。
現時点での JavaScript 1.7/1.8 の使いどころは、Firefox の拡張機能内部などに限られてくると思います。Web 上で気軽に使えるようになるのは果たしていつのことやら。
本題からずれているような気がしたのと時間の都合で発表からははずしましたが、Haskell の .
演算子のようなことをする compose 関数も作ってみました。
const compose = (function (f, g)
(function () f(g.apply(null, arguments))).lengthIs(g.length).curry()
).curry();
lengthIs メソッドがやっていることは「JavaScript でカリー化、再び」の setParameterLength 関数と同じです。引数 i と j が与えられると、i から j までの値を収めたリストを返す enumFromTo 関数なども定義して、Haskell での階乗を求める関数の書き方を模倣してみます。
-- Haskell
fact = product . enumFromTo 1
const enumFromTo = function (from, to) {
if (from > to) return;
yield from;
for (var i in enumFromTo(from + 1, to))
yield i;
}.curry();
const foldl = function (folder, initial, list) {
try {
return foldl(folder, folder(initial, list.next()), list);
} catch (ex if ex instanceof StopIteration) {
return initial;
}
}.curry();
const mul = (function (a, b) a * b).curry();
const product = foldl(mul, 1);
const fact = compose(product, enumFromTo(1));
print.apply(null, [fact(i) for (i in enumFromTo(1, 5))]);
// => 1 2 6 24 120
別の書き方も試してみます。
-- Haskell
fact n = (foldl (.) id [\x -> x * k | k <- [1..n]]) 1
const id = (function (x) x).curry();
const fact = function (n)
foldl(compose, id, (mul(i) for (i in enumFromTo(1, n))))(1);
print.apply(null, [fact(i) for (i in enumFromTo(1, 5))]);
// => 1 2 6 24 120
ちなみにこの enumFromTo 関数で無限リストを作ることもできます。
print.apply(null,
[i for (i in take(10, enumFromTo(1, Infinity)))]);
// => 1 2 3 4 5 6 7 8 9 10
セコメントをする