0

次のように定義された Point というケース クラスがあります。

case class Point(x: Double, y: Double)

ポイントの配列を取る関数:

def f(coords: Array[Point]) ...

double 配列の配列を関数に暗黙的に渡すことができるようにしたいと考えています。これを実現するために、次の 2 つの暗黙的な関数を定義しました。

implicit def arrayToPoint(a: Array[Double]) = new Point(a(0), a(1)) 
implicit def arraysToPoints(a: Array[Array[Double]]) = a map(p => Point(p(0), p(1)))

私の質問は、問題を単純化するために単一の暗黙的な変換関数だけでこれを達成できる方法はありますか?

関連する質問として、Double の代わりに Int の配列を渡すことができるようにしたい場合、どのような方法が最適でしょうか?

よろしく

デス

4

1 に答える 1

1

あなたの方法arraysToPointsは余計です。次のように、メソッドの配列引数にバインドされたビューを使用してf、のコンパニオン オブジェクトに変換を追加できますPoint

object Point {
  implicit def arrayToPoint[A](a: Array[A])(implicit view: A => Double): Point =
    Point(a(0), a(1))
}
case class Point(x: Double, y: Double)

def f[P](coords: Array[P])(implicit view: P => Point): Unit = coords.foreach { p =>
  println(p: Point)
}

f(Array(Point(1, 2), Point(2, 3)))
f(Array(Array(1.0, 2.0), Array(3.0, 4.0)))
f(Array(Array(1, 2), Array(3, 4)))

Intとの両方の配列をカバーできるようにするために、メソッドDoubleにバインドされた 2 番目のビューを使用しました。arrayToPointそうしないと、 と に対して 2 つの別個の変換メソッドが必要にArray[Int]なりArray[Double]ます。

この定義は、「型として表示できるf型の要素の配列を取る」と読むことができます。コンパイラがそのようなビューを探す 1 つの場所は、ターゲット型のコンパニオン オブジェクトです。これは、暗黙的なメソッドに適した場所です。PPointobject Point


2 番目の可能性は、マグネット パターンを使用することです。のビューでポイントごとに変換する代わりにf、単一のラッパー オブジェクトを一度に作成します。これは少しきれいで、大きな配列の場合、直接Array[Double]引数のペナルティを最小限に抑えます (ラッパーを一度インスタンス化するだけで、ビュー関数を呼び出す必要がなくなるため)。arrayToPoint配列要素の型Aが再び として表示できる場合は常に使用されDoubleます。Doubleこれはもちろんそれ自体にも当てはまりますが、これはScala が数値の拡大と呼んでいるものと見なすIntことDoubleもできます (たとえば、val x: Double = 33整数33は暗黙的に double に「拡大」されます)。

object Points {
  implicit def direct(a: Array[Point]): Points =
    new Points {
      val peer = a
    }

  implicit def indirect[A](a: Array[Array[A]])(implicit view: A => Double): Points =
    new Points {
      lazy val peer = a.map { c => Point(c(0), c(1)) }
    }
}
trait Points {
  def peer: Array[Point]
}

def f(coords: Points): Unit = coords.peer.foreach(println)

これは、コンパニオン オブジェクトで、引数 type から特殊な magnet type への暗黙的なメソッドを探しますPoints。メソッドが呼び出されないlazy val場合に実際の変換アクションを保存できるように、非直接配列に使用します。peer

于 2013-10-18T13:41:10.183 に答える