Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stateful function pipeline

The code explains itself.

val s = Seq(1,1,1)
val res: Seq[Int] = s.map(...)
                     .check(count how many 1s, if > 2 throw Exception)
                     .map(...)

I am searching the simple solution to this check function .

  • I can use map and closure to count and throw, but I want pure function.
  • I can use filter and size or reduce, but it return a value and not resumable with following maps.

How do I make a pure and stateful checking-pipe to the pipeline ?

like image 218
WeiChing 林煒清 Avatar asked Dec 24 '22 05:12

WeiChing 林煒清


1 Answers

Throwing an exception is arguably not pure. If you instead were using a monadic form of error handling, you'd do something like this:

Option(s.map(foo)).
  filter(m => m.count(_ == 1) < 2).
  map{ s =>
    s.map(bar)
     .filter(baz)
     ...
  }

As it is, if you want to compose it within the pipeline, and you don't want to add extra parentheses as is necessary with match, you can use the commonly-enriched tap method:

implicit class TapAnything[A](private val a: A) extends AnyVal {
  def tap[U](f: A => U): A = { f(a); a }
}

Now you can

s.map(...)
 .tap(self => if (self.count(_ == 1) > 1) throw new Exception)
 .map(...)
 ...

(note: the private val + extends AnyVal stuff is just to indicate to the compiler that it's supposed to try to avoid creating an extra object to make the call).

like image 64
Rex Kerr Avatar answered Jan 11 '23 23:01

Rex Kerr