Search code examples
scalachaining

Why my function is not being print after map?


I am trying to figure it out how to chain functions in Scala.

I have the following code:

def multiPrint(list: List[Int], number: Int): Unit = {
    list
      .map(x => x * number)
      .andThen(x => print(x))
  }

but this does not print a result as I expected. It prints "()" like if it was an empty list.

Then I tried like:

  def multiPrint(list: List[Int], number: Int): Unit = {
      list
        .toStream
        .map(x => x * number)
        .print
  }

This works, but toStream is deprecated. Anyway, I would like to do it with andThen. Any idea?


Solution

  • As the other answer mentioned, you are looking for foreach ... But I thought, I'd explain what andThen actually does here, which is kinda interesting.

    So, if you look at a signature of andThen:

    trait PartialFunction[A, B] extends (A => B) { 
    ...
       def andThen[C](k: B => C): PartialFunction[A, C]
    ...
    }
    

    it should become clear that it doesn't do what you think it does. It is actually a partial function combinator: given two partial functions, one f1: A => B, and and another f2: B => C, it creates and returns a third function, A => C, that first calls f1 with the given argument, and then invokes f2 with the result of execution of f1.

    So,

     list
          .map(_ * number)
          .andThen(print(_))
    

    Does not really print anything at all (I am guessing your saw () in the output when because you tried to print out the result of multiPrint, which is a Unit.

    But, if you try something like this:

    val foo = Seq(1,2,3).map(_ * 2).antThen(print(_))
    foo(1)
    

    You may get mildly surprised because this prints 4. foo(2) will print 6. and foo(3)? It throws an IndexOutOfBoundException which may give you a hint on what's really going on.

    Seq[Int] in scala is actually a PartialFunction[Int, Int], that returns the Seq element at the index given by the argument. Your .andThen combined that function with print, and created a new function foo, that accesses the element of the result of .map at the given index, andThen prints the result.

    So, foo(1) for instance, gets the element at index 1, which is 2*2, and prints 4. And foo(3) fails, because index 3 does not exist.

    A note just for the sake of completness:

    As the other answer mentions, to print out elements of seq one-by-one, just use foreach: Seq(1,2,3).map(_ *2).foreach(println)