scan.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. define("dojox/lang/functional/scan", ["dojo/_base/kernel", "dojo/_base/lang", "./lambda"], function(d, darray, df){
  2. // This module adds high-level functions and related constructs:
  3. // - "scan" family of functions
  4. // Notes:
  5. // - missing high-level functions are provided with the compatible API:
  6. // scanl, scanl1, scanr, scanr1
  7. // Defined methods:
  8. // - take any valid lambda argument as the functional argument
  9. // - operate on dense arrays
  10. // - take a string as the array argument
  11. // - take an iterator objects as the array argument (only scanl, and scanl1)
  12. var empty = {};
  13. d.mixin(df, {
  14. // classic reduce-class functions
  15. scanl: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object*/ z, /*Object?*/ o){
  16. // summary: repeatedly applies a binary function to an array from left
  17. // to right using a seed value as a starting point; returns an array
  18. // of values produced by foldl() at that point.
  19. if(typeof a == "string"){ a = a.split(""); }
  20. o = o || d.global; f = df.lambda(f);
  21. var t, n, i;
  22. if(d.isArray(a)){
  23. // array
  24. t = new Array((n = a.length) + 1);
  25. t[0] = z;
  26. for(i = 0; i < n; z = f.call(o, z, a[i], i, a), t[++i] = z);
  27. }else if(typeof a.hasNext == "function" && typeof a.next == "function"){
  28. // iterator
  29. t = [z];
  30. for(i = 0; a.hasNext(); t.push(z = f.call(o, z, a.next(), i++, a)));
  31. }else{
  32. // object/dictionary
  33. t = [z];
  34. for(i in a){
  35. if(!(i in empty)){
  36. t.push(z = f.call(o, z, a[i], i, a));
  37. }
  38. }
  39. }
  40. return t; // Array
  41. },
  42. scanl1: function(/*Array|String|Object*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
  43. // summary: repeatedly applies a binary function to an array from left
  44. // to right; returns an array of values produced by foldl1() at that
  45. // point.
  46. if(typeof a == "string"){ a = a.split(""); }
  47. o = o || d.global; f = df.lambda(f);
  48. var t, n, z, first = true;
  49. if(d.isArray(a)){
  50. // array
  51. t = new Array(n = a.length);
  52. t[0] = z = a[0];
  53. for(var i = 1; i < n; t[i] = z = f.call(o, z, a[i], i, a), ++i);
  54. }else if(typeof a.hasNext == "function" && typeof a.next == "function"){
  55. // iterator
  56. if(a.hasNext()){
  57. t = [z = a.next()];
  58. for(i = 1; a.hasNext(); t.push(z = f.call(o, z, a.next(), i++, a)));
  59. }
  60. }else{
  61. // object/dictionary
  62. for(i in a){
  63. if(!(i in empty)){
  64. if(first){
  65. t = [z = a[i]];
  66. first = false;
  67. }else{
  68. t.push(z = f.call(o, z, a[i], i, a));
  69. }
  70. }
  71. }
  72. }
  73. return t; // Array
  74. },
  75. scanr: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object*/ z, /*Object?*/ o){
  76. // summary: repeatedly applies a binary function to an array from right
  77. // to left using a seed value as a starting point; returns an array
  78. // of values produced by foldr() at that point.
  79. if(typeof a == "string"){ a = a.split(""); }
  80. o = o || d.global; f = df.lambda(f);
  81. var n = a.length, t = new Array(n + 1), i = n;
  82. t[n] = z;
  83. for(; i > 0; --i, z = f.call(o, z, a[i], i, a), t[i] = z);
  84. return t; // Array
  85. },
  86. scanr1: function(/*Array|String*/ a, /*Function|String|Array*/ f, /*Object?*/ o){
  87. // summary: repeatedly applies a binary function to an array from right
  88. // to left; returns an array of values produced by foldr1() at that
  89. // point.
  90. if(typeof a == "string"){ a = a.split(""); }
  91. o = o || d.global; f = df.lambda(f);
  92. var n = a.length, t = new Array(n), z = a[n - 1], i = n - 1;
  93. t[i] = z;
  94. for(; i > 0; --i, z = f.call(o, z, a[i], i, a), t[i] = z);
  95. return t; // Array
  96. }
  97. });
  98. });