18

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引数を anにして、関数定義でチェックできることはわかっていOption[String]ますが、2.8.0 の新しい名前付き/デフォルト引数のサポートでそれを回避する方法があるかどうか疑問に思っていました。

4

3 に答える 3

22

はい、Scala 2.8 では可能です。以下は、 「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
于 2010-06-22T06:55:54.213 に答える
2

別の簡単な解決策は、メソッドをオーバーロードすることです。

case class Thing (property: String)

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

def f(thing: Thing) = f(thing, thing.property)
于 2010-06-22T08:09:20.243 に答える
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

期待される動作は、単純なオーバーロードで実現できます。objectREPL ではオーバーロードされた関数の直接宣言が許可されていないように見えるため、メソッドを に配置する必要がありました。

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
于 2010-06-22T06:43:05.723 に答える