iterflow 0.4.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -221,13 +221,52 @@ const movingAverages = iter(temperatures)
221
221
  .toArray();
222
222
  ```
223
223
 
224
- <!-- BENCHMARK_SUMMARY_START -->
225
- <!-- BENCHMARK_SUMMARY_END -->
224
+ ## When to Use iterflow
225
+
226
+ iterflow balances developer experience with performance. Here's how to decide:
227
+
228
+ ### Use iterflow when:
229
+
230
+ - **Large datasets** (1000+ items) - lazy evaluation avoids unnecessary work
231
+ - **Early termination** - finding first match, taking limited results (find, some, every, take)
232
+ - **Memory efficiency** - windowing, chunking, or processing huge files
233
+ - **Complex pipelines** - chaining 3+ operations together
234
+ - **Statistical operations** - mean, median, variance, percentile calculations
235
+ - **Code readability** - method chaining feels more natural than manual loops
236
+
237
+ ### Consider alternatives when:
238
+
239
+ - **Small arrays** (< 100 items) - native Array methods are slightly faster
240
+ - **Single simple operation** - map or filter alone on small data
241
+ - **Performance-critical hot paths** - called millions of times, every microsecond matters
242
+ - **Need multiple iterations** - arrays are easier to loop over multiple times
243
+
244
+ ### The Trade-off
245
+
246
+ iterflow uses lazy evaluation, which means:
247
+ - **Lower memory usage** - no intermediate arrays created
248
+ - **Slightly slower per operation** - small function call overhead
249
+ - **Better for large datasets** - memory savings far exceed speed cost
250
+ - **Better for partial consumption** - stops early when possible
251
+
252
+ ### Real Performance Impact
253
+
254
+ For datasets < 100 items, the differences are negligible—use what feels natural.
255
+
256
+ For datasets > 1000 items:
257
+ - **With early termination** (take 10 from 100K): iterflow can be 20-300x faster
258
+ - **With windowing** (moving average): iterflow can be 35-600x faster due to memory efficiency
259
+ - **Full consumption** (process all items): native arrays are 2-5x faster
260
+
261
+ See **[docs/BENCHMARKS.md](docs/BENCHMARKS.md)** for detailed performance data and specific operation comparisons.
226
262
 
227
263
  ## Documentation
228
264
 
229
265
  - **[FAQ](FAQ.md)** - Frequently asked questions, common patterns, and troubleshooting
230
266
  - **[Examples](examples/)** - Real-world usage examples
267
+ - **[Memory Safety Guide](docs/guides/memory-safety.md)** - Avoiding memory leaks and efficient memory usage
268
+ - **[Performance Guide](docs/PERFORMANCE.md)** - Optimization techniques and benchmarking
269
+ - **[Benchmarking Guide](docs/BENCHMARKING.md)** - Running and interpreting benchmarks
231
270
  - **[SECURITY.md](SECURITY.md)** - Security best practices and vulnerability reporting
232
271
 
233
272
  ## Contributing
package/dist/fn/index.cjs CHANGED
@@ -183,6 +183,13 @@ function transducerToIterator(transducer) {
183
183
 
184
184
  // src/fn/index.ts
185
185
  function sum(iterable) {
186
+ if (Array.isArray(iterable)) {
187
+ let total2 = 0;
188
+ for (let i = 0; i < iterable.length; i++) {
189
+ total2 += iterable[i];
190
+ }
191
+ return total2;
192
+ }
186
193
  let total = 0;
187
194
  for (const value of iterable) {
188
195
  total += value;
@@ -190,6 +197,14 @@ function sum(iterable) {
190
197
  return total;
191
198
  }
192
199
  function mean(iterable) {
200
+ if (Array.isArray(iterable)) {
201
+ if (iterable.length === 0) return void 0;
202
+ let total2 = 0;
203
+ for (let i = 0; i < iterable.length; i++) {
204
+ total2 += iterable[i];
205
+ }
206
+ return total2 / iterable.length;
207
+ }
193
208
  let total = 0;
194
209
  let count2 = 0;
195
210
  for (const value of iterable) {
@@ -199,6 +214,10 @@ function mean(iterable) {
199
214
  return count2 === 0 ? void 0 : total / count2;
200
215
  }
201
216
  function min(iterable) {
217
+ if (Array.isArray(iterable)) {
218
+ if (iterable.length === 0) return void 0;
219
+ return Math.min(...iterable);
220
+ }
202
221
  let minimum = void 0;
203
222
  for (const value of iterable) {
204
223
  if (minimum === void 0 || value < minimum) {
@@ -208,6 +227,10 @@ function min(iterable) {
208
227
  return minimum;
209
228
  }
210
229
  function max(iterable) {
230
+ if (Array.isArray(iterable)) {
231
+ if (iterable.length === 0) return void 0;
232
+ return Math.max(...iterable);
233
+ }
211
234
  let maximum = void 0;
212
235
  for (const value of iterable) {
213
236
  if (maximum === void 0 || value > maximum) {
@@ -217,6 +240,9 @@ function max(iterable) {
217
240
  return maximum;
218
241
  }
219
242
  function count(iterable) {
243
+ if (Array.isArray(iterable)) {
244
+ return iterable.length;
245
+ }
220
246
  let count2 = 0;
221
247
  for (const _ of iterable) {
222
248
  count2++;
@@ -224,18 +250,18 @@ function count(iterable) {
224
250
  return count2;
225
251
  }
226
252
  function median(iterable) {
227
- const values = Array.from(iterable);
253
+ const values = Array.isArray(iterable) ? iterable : Array.from(iterable);
228
254
  if (values.length === 0) return void 0;
229
- values.sort((a, b) => a - b);
230
- const mid = Math.floor(values.length / 2);
231
- if (values.length % 2 === 0) {
232
- return (values[mid - 1] + values[mid]) / 2;
255
+ const sorted = values.slice().sort((a, b) => a - b);
256
+ const mid = Math.floor(sorted.length / 2);
257
+ if (sorted.length % 2 === 0) {
258
+ return (sorted[mid - 1] + sorted[mid]) / 2;
233
259
  } else {
234
- return values[mid];
260
+ return sorted[mid];
235
261
  }
236
262
  }
237
263
  function variance(iterable) {
238
- const values = Array.from(iterable);
264
+ const values = Array.isArray(iterable) ? iterable : Array.from(iterable);
239
265
  if (values.length === 0) return void 0;
240
266
  const mean2 = values.reduce((sum2, val) => sum2 + val, 0) / values.length;
241
267
  let sumSquaredDiffs = 0;
@@ -251,22 +277,22 @@ function stdDev(iterable) {
251
277
  }
252
278
  function percentile(iterable, p) {
253
279
  validateRange(p, 0, 100, "percentile", "percentile");
254
- const values = Array.from(iterable);
280
+ const values = Array.isArray(iterable) ? iterable : Array.from(iterable);
255
281
  if (values.length === 0) return void 0;
256
- values.sort((a, b) => a - b);
257
- if (p === 0) return values[0];
258
- if (p === 100) return values[values.length - 1];
259
- const index = p / 100 * (values.length - 1);
282
+ const sorted = values.slice().sort((a, b) => a - b);
283
+ if (p === 0) return sorted[0];
284
+ if (p === 100) return sorted[sorted.length - 1];
285
+ const index = p / 100 * (sorted.length - 1);
260
286
  const lower = Math.floor(index);
261
287
  const upper = Math.ceil(index);
262
288
  if (lower === upper) {
263
- return values[lower];
289
+ return sorted[lower];
264
290
  }
265
291
  const weight = index - lower;
266
- return values[lower] * (1 - weight) + values[upper] * weight;
292
+ return sorted[lower] * (1 - weight) + sorted[upper] * weight;
267
293
  }
268
294
  function mode(iterable) {
269
- const values = Array.from(iterable);
295
+ const values = Array.isArray(iterable) ? iterable : Array.from(iterable);
270
296
  if (values.length === 0) return void 0;
271
297
  const frequency = /* @__PURE__ */ new Map();
272
298
  let maxFreq = 0;
@@ -284,20 +310,20 @@ function mode(iterable) {
284
310
  return modes.sort((a, b) => a - b);
285
311
  }
286
312
  function quartiles(iterable) {
287
- const values = Array.from(iterable);
313
+ const values = Array.isArray(iterable) ? iterable : Array.from(iterable);
288
314
  if (values.length === 0) return void 0;
289
- values.sort((a, b) => a - b);
315
+ const sorted = values.slice().sort((a, b) => a - b);
290
316
  const calculatePercentile = (p) => {
291
- if (p === 0) return values[0];
292
- if (p === 100) return values[values.length - 1];
293
- const index = p / 100 * (values.length - 1);
317
+ if (p === 0) return sorted[0];
318
+ if (p === 100) return sorted[sorted.length - 1];
319
+ const index = p / 100 * (sorted.length - 1);
294
320
  const lower = Math.floor(index);
295
321
  const upper = Math.ceil(index);
296
322
  if (lower === upper) {
297
- return values[lower];
323
+ return sorted[lower];
298
324
  }
299
325
  const weight = index - lower;
300
- return values[lower] * (1 - weight) + values[upper] * weight;
326
+ return sorted[lower] * (1 - weight) + sorted[upper] * weight;
301
327
  };
302
328
  return {
303
329
  Q1: calculatePercentile(25),