3

後で使用するために一連の変数を定義できますか?

私の意図を強調する擬似コードを次に示します。

def coordinates = x1, y1, x2, y2

log("Drawing from (%4.1f, %4.1f) to (%4.1f, %4.1f)".format(coordinates))
canvas.drawLine(coordinates, linePaint)

重複したコードを含む実際の例を次に示します。

log("Drawing from (%4.1f, %4.1f) to (%4.1f, %4.1f)".format(x1, y1, x2, y2))
canvas.drawLine(x1, y1, x2, y2, linePaint)
4

3 に答える 3

6

はい、できますが、構文は間違いなく恐ろしく不格好です。また、最初は少し恣意的に思えるかもしれないいくつかの制限があります。秘訣は、メソッドを関数に変換し (「eta 拡張」と呼ばれます)、その関数のtupledメソッドを使用して、タプルに適用できるものを取得することです。

次のようなクラスがあるとします。

class Foo {
  def f(a: String, b: String) = "%s, %s".format(b, a)
  def g(x: Int, y: Int, z: Int) = x + y * z
}

そしてインスタンス:

val foo = new Foo

のメソッドを使用したいデータFoo:

val names = ("John", "Doe")
val nums = (42, 3, 37)

foo.f(names)型が一致しないため、単にorと書くことはできませんfoo.g(nums)— 引数リストとタプルは Scala では別のものです。ただし、次のように記述できます。

scala> (foo.f _).tupled(names)
res0: String = Doe, John

scala> (foo.g _).tupled(nums)
res1: Int = 153

メソッドの後にアンダースコアを付けると、それが関数になり (私の意見では、これは Scala の構文の最も紛らわしい小さな癖です)、tupled2 つ (または 3 つ) の引数を持つ関数から単一のタプル引数を持つ関数に変換されます。

たとえば、次のヘルパー関数を定義することで、コードを少しきれいにすることができます。

scala> val myF = (foo.f _).tupled
myF: ((String, String)) => String = <function1>

scala> val myG = (foo.g _).tupled
myG: ((Int, Int, Int)) => Int = <function1>

scala> myF(names)
res2: String = Doe, John

scala> myG(nums)
res3: Int = 153

しかし、それがはるかに優れているかどうかはわかりません。

最後に、(便利なことに) このアプローチを varargs メソッドで使用することはできません。たとえば、次のように書くことはできません。

val coordsTupleToString = ("(%4.1f, %4.1f) to (%4.1f, %4.1f)".format _).tupled

または単に:

val coordsToString = "(%4.1f, %4.1f) to (%4.1f, %4.1f)".format _

これは、Scala で可変引数を避けるもう 1 つの理由です。

于 2012-07-15T21:15:37.610 に答える
2

タプルが必要なようです:

val coordinates = (x1, y1, x2, y2)

それとも本格的なオブジェクトですか?

于 2012-07-15T20:24:04.907 に答える
0

さて、これは明白かもしれませんが、それがあなたを悩ませる場合がごくわずかである場合は、いつでも強化できます:

implicit def enhancedCanvas(canvas: Canvas) = new {
  // using bad and slow syntax. please change this in Scala 2.10.
  def drawLineC(coordinates: (Float, Float, Float, Float), paint: Paint) = {
    val (x1, y1, x2, y2) = coordinates
    canvas.drawLine(x1, y1, x2, y2, paint)
  }
}

あなたが十分に狂っているなら、別の可能性。(このような機能強化は、Scalaz や Shapeless で既に行われている可能性があります。)

implicit def enhTuple4[A,B,C,D](t: Tuple4[A,B,C,D]) = new {
  def |<[E] (f: (A, B, C, D) => E) = f(t._1, t._2, t._3, t._4)
}

// to be used as
val coordinates = (x1, y1, x2, y2)
coordinates |< (canvas.drawLine(_, _, _, _, linePaint))
于 2012-07-15T21:27:18.190 に答える