代码之家  ›  专栏  ›  技术社区  ›  Kristian Domagala

可选参数值是否可以依赖scala中的另一个参数?

  •  17
  • Kristian Domagala  · 技术社区  · 15 年前

    是否有人知道这样的事情在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 回复  |  直到 14 年前
        1
  •  20
  •   Vasil Remeniuk    15 年前

    是的,这在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
    
        2
  •  1
  •   Jesper    15 年前

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

    case class Thing (property: String)
    
    def f(thing: Thing, prop: String) = println(prop)
    
    def f(thing: Thing) = f(thing, thing.property)
    
        3
  •  0
  •   michael.kebe    15 年前

    这正是 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