@@ -280,6 +280,51 @@ extension Signal.Event {
280280 }
281281 }
282282
283+ internal static func attemptMap< U> ( _ transform: @escaping ( Value ) -> Result < U , Error > ) -> Transformation < U , Error > {
284+ return { action in
285+ return { event in
286+ switch event {
287+ case let . value( value) :
288+ switch transform ( value) {
289+ case let . success( value) :
290+ action ( . value( value) )
291+ case let . failure( error) :
292+ action ( . failed( error) )
293+ }
294+ case let . failed( error) :
295+ action ( . failed( error) )
296+ case . completed:
297+ action ( . completed)
298+ case . interrupted:
299+ action ( . interrupted)
300+ }
301+ }
302+ }
303+ }
304+
305+ internal static func attempt( _ action: @escaping ( Value ) -> Result < ( ) , Error > ) -> Transformation < Value , Error > {
306+ return attemptMap { value -> Result < Value , Error > in
307+ return action ( value) . map { _ in value }
308+ }
309+ }
310+ }
311+
312+ extension Signal . Event where Error == AnyError {
313+ internal static func attempt( _ action: @escaping ( Value ) throws -> Void ) -> Transformation < Value , AnyError > {
314+ return attemptMap { value in
315+ try action ( value)
316+ return value
317+ }
318+ }
319+
320+ internal static func attemptMap< U> ( _ transform: @escaping ( Value ) throws -> U ) -> Transformation < U , AnyError > {
321+ return attemptMap { value in
322+ ReactiveSwift . materialize { try transform ( value) }
323+ }
324+ }
325+ }
326+
327+ extension Signal . Event {
283328 internal static func take( first count: Int ) -> Transformation < Value , Error > {
284329 assert ( count >= 1 )
285330
@@ -304,6 +349,46 @@ extension Signal.Event {
304349 }
305350 }
306351
352+ internal static func take( last count: Int ) -> Transformation < Value , Error > {
353+ return { action in
354+ var buffer : [ Value ] = [ ]
355+ buffer. reserveCapacity ( count)
356+
357+ return { event in
358+ switch event {
359+ case let . value( value) :
360+ // To avoid exceeding the reserved capacity of the buffer,
361+ // we remove then add. Remove elements until we have room to
362+ // add one more.
363+ while ( buffer. count + 1 ) > count {
364+ buffer. remove ( at: 0 )
365+ }
366+
367+ buffer. append ( value)
368+ case let . failed( error) :
369+ action ( . failed( error) )
370+ case . completed:
371+ buffer. forEach { action ( . value( $0) ) }
372+ action ( . completed)
373+ case . interrupted:
374+ action ( . interrupted)
375+ }
376+ }
377+ }
378+ }
379+
380+ internal static func take( while shouldContinue: @escaping ( Value ) -> Bool ) -> Transformation < Value , Error > {
381+ return { action in
382+ return { event in
383+ if let value = event. value, !shouldContinue( value) {
384+ action ( . completed)
385+ } else {
386+ action ( event)
387+ }
388+ }
389+ }
390+ }
391+
307392 internal static func skip( first count: Int ) -> Transformation < Value , Error > {
308393 precondition ( count > 0 )
309394
@@ -319,6 +404,25 @@ extension Signal.Event {
319404 }
320405 }
321406 }
407+
408+ internal static func skip( while shouldContinue: @escaping ( Value ) -> Bool ) -> Transformation < Value , Error > {
409+ return { action in
410+ var isSkipping = true
411+
412+ return { event in
413+ switch event {
414+ case let . value( value) :
415+ isSkipping = isSkipping && shouldContinue ( value)
416+ if !isSkipping {
417+ fallthrough
418+ }
419+
420+ case . failed, . completed, . interrupted:
421+ action ( event)
422+ }
423+ }
424+ }
425+ }
322426}
323427
324428extension Signal . Event where Value: EventProtocol {
@@ -443,6 +547,112 @@ extension Signal.Event {
443547 }
444548 }
445549
550+ /// Implementation detail of `combinePrevious`. A default argument of a `nil` initial
551+ /// is deliberately avoided, since in the case of `Value` being an optional, the
552+ /// `nil` literal would be materialized as `Optional<Value>.none` instead of `Value`,
553+ /// thus changing the semantic.
554+ internal static func combinePrevious( initial: Value ? ) -> Transformation < ( Value , Value ) , Error > {
555+ return { action in
556+ var previous = initial
557+
558+ return { event in
559+ switch event {
560+ case let . value( value) :
561+ if let previous = previous {
562+ action ( . value( ( previous, value) ) )
563+ }
564+ previous = value
565+ case . completed:
566+ action ( . completed)
567+ case let . failed( error) :
568+ action ( . failed( error) )
569+ case . interrupted:
570+ action ( . interrupted)
571+ }
572+ }
573+ }
574+ }
575+
576+ internal static func skipRepeats( _ isEquivalent: @escaping ( Value , Value ) -> Bool ) -> Transformation < Value , Error > {
577+ return { action in
578+ var previous : Value ?
579+
580+ return { event in
581+ switch event {
582+ case let . value( value) :
583+ if let previous = previous, isEquivalent ( previous, value) {
584+ return
585+ }
586+ previous = value
587+ fallthrough
588+ case . completed, . interrupted, . failed:
589+ action ( event)
590+ }
591+ }
592+ }
593+ }
594+
595+ internal static func uniqueValues< Identity: Hashable > ( _ transform: @escaping ( Value ) -> Identity ) -> Transformation < Value , Error > {
596+ return { action in
597+ var seenValues : Set < Identity > = [ ]
598+
599+ return { event in
600+ switch event {
601+ case let . value( value) :
602+ let identity = transform ( value)
603+ let ( inserted, _) = seenValues. insert ( identity)
604+ if inserted {
605+ fallthrough
606+ }
607+
608+ case . failed, . completed, . interrupted:
609+ action ( event)
610+ }
611+ }
612+ }
613+ }
614+
615+ internal static func scan< U> ( into initialResult: U , _ nextPartialResult: @escaping ( inout U , Value ) -> Void ) -> Transformation < U , Error > {
616+ return { action in
617+ var accumulator = initialResult
618+
619+ return { event in
620+ action ( event. map { value in
621+ nextPartialResult ( & accumulator, value)
622+ return accumulator
623+ } )
624+ }
625+ }
626+ }
627+
628+ internal static func scan< U> ( _ initialResult: U , _ nextPartialResult: @escaping ( U , Value ) -> U ) -> Transformation < U , Error > {
629+ return scan ( into: initialResult) { $0 = nextPartialResult ( $0, $1) }
630+ }
631+
632+ internal static func reduce< U> ( into initialResult: U , _ nextPartialResult: @escaping ( inout U , Value ) -> Void ) -> Transformation < U , Error > {
633+ return { action in
634+ var accumulator = initialResult
635+
636+ return { event in
637+ switch event {
638+ case let . value( value) :
639+ nextPartialResult ( & accumulator, value)
640+ case . completed:
641+ action ( . value( accumulator) )
642+ action ( . completed)
643+ case . interrupted:
644+ action ( . interrupted)
645+ case let . failed( error) :
646+ action ( . failed( error) )
647+ }
648+ }
649+ }
650+ }
651+
652+ internal static func reduce< U> ( _ initialResult: U , _ nextPartialResult: @escaping ( U , Value ) -> U ) -> Transformation < U , Error > {
653+ return reduce ( into: initialResult) { $0 = nextPartialResult ( $0, $1) }
654+ }
655+
446656 internal static func observe( on scheduler: Scheduler ) -> Transformation < Value , Error > {
447657 return { action in
448658 return { event in
@@ -474,3 +684,41 @@ extension Signal.Event {
474684 }
475685 }
476686}
687+
688+ extension Signal . Event where Error == NoError {
689+ internal static func promoteError< F> ( _: F . Type ) -> Transformation < Value , F > {
690+ return { action in
691+ return { event in
692+ switch event {
693+ case let . value( value) :
694+ action ( . value( value) )
695+ case . failed:
696+ fatalError ( " NoError is impossible to construct " )
697+ case . completed:
698+ action ( . completed)
699+ case . interrupted:
700+ action ( . interrupted)
701+ }
702+ }
703+ }
704+ }
705+ }
706+
707+ extension Signal . Event where Value == Never {
708+ internal static func promoteValue< U> ( _: U . Type ) -> Transformation < U , Error > {
709+ return { action in
710+ return { event in
711+ switch event {
712+ case . value:
713+ fatalError ( " Never is impossible to construct " )
714+ case let . failed( error) :
715+ action ( . failed( error) )
716+ case . completed:
717+ action ( . completed)
718+ case . interrupted:
719+ action ( . interrupted)
720+ }
721+ }
722+ }
723+ }
724+ }
0 commit comments