Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there something like Java Stream's "peek" operation in Scala?

In Java you can call peek(x -> println(x)) on a Stream and it will perform the action for each element and return the original stream, unlike foreach which is Unit. Is there something similar in Scala, ideally something which works on all Monady types, allowing you to "pass through" the original Monad while performing a side effect action? (Logging, e.g.)

It is of course easily implemented:

def tap[A, U](a: A)(action: (A) => U): A = {
  action(a)
  a
}

but I'm hoping for something a bit more elegant or idiomatic.

like image 738
Daniel Skogquist Åborg Avatar asked Jul 08 '16 00:07

Daniel Skogquist Åborg


People also ask

Why would you choose to use a peek operation instead of a foreach operation on a stream?

peek can get the smallest item directly compared with stream. foreach().

What is peek in Java?

peek() method in Java is used to retrieve or fetch the first element of the Stack or the element present at the top of the Stack. The element retrieved does not get deleted or removed from the Stack.

How do you peek in the stream?

Java Stream peek() Java Stream peek() method returns a new Stream consisting of all the elements from the original Stream after applying a given Consumer action. Note that the peek() method is an intermediate Stream operation so, to process the Stream elements through peek() , we must use a terminal operation.

What is the use of PEEK method in Java 8?

This method exists mainly to support debugging, where you want to see the elements as they flow past a certain point in a pipeline. Since Java 9, if the number of elements is known in advance and unchanged in the stream, the . peek () statement will not be executed due to performance optimization.


1 Answers

One way to solve this is using implicits:

class Tappable[A](a: A) {
  def tap[U](action: (A) => U): A = {
    action(a)
    a
  }
}

implicit def any2Tappable[A](a: A): Tappable[A] = new Tappable[A](a)

Which can then be used natively:

connection.tap(_.connect()) match {
  case c if c.getResponseCode == 304 => None
  ...

Any other answers?

like image 110
Daniel Skogquist Åborg Avatar answered Sep 20 '22 19:09

Daniel Skogquist Åborg