@@ -5,7 +5,6 @@ import ox.*
5
5
import java .util .concurrent .{CountDownLatch , Semaphore }
6
6
import scala .collection .{IterableOnce , mutable }
7
7
import scala .concurrent .duration .FiniteDuration
8
- import scala .util .Try
9
8
10
9
trait SourceOps [+ T ] { this : Source [T ] =>
11
10
// view ops (lazy)
@@ -46,7 +45,7 @@ trait SourceOps[+T] { this: Source[T] =>
46
45
* import ox.*
47
46
* import ox.channels.Source
48
47
*
49
- * scoped {
48
+ * supervised {
50
49
* Source.empty[String].intersperse(", ").toList // List()
51
50
* Source.fromValues("foo").intersperse(", ").toList // List(foo)
52
51
* Source.fromValues("foo", "bar").intersperse(", ").toList // List(foo, ", ", bar)
@@ -71,7 +70,7 @@ trait SourceOps[+T] { this: Source[T] =>
71
70
* import ox.*
72
71
* import ox.channels.Source
73
72
*
74
- * scoped {
73
+ * supervised {
75
74
* Source.empty[String].intersperse("[", ", ", "]").toList // List([, ])
76
75
* Source.fromValues("foo").intersperse("[", ", ", "]").toList // List([, foo, ])
77
76
* Source.fromValues("foo", "bar").intersperse("[", ", ", "]").toList // List([, foo, ", ", bar, ])
@@ -210,7 +209,7 @@ trait SourceOps[+T] { this: Source[T] =>
210
209
* import ox.*
211
210
* import ox.channels.Source
212
211
*
213
- * scoped {
212
+ * supervised {
214
213
* Source.empty[Int].takeWhile(_ > 3).toList // List()
215
214
* Source.fromValues(1, 2, 3).takeWhile(_ < 3).toList // List(1, 2)
216
215
* Source.fromValues(3, 2, 1).takeWhile(_ < 3).toList // List()
@@ -228,7 +227,7 @@ trait SourceOps[+T] { this: Source[T] =>
228
227
* import ox.*
229
228
* import ox.channels.Source
230
229
*
231
- * scoped {
230
+ * supervised {
232
231
* Source.empty[Int].drop(1).toList // List()
233
232
* Source.fromValues(1, 2, 3).drop(1).toList // List(2 ,3)
234
233
* Source.fromValues(1).drop(2).toList // List()
@@ -303,7 +302,7 @@ trait SourceOps[+T] { this: Source[T] =>
303
302
* import ox.*
304
303
* import ox.channels.Source
305
304
*
306
- * scoped {
305
+ * supervised {
307
306
* Source.empty[Int].zipAll(Source.empty[String], -1, "foo").toList // List()
308
307
* Source.empty[Int].zipAll(Source.fromValues("a"), -1, "foo").toList // List((-1, "a"))
309
308
* Source.fromValues(1).zipAll(Source.empty[String], -1, "foo").toList // List((1, "foo"))
@@ -355,7 +354,7 @@ trait SourceOps[+T] { this: Source[T] =>
355
354
* import ox.*
356
355
* import ox.channels.Source
357
356
*
358
- * scoped {
357
+ * supervised {
359
358
* val s1 = Source.fromValues(1, 2, 3, 4, 5, 6, 7)
360
359
* val s2 = Source.fromValues(10, 20, 30, 40)
361
360
* s1.interleave(s2, segmentSize = 2).toList
@@ -433,7 +432,7 @@ trait SourceOps[+T] { this: Source[T] =>
433
432
* import ox.*
434
433
* import ox.channels.Source
435
434
*
436
- * scoped {
435
+ * supervised {
437
436
* val s = Source.fromValues(1, 2, 3, 4, 5)
438
437
* s.mapStateful(() => 0)((sum, element) => (sum + element, sum), Some.apply)
439
438
* }
@@ -476,7 +475,7 @@ trait SourceOps[+T] { this: Source[T] =>
476
475
* import ox.*
477
476
* import ox.channels.Source
478
477
*
479
- * scoped {
478
+ * supervised {
480
479
* val s = Source.fromValues(1, 2, 2, 3, 2, 4, 3, 1, 5)
481
480
* // deduplicate the values
482
481
* s.mapStatefulConcat(() => Set.empty[Int])((s, e) => (s + e, Option.unless(s.contains(e))(e)))
@@ -515,56 +514,58 @@ trait SourceOps[+T] { this: Source[T] =>
515
514
}
516
515
c
517
516
518
- /** Returns the first element from this source wrapped in ` Some` or ` None` when the source is empty or fails during the receive operation.
519
- * Note that `headOption` is not an idempotent operation on source as it receives elements from it.
517
+ /** Returns the first element from this source wrapped in [[ Some ]] or [[ None ]] when this source is empty. Note that `headOption` is not an
518
+ * idempotent operation on source as it receives elements from it.
520
519
*
521
520
* @return
522
- * A `Some(first element)` if source is not empty or None` otherwise.
521
+ * A `Some(first element)` if source is not empty or `None` otherwise.
522
+ * @throws ChannelClosedException.Error
523
+ * When receiving an element from this source fails.
523
524
* @example
524
525
* {{{
525
526
* import ox.*
526
527
* import ox.channels.Source
527
528
*
528
- * scoped {
529
+ * supervised {
529
530
* Source.empty[Int].headOption() // None
530
531
* val s = Source.fromValues(1, 2)
531
532
* s.headOption() // Some(1)
532
533
* s.headOption() // Some(2)
533
534
* }
534
535
* }}}
535
536
*/
536
- def headOption (): Option [T ] = Try (head()).toOption
537
+ def headOption (): Option [T ] =
538
+ supervised {
539
+ receive() match
540
+ case ChannelClosed .Done => None
541
+ case e : ChannelClosed .Error => throw e.toThrowable
542
+ case t : T @ unchecked => Some (t)
543
+ }
537
544
538
- /** Returns the first element from this source or throws ` NoSuchElementException` when the source is empty or `receive()` operation fails
539
- * without error. In case when the `receive()` operation fails with exception that exception is re- thrown. Note that `headOption ` is not
540
- * an idempotent operation on source as it receives elements from it.
545
+ /** Returns the first element from this source or throws [[ NoSuchElementException ]] when this source is empty. In case when receiving an
546
+ * element fails with exception then [[ ChannelClosedException.Error ]] is thrown. Note that `head ` is not an idempotent operation on
547
+ * source as it receives elements from it.
541
548
*
542
549
* @return
543
550
* A first element if source is not empty or throws otherwise.
544
551
* @throws NoSuchElementException
545
- * When source is empty or `receive()` failed without error .
546
- * @throws exception
547
- * When `receive()` failed with exception then this exception is re-thrown .
552
+ * When this source is empty.
553
+ * @throws ChannelClosedException.Error
554
+ * When receiving an element from this source fails .
548
555
* @example
549
556
* {{{
550
557
* import ox.*
551
558
* import ox.channels.Source
552
559
*
553
- * scoped {
554
- * Source.empty[Int].head() // throws NoSuchElementException("cannot obtain head from an empty source")
560
+ * supervised {
561
+ * Source.empty[Int].head() // throws NoSuchElementException("cannot obtain head element from an empty source")
555
562
* val s = Source.fromValues(1, 2)
556
563
* s.head() // 1
557
564
* s.head() // 2
558
565
* }
559
566
* }}}
560
567
*/
561
- def head (): T =
562
- supervised {
563
- receive() match
564
- case ChannelClosed .Done => throw new NoSuchElementException (" cannot obtain head from an empty source" )
565
- case ChannelClosed .Error (r) => throw r.getOrElse(new NoSuchElementException (" getting head failed" ))
566
- case t : T @ unchecked => t
567
- }
568
+ def head (): T = headOption().getOrElse(throw new NoSuchElementException (" cannot obtain head element from an empty source" ))
568
569
569
570
/** Sends elements to the returned channel limiting the throughput to specific number of elements (evenly spaced) per time unit. Note that
570
571
* the element's `receive()` time is included in the resulting throughput. For instance having `throttle(1, 1.second)` and `receive()`
@@ -645,7 +646,7 @@ trait SourceOps[+T] { this: Source[T] =>
645
646
* @return
646
647
* A last element if source is not empty or throws otherwise.
647
648
* @throws NoSuchElementException
648
- * When source is empty.
649
+ * When this source is empty.
649
650
* @throws ChannelClosedException.Error
650
651
* When receiving an element from this source fails.
651
652
* @example
@@ -822,7 +823,7 @@ trait SourceCompanionOps:
822
823
* import ox.*
823
824
* import ox.channels.Source
824
825
*
825
- * scoped {
826
+ * supervised {
826
827
* val s1 = Source.fromValues(1, 2, 3, 4, 5, 6, 7, 8)
827
828
* val s2 = Source.fromValues(10, 20, 30)
828
829
* val s3 = Source.fromValues(100, 200, 300, 400, 500)
0 commit comments