可选参数值是否可能依赖于Scala中的另一个参数

时间:2010-06-22 06:25:35

标签: scala scala-2.8 default-value named-parameters

有人知道在Scala中是否可以使用这样的东西:

case class Thing(property:String)

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

以上代码无法编译;在error: not found: value thing

处提供错误thing.property

以下显示了预期的行为:

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

我意识到我可以将prop参数设为Option[String]并在函数定义中进行检查,但我想知道是否有一种方法可以使用新的命名/默认参数支持2.8.0。

3 个答案:

答案 0 :(得分:20)

是的,它可以在Scala 2.8中使用。以下是"Named and Default Arguments in Scala 2.8"设计文档的引用:

  

由于参数的范围扩展   在所有后续参数列表中   (和方法体),默认   表达式可以取决于参数   前面的参数列表(但不是   在其他参数上   参数列表)。请注意,使用时   一个默认值取决于   较早的参数,实际   使用参数,而不是默认值   参数。

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

另一个例子:

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

根据这一点,您的代码可能如下所示:

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

答案 1 :(得分:1)

另一个简单的解决方案就是重载方法:

case class Thing (property: String)

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

def f(thing: Thing) = f(thing, thing.property)

答案 2 :(得分:0)

这正是Option的用途。您可以在方法调用之前或方法getOrElse内使用f方法。

scala> val abc = Some("abc")
abc: Some[java.lang.String] = Some(abc)

scala> val none: Option[String] = None
none: Option[String] = None

scala> println(abc getOrElse "123")
abc

scala> println(none getOrElse "123")
123

scala> def f(o: Option[String]) = println(o getOrElse "123")
f: (o: Option[String])Unit

scala> f(abc)
abc

scala> f(none)
123

哦,这是你可以通过默认参数做的事情:

scala> case class Thing(property: String = "123")
defined class Thing

scala> def f(t: Thing) = println(t.property)
f: (t: Thing)Unit

scala> f(Thing("abc"))
abc

scala> f(Thing())
123

通过简单的重载可以实现预期的行为。我需要将方法放在object中,因为看起来REPL不允许直接重载函数声明:

scala> object O {
         def overloaded(t:Thing) = println(t.property)
         def overloaded(t:Thing,s:String) = println(s)
       }
defined module O

scala> O.overloaded(Thing("abc"), "123")
123

scala> O.overloaded(Thing("abc"))
abc