scalaimplicit-conversioncallbyname

Conversion to tuple with by-name parameter


I would like to create a function with the following signature:

def myFunction[T](functionWithName: (String, => T)): T 

so that I can call it, e.g., like this: val x = myFunction("abc" -> 4 * 3). Tuple doesn't accept by-name parameter, however, so the signature above is invalid.

Inspired by this answer, I tried the following implicit conversion:

implicit class ByName[T](getValue: => T) extends Proxy {
  def apply(): T = getValue
  def self = apply()
}

def myFunction[T](functionWithName: (String, ByName[T])): T = {
  // do something
  functionWithName._2()
}

The implicit doesn't work in this case, however (unlike in the linked answer).


Solution

  • I have two proposals to implement this:

    and have a custom implicit method somewhere, like -> for Tuple2 (see ArrowAssoc in Predef):

      implicit final class ArrAssoc[A](private val self: A) extends AnyVal {
        @inline def -->[B](y: => B): MyTuple[A, B] = {
          new MyTuple(self, y)
        }
      }
    

    Then you could say this:

      val t = 1 --> { println("blah"); 5 }
      //t._2
      //t.toTuple
    

    The b parameter should not be evaluated until you call t._2 Or even make toTuple imlicit conversion, so when Tuple2 is espected you can pass a MyTuple...