numrec.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource["dojox.lang.functional.numrec"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojox.lang.functional.numrec"] = true;
  8. dojo.provide("dojox.lang.functional.numrec");
  9. dojo.require("dojox.lang.functional.lambda");
  10. dojo.require("dojox.lang.functional.util");
  11. // This module provides recursion combinators:
  12. // - a simplified numeric linear recursion combinator.
  13. // Acknoledgements:
  14. // - recursion combinators are inspired by Manfred von Thun's article
  15. // "Recursion Theory and Joy"
  16. // (http://www.latrobe.edu.au/philosophy/phimvt/joy/j05cmp.html)
  17. // Notes:
  18. // - recursion combinators produce a function, which implements
  19. // their respective recusion patterns. String lambdas are inlined, if possible.
  20. (function(){
  21. var df = dojox.lang.functional, inline = df.inlineLambda,
  22. _r_i = ["_r", "_i"];
  23. df.numrec = function(/*Object*/ then, /*Function|String|Array*/ after){
  24. // summary:
  25. // Generates a function for the simplified numeric linear recursion pattern.
  26. // All parameter functions are called in the context of "this" object.
  27. // description:
  28. // This is a simplification of the linear recursion combinator:
  29. // - the generated function takes one numeric parameter "x",
  30. // - the "cond" is fixed and checks for 0.
  31. // - the "before" is fixed and the generated function is called with "x - 1".
  32. // - the "above is called with two parameters: the return from the generated
  33. // function, and with "x".
  34. // - as you can see the recursion is done by decreasing the parameter,
  35. // and calling itself until it reaches 0.
  36. // then:
  37. // The value, which is used upon termination of the recursion.
  38. // It will be returned as the value of the generated function.
  39. // above:
  40. // The lambda expression, which is called after the recursive step.
  41. // It accepts two parameters: the returned value from the recursive step, and
  42. // the original parameter. The returned value will be returned as the value of
  43. // the generated function.
  44. var a, as, dict = {},
  45. add2dict = function(x){ dict[x] = 1; };
  46. if(typeof after == "string"){
  47. as = inline(after, _r_i, add2dict);
  48. }else{
  49. a = df.lambda(after);
  50. as = "_a.call(this, _r, _i)";
  51. }
  52. var locals = df.keys(dict),
  53. f = new Function(["_x"], "var _t=arguments.callee,_r=_t.t,_i".concat( // Function
  54. locals.length ? "," + locals.join(",") : "",
  55. a ? ",_a=_t.a" : "",
  56. ";for(_i=1;_i<=_x;++_i){_r=",
  57. as,
  58. "}return _r"
  59. ));
  60. f.t = then;
  61. if(a){ f.a = a; }
  62. return f;
  63. };
  64. })();
  65. /*
  66. For documentation only:
  67. 1) The original recursive version:
  68. var numrec1 = function(then, after){
  69. var after = df.lambda(after);
  70. return function(x){
  71. return x ? after.call(this, arguments.callee.call(this, x - 1), x) : then;
  72. };
  73. };
  74. 2) The original iterative version (before minification and inlining):
  75. var numrec2 = function(then, after){
  76. var after = df.lambda(after);
  77. return function(x){
  78. var ret = then, i;
  79. for(i = 1; i <= x; ++i){
  80. ret = after.call(this, ret, i);
  81. }
  82. return ret;
  83. };
  84. };
  85. */
  86. }