scalathisinfix-notationmethod-invocation

Scala: How can I create a function that allows me to use dot notation when calling it?


I have been confused about this for a while, even despite reading the Scala Style Guide - Method Invocation several times.

I want to be able to call this method

def foldRVL[A,B](l: List[A], z: B)(f: (A, B) => B) = //"Right-Via-Left"
  l.reverse.foldLeft(z)((a, b) => f(b, a))

using dot notation like this List(1,2,3).foldRVL(0)(_ + _).

And not like this: foldRVL(List(1,2,3), 0)(_ + _).

Also, sometimes I've seen code that shows methods that actually either takes zero parameters in their signature, or one fewer parameters than I would expect them to take, and still properly take a parameter using dot-notation. How does this work? I ask this because those methods work with dot-notation, so maybe if I wrote something like that I could solve my problem.


Solution

  • For the first part of your question, you probably need to look at implicit classes:

      implicit class RichRVLList[A](l:List[A]) {
        def foldRVL[B](z: B)(f: (A, B) => B) = //"Right-Via-Left"
          l.reverse.foldLeft(z)((a, b) => f(b, a))
      }
    
      List(1,2,3).foldRVL(1)(_ + _)  // output: res0: Int = 7
    

    You can "enrich" existent class using implicit wrapper to "add" new methods.

    As for the second part, probably you want implicit parameters. Implicit parameters are deduced from the current scope by type. There are some predefined implicit values, such as Numerics, that were used in the example below:

      def product[T](els:TraversableOnce[T])(implicit num:Numeric[T]) = {
        els.fold(num.one)((x1, x2) => num.times(x1, x2))
      }      
    
      product(List(1, 2, 3)) // res1: Int = 6
      product(List(1, 2.5, 3)) //res2: Double = 7.5