sschaef가 임의로 중첩 된 목록에 대한 작동 제안 유형 클래스 방식의 버전을 쓰고 실제로 너무 어렵지 않다 :
trait Reverser[C] {
def reverse(xs: C): C
}
implicit def rev[A](implicit ev: Reverser[A] = null) = new Reverser[List[A]] {
def reverse(xs: List[A]) =
Option(ev).map(r => xs map r.reverse).getOrElse(xs).reverse
}
def deepReverse[A](xs: A)(implicit ev: Reverser[A]): A = ev.reverse(xs)
암시 인수 ev
우리 rev
방법을 증거 A
자체가된다는 점이다 되돌릴 수 있고, ev
이 null 인 경우 이는 의미가 없습니다. A
이 되돌릴 수 있다는 증거가있는 경우 List[A]
의 요소를 뒤집을 때 사용합니다 (map
이 수행하는 것입니다). 그런 다음 목록 자체를 뒤집습니다. 우리가이 증거 (getOrElse
경우)를 가지고 있지 않다면, 우리는 그 목록을 되돌릴 수 있습니다.
scala> deepReverse(List.tabulate(3)(identity))
res0: List[Int] = List(2, 1, 0)
scala> deepReverse(List.tabulate(2,3) { case (a, b) => a + b })
res1: List[List[Int]] = List(List(3, 2, 1), List(2, 1, 0))
scala> deepReverse(List.tabulate(2, 3, 4, 5, 6) {
| case (a, b, c, d, e) => a + b + c + d + e
| }).head.head.head.head
res2: List[Int] = List(15, 14, 13, 12, 11, 10)
로 :
implicit def rev[A](implicit ev: Reverser[A] = null) = if (ev == null) {
new Reverser[List[A]] {
def reverse(xs: List[A]) = xs.reverse
}
} else {
new Reverser[List[A]] {
def reverse(xs: List[A]) = (xs map ev.reverse).reverse
}
}
이 두 버전 중 하나를 테스트하려면, 우리는 다음과 같은 작성할 수 있습니다
우리는 rev
좀 덜 간결하게 (그러나 아마도 더 performantly)과 같이 쓸 수있다 예상했다.
나는 다음과 같은 좀 더 일반적인 관용구가 바로 이런 경우에 implicits를 얻기위한 것이라고 추가해야합니다 :
우리가 같은 수준에
listReverser
및
nestedListReverser
를 작성하려는 경우
trait ReverserLow {
implicit def listReverser[A] = new Reverser[List[A]] {
def reverse(xs: List[A]) = xs.reverse
}
}
object ReverserHigh extends ReverserLow {
implicit def nestedListReverser[A](implicit ev: Reverser[A]) =
new Reverser[List[A]] {
def reverse(xs: List[A]) = xs.map(ev.reverse).reverse
}
}
import ReverserHigh._
, 두 가지를 우선 순위에 대한 표준 접근 방식은
scala> deepReverse(List.tabulate(2, 3)(_ + _))
<console>:12: error: ambiguous implicit values:
both method listReverser...
and method nestedListReverser...
match expected type Reverser[List[List[Int]]]
deepReverse(List.tabulate(2, 3)(_ + _))
가 낮은 우선 순위의 꼬마 도깨비를 넣어 : 우리는 목록의 목록을 반대 할 때 우리는 다음과 같은 오류를 얻을 것 특성 (
WhateverLow
)에 부합하고 그 특성을 확장하는 대상 (
WhateverHigh
)에 다른 것.이와 같은 비교적 간단한 경우에는 위의 내
rev
메서드에서 기본 인수 트릭을 사용하는 것이 더 간결합니다. 그러나 다른 사람의 코드에서 다른 버전을 볼 가능성이 더 큽니다.
젠장! 저는 타이프라이터를 그 자체에 주입하는 것을 생각하지 않았습니다. 위대한 트릭! – sschaef
환상적입니다! getOrElse는 반환 된지도가없는 경우 자체 값을 반환합니다. 매우 감사. –
@GrittyKitty : 감사합니다. 트릭에 대한 자세한 설명은 내 업데이트를 참조하십시오. –