Number#lazy をやめて Number#wait にしたいメモ
Number#lazy を作ってみて、
メソッド名の改善と引数の並びに改善可能な点を感じたので、
Number#lazy は廃止して Number#wait にして、さらに引数変えるかもよの巻。
何を考えてAPIの変更を行なったかメモ
Number#lazy の実装はこうなっています。
// Number#lazy function Number_lazy(fn, // @arg Function: callback args, // @arg Mix/MixArray(= undefined): callback(args) that) { // @arg this(= null): // @return Number: atom (setTimeout timer id) // @help: Number#Number.prototype.lazy // @desc: lazy callback function //{@assert mm.allow(fn, FN); mm.allow(args, ARRAY | UNDEF); //}@assert return setTimeout(function() { fn.apply(that || null, Array.isArray(args) ? args : [args]); }, this * 1000); }
Number#wait はこうなる予定です。
function Number_wait(fn_that // @arg Function/FunctionAndThatArray: callback or [callback, that] /*, ... */) { // @var_arg Mix(= undefined): callback.apply(that, var_args) // @this Number: delay seconds // @return Number: atom (setTimeout timer id) // @help: Number#Number.prototype.wait // @desc: lazy evaluate //{@assert mm.allow(fn_that, FN | ARRAY); if (Array.isArray(fn_that)) { if (!mm.isFn(fn_that[0]) || fn_that.length !== 2) { throw new Error("BAD_ARG"); } } //}@assert var fn = fn_that[0] || fn_that, that = fn_that[1] || null, args = Array.prototype.slice.call(arguments, 1); return setTimeout(function() { fn.apply(that, args); }, this * 1000); }
Number#lazy は 0..lazy(コールバック関数, [引数], this) の形で指定しますが、this を渡すために 0..lazy(fn, [], this) とするのが無駄に感じられる人もいるということで、 Number#wait では 0..wait(コールバック引数, var_args) または 0..wait([コールバック引数, this], var_args) の形で指定できるように、引数の構造を変えています。
0..lazy(fn); // fn() を遅延評価 0..lazy(fn, ["arg1", "arg2"]); // fn("arg1", "arg2") を遅延評価 0..lazy(fn, [], this); // this.fn() を遅延評価 0..lazy(fn, ["arg1", "arg2"], this); // this.fn("arg1", "arg2") を遅延評価 0..wait(fn); // fn() を遅延評価 0..wait(fn, "arg1", "arg2"); // fn("arg1", "arg2") を遅延評価 0..wait([fn, this]); // this.fn() を遅延評価 0..wait([fn, this], "arg1", "arg2"); // this.fn("arg1", "arg2") を遅延評価
Number#wait の引数の並びのほうが若干短く書けるし、見慣れると自然に感じられるかなーと。
# Number#lazy の最後に this を指定する書式は、Array#forEach 系がそんな感じだから、それに発想が引きづられてしまってた感じですね
Number#wait の引数展開部分は、正しくは↓こう書くべきなんだろうけど、
var fn, that, args = Array_slice(arguments, 1); if (Array.isArray(fn_that)) { fn = fn_that[0]; that = fn_that[1]; } else { fn = fn_that; }
↓のように、関数オブジェクトに 0 と 1 を生やし適切な値を設定しておくと、自己参照呼び出しも可能になるなーと考え、あのようにしています。裏ワザ的用法で知っていれば使えるということで。
function aaa(a, b, c) { console.log(123, a, b, c, this.hoge); // 123 1 2 3 "hogehoge" } aaa[0] = aaa; aaa[1] = aaa; aaa["hoge"] = "hogehoge"; 2..wait(aaa, 1, 2, 3);
jQuery のように「関数なんだけど、配列の要素が格納されている変造オブジェクト」を Number#wait に食べさせると、誤作動起こす可能性があるので、0..wait(jQuery, "arg") の結果は不定になります。
でも 0..wait(jQuery, "arg") なコードは絶対に書かれないだろうから、それは織り込み済み(designed)ってことになります。