@effekt-lang/effekt 0.22.0 → 0.24.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/bin/effekt +0 -0
- package/libraries/common/array.effekt +381 -7
- package/libraries/common/stream.effekt +11 -0
- package/libraries/llvm/file.c +1 -0
- package/libraries/llvm/rts.ll +103 -92
- package/licenses/eclipse public license, version 2.0 - epl-2.0.html +2 -2
- package/licenses/mit license - mit-license.html +46 -30
- package/licenses/the bsd license - bsd-license.html +45 -29
- package/licenses/the mit license - mit.html +46 -32
- package/package.json +1 -1
package/bin/effekt
CHANGED
|
Binary file
|
|
@@ -3,6 +3,7 @@ module array
|
|
|
3
3
|
import effekt
|
|
4
4
|
import exception
|
|
5
5
|
import list
|
|
6
|
+
import option
|
|
6
7
|
|
|
7
8
|
/// A mutable 0-indexed fixed-sized array.
|
|
8
9
|
extern type Array[T]
|
|
@@ -18,12 +19,17 @@ extern global def allocate[T](size: Int): Array[T] =
|
|
|
18
19
|
"""
|
|
19
20
|
vm "array::allocate(Int)"
|
|
20
21
|
|
|
22
|
+
/// Fills a given array in-place.
|
|
23
|
+
def fill[T](arr: Array[T], filler: T): Unit = {
|
|
24
|
+
arr.foreachIndex { (idx, _) =>
|
|
25
|
+
arr.unsafeSet(idx, filler)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
21
29
|
/// Creates a new Array of size `size` filled with the value `init`
|
|
22
30
|
def array[T](size: Int, init: T): Array[T] = {
|
|
23
31
|
val arr = allocate[T](size);
|
|
24
|
-
|
|
25
|
-
unsafeSet(arr, i, init)
|
|
26
|
-
};
|
|
32
|
+
arr.fill(init)
|
|
27
33
|
arr
|
|
28
34
|
}
|
|
29
35
|
|
|
@@ -81,8 +87,6 @@ extern global def unsafeSet[T](arr: Array[T], index: Int, value: T): Unit =
|
|
|
81
87
|
"""
|
|
82
88
|
vm "array::unsafeSet[T](Array[T], Int, T)"
|
|
83
89
|
|
|
84
|
-
|
|
85
|
-
|
|
86
90
|
// Derived operations:
|
|
87
91
|
|
|
88
92
|
/// Gets the element of the `arr` at given `index` in constant time,
|
|
@@ -107,6 +111,9 @@ def build[T](size: Int) { index: Int => T }: Array[T] = {
|
|
|
107
111
|
arr
|
|
108
112
|
}
|
|
109
113
|
|
|
114
|
+
/// Resizes an array to a given size.
|
|
115
|
+
///
|
|
116
|
+
/// O(N + M)
|
|
110
117
|
def resize[T](source: Array[T], size: Int): Array[T] = {
|
|
111
118
|
val target = allocate(size)
|
|
112
119
|
val n = min(source.size, target.size)
|
|
@@ -147,6 +154,27 @@ def copy[T](from: Array[T], start: Int, to: Array[T], offset: Int, length: Int):
|
|
|
147
154
|
|
|
148
155
|
// Utility functions:
|
|
149
156
|
|
|
157
|
+
/// Swap the value at index i with that at index j.
|
|
158
|
+
/// Warning: undefined behaviour if the indices are out bound.
|
|
159
|
+
///
|
|
160
|
+
/// O(1)
|
|
161
|
+
def unsafeSwap[A](arr: Array[A], i: Int, j: Int): Unit = {
|
|
162
|
+
val tmp = arr.unsafeGet(i)
|
|
163
|
+
arr.unsafeSet(i, arr.unsafeGet(j))
|
|
164
|
+
arr.unsafeSet(j, tmp)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/// Swap the value at index i with that at index j.
|
|
168
|
+
///
|
|
169
|
+
/// O(1)
|
|
170
|
+
def swap[A](arr: Array[A], i: Int, j: Int): Unit / Exception[OutOfBounds] = {
|
|
171
|
+
if (i < 0 || i >= arr.size || j < 0 || j >= arr.size) do raise(OutOfBounds(), "Index out of bounds")
|
|
172
|
+
arr.unsafeSwap(i, j)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/// Converts the given array into a list.
|
|
176
|
+
///
|
|
177
|
+
/// O(N)
|
|
150
178
|
def toList[T](arr: Array[T]): List[T] = {
|
|
151
179
|
var i = arr.size - 1;
|
|
152
180
|
var l = Nil[T]()
|
|
@@ -157,34 +185,380 @@ def toList[T](arr: Array[T]): List[T] = {
|
|
|
157
185
|
l
|
|
158
186
|
}
|
|
159
187
|
|
|
188
|
+
/// Traverse an array, applying the given action on every element.
|
|
189
|
+
///
|
|
190
|
+
/// O(N)
|
|
160
191
|
def foreach[T](arr: Array[T]){ action: T => Unit }: Unit =
|
|
161
192
|
each(0, arr.size) { i =>
|
|
162
193
|
action(arr.unsafeGet(i))
|
|
163
194
|
}
|
|
164
195
|
|
|
196
|
+
/// Traverse an array, applying the given action on every element.
|
|
197
|
+
///
|
|
198
|
+
/// O(N)
|
|
165
199
|
def foreach[T](arr: Array[T]){ action: (T) {Control} => Unit }: Unit =
|
|
166
200
|
each(0, arr.size) { (i) {label} =>
|
|
167
201
|
action(arr.unsafeGet(i)) {label}
|
|
168
202
|
}
|
|
169
203
|
|
|
204
|
+
/// Traverse an array, applying the given action on every element and its (zero-based) index.
|
|
205
|
+
///
|
|
206
|
+
/// O(N)
|
|
170
207
|
def foreachIndex[T](arr: Array[T]){ action: (Int, T) => Unit }: Unit =
|
|
171
208
|
each(0, arr.size) { i =>
|
|
172
209
|
action(i, arr.unsafeGet(i))
|
|
173
210
|
}
|
|
174
211
|
|
|
212
|
+
/// Traverse an array, applying the given action on every element and its (zero-based) index.
|
|
213
|
+
///
|
|
214
|
+
/// O(N)
|
|
175
215
|
def foreachIndex[T](arr: Array[T]){ action: (Int, T) {Control} => Unit }: Unit =
|
|
176
216
|
each(0, arr.size) { (i) {label} =>
|
|
177
217
|
action(i, arr.unsafeGet(i)) {label}
|
|
178
218
|
}
|
|
179
219
|
|
|
180
|
-
|
|
220
|
+
/// Sum the elements of the array.
|
|
221
|
+
///
|
|
222
|
+
/// O(N)
|
|
223
|
+
def sum(arr: Array[Int]): Int = {
|
|
181
224
|
var acc = 0
|
|
182
|
-
|
|
225
|
+
arr.foreach { x =>
|
|
183
226
|
acc = acc + x
|
|
184
227
|
}
|
|
185
228
|
acc
|
|
186
229
|
}
|
|
187
230
|
|
|
231
|
+
/// Checks whether two given arrays are equal with respect to an equalty funciton defined on their element.
|
|
232
|
+
///
|
|
233
|
+
/// O(N)
|
|
234
|
+
def equals[A](this: Array[A], other: Array[A]) { eq: (A, A) => Bool }: Bool = {
|
|
235
|
+
if (this.size != other.size) false
|
|
236
|
+
else {
|
|
237
|
+
var res = true
|
|
238
|
+
this.foreachIndex { (idx, elem) {label} =>
|
|
239
|
+
if (not(eq(elem, other.unsafeGet(idx)))) {
|
|
240
|
+
res = false
|
|
241
|
+
label.break()
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
res
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/// Map a function `f` over the elements in a given array.
|
|
249
|
+
/// Modifies the array in-place.
|
|
250
|
+
///
|
|
251
|
+
/// O(N)
|
|
252
|
+
def map[A](arr: Array[A]) { f: A => A }: Unit = {
|
|
253
|
+
arr.foreachIndex { (idx, elem) =>
|
|
254
|
+
arr.unsafeSet(idx, f(arr.unsafeGet(idx)))
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/// Map a function over elements.
|
|
259
|
+
/// Allocates a new array of the same size.
|
|
260
|
+
///
|
|
261
|
+
/// O(N)
|
|
262
|
+
def mapped[A, B](arr: Array[A]) { f: A => B }: Array[B] = {
|
|
263
|
+
val res = allocate(arr.size)
|
|
264
|
+
arr.foreachIndex { (idx, elem) =>
|
|
265
|
+
res.unsafeSet(idx, f(arr.unsafeGet(idx)))
|
|
266
|
+
}
|
|
267
|
+
res
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/// Reverses an array in-place.
|
|
271
|
+
///
|
|
272
|
+
/// O(N)
|
|
273
|
+
def reverse[A](arr: Array[A]): Unit = {
|
|
274
|
+
val size = arr.size()
|
|
275
|
+
val mid = size / 2
|
|
276
|
+
|
|
277
|
+
// Swap elements from start and end, moving towards the middle
|
|
278
|
+
each(0, mid) { i =>
|
|
279
|
+
val temp = arr.unsafeGet(i)
|
|
280
|
+
val j = size - 1 - i
|
|
281
|
+
val other = arr.unsafeGet(j)
|
|
282
|
+
arr.unsafeSet(i, other)
|
|
283
|
+
arr.unsafeSet(j, temp)
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
/// Creates a new array with elements in reverse order.
|
|
287
|
+
///
|
|
288
|
+
/// O(N)
|
|
289
|
+
def reversed[A](arr: Array[A]): Array[A] = {
|
|
290
|
+
val size = arr.size()
|
|
291
|
+
val result = allocate[A](size)
|
|
292
|
+
|
|
293
|
+
// Copy elements in reverse order to new array
|
|
294
|
+
each(0, size) { i =>
|
|
295
|
+
val value = arr.unsafeGet(i)
|
|
296
|
+
result.unsafeSet(size - 1 - i, value)
|
|
297
|
+
}
|
|
298
|
+
result
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/// Fold an array using `f`, starting from the left given a starting value.
|
|
302
|
+
///
|
|
303
|
+
/// O(N)
|
|
304
|
+
def foldLeft[A, B](arr: Array[A], init: B) { f: (B, A) => B }: B = {
|
|
305
|
+
var acc = init;
|
|
306
|
+
arr.foreach { x => acc = f(acc, x) };
|
|
307
|
+
acc
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/// Fold an array using `f`, starting from the right given a starting value.
|
|
311
|
+
///
|
|
312
|
+
/// O(N)
|
|
313
|
+
def foldRight[A, B](arr: Array[A], init: B) { f: (A, B) => B }: B = {
|
|
314
|
+
var acc = init;
|
|
315
|
+
arr.reversed.foreach { x => acc = f(x, acc) };
|
|
316
|
+
acc
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/// Filters a given array with respect to a given predicate such that a
|
|
320
|
+
/// new array containing all the elements for which the predicate
|
|
321
|
+
/// holds is allocated.
|
|
322
|
+
///
|
|
323
|
+
/// O(N)
|
|
324
|
+
def filtered[A](arr: Array[A]) { shouldKeep: A => Bool }: Array[A] = {
|
|
325
|
+
val res = arr.copy()
|
|
326
|
+
var idx = 0
|
|
327
|
+
arr.foreach { x =>
|
|
328
|
+
if (shouldKeep(x)) {
|
|
329
|
+
res.unsafeSet(idx, x)
|
|
330
|
+
idx = idx + 1
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
res.resize(idx)
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/// Check if predicate is true for all elements.
|
|
337
|
+
///
|
|
338
|
+
/// O(N)
|
|
339
|
+
def all[A](arr: Array[A]) { predicate: A => Bool }: Bool = {
|
|
340
|
+
var result = true
|
|
341
|
+
arr.foreach { (x) {label} =>
|
|
342
|
+
if (not(predicate(x))) {
|
|
343
|
+
result = false
|
|
344
|
+
label.break()
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
result
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/// Check if predicate is true for at least one element.
|
|
351
|
+
///
|
|
352
|
+
/// O(N)
|
|
353
|
+
def any[A](arr: Array[A]) { predicate: A => Bool }: Bool = {
|
|
354
|
+
not(arr.all { x => not(predicate(x)) })
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/// Count elements satisfying the predicate.
|
|
358
|
+
///
|
|
359
|
+
/// O(N)
|
|
360
|
+
def count[A](arr: Array[A]) { predicate: A => Bool }: Int = {
|
|
361
|
+
var count = 0
|
|
362
|
+
arr.foreach { x =>
|
|
363
|
+
if (predicate(x)) count = count + 1
|
|
364
|
+
}
|
|
365
|
+
count
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/// Take first n elements.
|
|
369
|
+
/// Returns a new array.
|
|
370
|
+
///
|
|
371
|
+
/// O(N)
|
|
372
|
+
def take[A](arr: Array[A], n: Int): Array[A] = {
|
|
373
|
+
val len = min(max(0, n), arr.size)
|
|
374
|
+
val result = allocate[A](len)
|
|
375
|
+
each(0, len) { i =>
|
|
376
|
+
result.unsafeSet(i, arr.unsafeGet(i))
|
|
377
|
+
}
|
|
378
|
+
result
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// Drop first n elements.
|
|
382
|
+
/// Returns a new array.
|
|
383
|
+
///
|
|
384
|
+
/// O(N)
|
|
385
|
+
def drop[A](arr: Array[A], n: Int): Array[A] = {
|
|
386
|
+
val start = min(max(0, n), arr.size)
|
|
387
|
+
val len = arr.size - start
|
|
388
|
+
val result = allocate[A](len)
|
|
389
|
+
each(0, len) { i =>
|
|
390
|
+
result.unsafeSet(i, arr.unsafeGet(i + start))
|
|
391
|
+
}
|
|
392
|
+
result
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/// Return a slice from start (inclusive) to end (exclusive).
|
|
396
|
+
/// Returns a new array.
|
|
397
|
+
///
|
|
398
|
+
/// O(N)
|
|
399
|
+
def sliced[A](arr: Array[A], start: Int, end: Int): Array[A] = {
|
|
400
|
+
val validStart = min(max(0, start), arr.size)
|
|
401
|
+
val validEnd = min(max(validStart, end), arr.size)
|
|
402
|
+
val len = validEnd - validStart
|
|
403
|
+
val result = allocate[A](len)
|
|
404
|
+
each(0, len) { i =>
|
|
405
|
+
result.unsafeSet(i, arr.unsafeGet(i + validStart))
|
|
406
|
+
}
|
|
407
|
+
result
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/// Zip two arrays into an array of pairs.
|
|
411
|
+
/// Length is minimum of input lengths.
|
|
412
|
+
///
|
|
413
|
+
/// O(min(N, M))
|
|
414
|
+
def zipped[A, B](this: Array[A], other: Array[B]): Array[(A, B)] = {
|
|
415
|
+
val len = min(this.size, other.size)
|
|
416
|
+
val result = allocate[(A, B)](len)
|
|
417
|
+
each(0, len) { i =>
|
|
418
|
+
result.unsafeSet(i, (this.unsafeGet(i), other.unsafeGet(i)))
|
|
419
|
+
}
|
|
420
|
+
result
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/// Combine two arrays using given function.
|
|
424
|
+
/// Length is minimum of input lengths.
|
|
425
|
+
///
|
|
426
|
+
/// O(min(N, M))
|
|
427
|
+
def zippedWith[A, B, C](this: Array[A], other: Array[B]) { f: (A, B) => C }: Array[C] = {
|
|
428
|
+
val len = min(this.size, other.size)
|
|
429
|
+
val result = allocate[C](len)
|
|
430
|
+
each(0, len) { i =>
|
|
431
|
+
result.unsafeSet(i, f(this.unsafeGet(i), other.unsafeGet(i)))
|
|
432
|
+
}
|
|
433
|
+
result
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/// Produce a pair of arrays from an array of pairs.
|
|
437
|
+
/// Allocates two new arrays as a result.
|
|
438
|
+
///
|
|
439
|
+
/// O(N)
|
|
440
|
+
def unzipped[A, B](arr: Array[(A, B)]): (Array[A], Array[B]) = {
|
|
441
|
+
val arr1 = allocate(arr.size)
|
|
442
|
+
val arr2 = allocate(arr.size)
|
|
443
|
+
arr.foreachIndex { (idx, tpl) =>
|
|
444
|
+
val (x, y) = tpl
|
|
445
|
+
arr1.unsafeSet(idx, x)
|
|
446
|
+
arr2.unsafeSet(idx, y)
|
|
447
|
+
}
|
|
448
|
+
(arr1, arr2)
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/// Partition a given array into two arrays.
|
|
452
|
+
/// The left array contains the elements that satsify the predicate,
|
|
453
|
+
/// the right array contains the elements that do not.
|
|
454
|
+
///
|
|
455
|
+
/// O(N)
|
|
456
|
+
def partioned[A](arr: Array[A]) { pred: A => Bool }: (Array[A], Array[A]) = {
|
|
457
|
+
val tcases = arr.copy()
|
|
458
|
+
val fcases = arr.copy()
|
|
459
|
+
var tidx = 0
|
|
460
|
+
var fidx = 0
|
|
461
|
+
arr.foreach { x =>
|
|
462
|
+
if (pred(x)) {
|
|
463
|
+
tcases.unsafeSet(tidx, x)
|
|
464
|
+
tidx = tidx + 1
|
|
465
|
+
} else {
|
|
466
|
+
fcases.unsafeSet(fidx, x)
|
|
467
|
+
fidx = fidx + 1
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
(tcases.resize(tidx), fcases.resize(fidx))
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/// Get the _first_ index of the last occurance of `elem`, if there is any.
|
|
474
|
+
///
|
|
475
|
+
/// O(N)
|
|
476
|
+
def indexOf[A](arr: Array[A], toFind: A) { eq: (A, A) => Bool }: Option[Int] = {
|
|
477
|
+
var found = None[Int]()
|
|
478
|
+
arr.foreachIndex { (idx, elem) {label} =>
|
|
479
|
+
if (eq(elem, toFind) && found.isEmpty) {
|
|
480
|
+
found = Some(idx)
|
|
481
|
+
label.break()
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
found
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/// Get the _last_ index of the last occurance of `elem`, if there is any.
|
|
488
|
+
///
|
|
489
|
+
/// O(N)
|
|
490
|
+
def lastIndexOf[A](arr: Array[A], toFind: A) { eq: (A, A) => Bool }: Option[Int] = {
|
|
491
|
+
var lastFound = None[Int]()
|
|
492
|
+
arr.foreachIndex { (idx, elem) =>
|
|
493
|
+
if (eq(elem, toFind)) {
|
|
494
|
+
lastFound = Some(idx)
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
lastFound
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/// Perform binary search to find the index of a given element.
|
|
501
|
+
///
|
|
502
|
+
/// O(log N)
|
|
503
|
+
def binarySearch[A](arr: Array[A], toFind: A) { ord: (A, A) => Ordering }: Option[Int] = {
|
|
504
|
+
def binarySearch(lowerIdx: Int, upperIdx: Int): Option[Int] = {
|
|
505
|
+
if (lowerIdx > upperIdx) None()
|
|
506
|
+
else {
|
|
507
|
+
val mid = lowerIdx + (upperIdx - lowerIdx) / 2
|
|
508
|
+
val current = arr.unsafeGet(mid)
|
|
509
|
+
ord(current, toFind) match {
|
|
510
|
+
case Less() => binarySearch(mid + 1, upperIdx)
|
|
511
|
+
case Greater() => binarySearch(lowerIdx, mid - 1)
|
|
512
|
+
case Equal() => Some(mid)
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
binarySearch(0, arr.size - 1)
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
/// Sort an array in-place using provided comparison function.
|
|
520
|
+
/// Note: sort is unstable since it uses QuickSort (unlike list::sortBy)
|
|
521
|
+
///
|
|
522
|
+
/// O(N log N) average case
|
|
523
|
+
def sort[A](arr: Array[A]) { ord: (A, A) => Ordering }: Unit = {
|
|
524
|
+
def partition(low: Int, high: Int): Int = {
|
|
525
|
+
val pivot = arr.unsafeGet(high)
|
|
526
|
+
var i = low - 1
|
|
527
|
+
|
|
528
|
+
each(low, high) { j =>
|
|
529
|
+
ord(arr.unsafeGet(j), pivot) match {
|
|
530
|
+
case Less() =>
|
|
531
|
+
i = i + 1
|
|
532
|
+
unsafeSwap(arr, i, j)
|
|
533
|
+
case _ => ()
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
unsafeSwap(arr, i + 1, high)
|
|
537
|
+
i + 1
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
def quickSort(low: Int, high: Int): Unit = {
|
|
541
|
+
if (low < high) {
|
|
542
|
+
val par = partition(low, high)
|
|
543
|
+
quickSort(low, par - 1)
|
|
544
|
+
quickSort(par + 1, high)
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
quickSort(0, arr.size - 1)
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/// Sort an array using provided comparison function.
|
|
552
|
+
/// A newly allocated sorted array is returned as result, i.e., the sorting is not in-place.
|
|
553
|
+
/// Note: sort is unstable since it uses QuickSort (unlike list::sortBy)
|
|
554
|
+
///
|
|
555
|
+
/// O(N log N) average case
|
|
556
|
+
def sorted[A](arr: Array[A]) { ord: (A, A) => Ordering }: Array[A] = {
|
|
557
|
+
val res = arr.copy()
|
|
558
|
+
res.sort { ord }
|
|
559
|
+
res
|
|
560
|
+
}
|
|
561
|
+
|
|
188
562
|
// Show Instances
|
|
189
563
|
// --------------
|
|
190
564
|
|
|
@@ -30,6 +30,17 @@ effect stop(): Nothing
|
|
|
30
30
|
def for[A] { stream: () => Unit / emit[A] } { action: A => Unit }: Unit =
|
|
31
31
|
returning::for[A, Unit]{stream}{action}
|
|
32
32
|
|
|
33
|
+
/// Runs the stream as a message queue,
|
|
34
|
+
/// handling each of its elements that can produce new elements ("messages"),
|
|
35
|
+
/// until a fixed point is reached.
|
|
36
|
+
def fix[T] { one: T => Unit / emit[T] } { stream: => Unit / emit[T] }: Unit =
|
|
37
|
+
try {
|
|
38
|
+
stream()
|
|
39
|
+
} with emit[T] { value =>
|
|
40
|
+
fix[T] {one} { one(value) }
|
|
41
|
+
resume(())
|
|
42
|
+
}
|
|
43
|
+
|
|
33
44
|
/// Turns a `list` into a producer of a push stream
|
|
34
45
|
/// by emitting each contained value left-to-right.
|
|
35
46
|
def each[A](list: List[A]): Unit / emit[A] =
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|