Search code examples
scalascala-2.8default-valuenamed-parameters

Is it possible for an optional argument value to depend on another argument in Scala


Does anyone know if something like this is possible in Scala:

case class Thing(property:String)

def f(thing:Thing, prop:String = thing.property) = println(prop)

The above code doesn't compile; giving the error error: not found: value thing at thing.property

The following shows the expected behaviour:

f(Thing("abc"), "123") // prints "123"
f(Thing("abc"))        // prints "abc"

I realise I could make the prop argument an Option[String] and do the check in the function definition, but I was wondering if there was a way around it with the new named/default argument support in 2.8.0.


Solution

  • Yes, it's possible in Scala 2.8. Here's a quote from the "Named and Default Arguments in Scala 2.8" design document:

    Since the scope of a parameter extends over all subsequent parameter lists (and the method body), default expressions can depend on parameters of preceding parameter lists (but not on other parameters in the same parameter list). Note that when using a default value which depends on earlier parameters, the actual arguments are used, not the default arguments.

    def f(a: Int = 0)(b: Int = a + 1) = b // OK
    

    And another example:

    def f[T](a: Int = 1)(b: T = a + 1)(c: T = b)
    // generates:
    // def f$default$1[T]: Int = 1
    // def f$default$2[T](a: Int): Int = a + 1
    // def f$default$3[T](a: Int)(b: T): T = b
    

    According to this, your code may look as follows:

    scala> case class Thing(property:String)
    defined class Thing
    
    scala> def f(thing:Thing)(prop:String = thing.property) = println(prop)
    f: (thing: Thing)(prop: String)Unit
    
    scala> f(Thing("abc"))("123")
    123
    
    scala> f(Thing("abc"))()
    abc