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

Posted

技术标签:

【中文标题】可选参数值是不是可能依赖于 Scala 中的另一个参数【英文标题】:Is it possible for an optional argument value to depend on another argument in Scala可选参数值是否可能依赖于 Scala 中的另一个参数 【发布时间】:2011-03-06 16:00:48 【问题描述】:

有谁知道这样的事情在 Scala 中是否可行:

case class Thing(property:String)

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

以上代码无法编译;在thing.property 给出错误error: not found: value thing

以下显示了预期的行为:

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

我意识到我可以将 prop 参数设为 Option[String] 并检查函数定义,但我想知道是否有办法通过 2.8.0 中的新命名/默认参数支持来解决它。

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

但我认为强制提供Option 而不是普通参数是不好的做法。【参考方案2】:

是的,在 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

【讨论】:

谢谢,这正是我所追求的。 要违反 DRY(不要重复自己):这太棒了。【参考方案3】:

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

case class Thing (property: String)

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

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

【讨论】:

如果我没记错的话,这就是 C++ 定义可选/默认参数的方式,对吧? 我用 C++ 编程已经很久了,但你当然可以用 C++ 或 Java 做同样的事情。

以上是关于可选参数值是不是可能依赖于 Scala 中的另一个参数的主要内容,如果未能解决你的问题,请参考以下文章

从表 2 中选择一个值,该值依赖于表 1 中的另一个值 (Oracle SQL)

scala:作为其他参数的函数的可选默认参数

使用Scala中的不可变值查找路径是不是存在于图形中

将行值转换为列,其值来自 spark scala 中的另一列 [重复]

scala-从入门到精通

如何将 main 方法移动到 Scala 中的另一个类?