정수를 래핑하는 간단한 사례 클래스가 있고 래퍼에 정수를 전달하는 함수를 허용하는 상위 순서 메서드가 있다고 가정합니다.스칼라 케이스 클래스를 추출기로 바꾸면 고차 함수가 손상된 이유는 무엇입니까?
case class Wrapper(x :Int)
def higherOrder(f : Int => Wrapper) = println(f(42))
그런 다음 상위 순서 함수를 호출하여 래퍼의 생성 된 적용 함수를 전달할 수 있습니다. 놀랍게도, 래퍼의 이름을 전달할 수도 있습니다.
higherOrder(Wrapper.apply) // okay
higherOrder(Wrapper) // okay, wow!
정말 멋지다. 우리는 표현 클래스의 추상화를 촉진하는 함수로서 사례 클래스의 이름을 취급 할 수 있습니다. 이 차가움의 예를 보려면 여기에서 답변을 참조하십시오. What does "abstract over" mean?
이제 내 사례 클래스가 충분히 강력하지 않다고 가정하고 대신 추출기를 만들어야합니다. 가볍게 고안된 유스 케이스로서, 정수로 파싱하는 문자열에서 패턴 일치를 할 수 있어야한다고 가정 해 봅시다.
// Replace Wrapper case class with an extractor
object Wrapper {
def apply(x :Int) = new Wrapper(x)
def unapply(s :String) :Option[Wrapper] = {
// details elided
}
}
class Wrapper(x :Int) {
override def toString = "Wrapper(" + x + ")"
// other methods elided
}
이러한 변화에 따라, 나는 아직도 내 고차 함수에 Wrapper.apply 전달할 수 없지만 전달은 래퍼가 더 이상 작동합니다.
higherOrder(Wrapper.apply) // still okay
higherOrder(Wrapper) // DOES NOT COMPILE
^^^^^^^
// type mismatch; found : Wrapper.type (with underlying type Wrapper)
// required: (Int) => Wrapper
아야! 여기 왜이 비대칭 성은 문제가되는 것입니다. Odersky, Spoon 및 Venners (Programming in Scala, 500 페이지)의 조언에 따르면
언제나 사례 클래스로 시작한 다음 필요할 경우 추출기로 변경할 수 있습니다. 스칼라에서는 사례 클래스의 추출기 및 패턴에 대한 패턴이 정확히 같기 때문에 클라이언트의 패턴 일치가 계속 작동합니다.
물론 사실이지만, 케이스 클래스 이름을 함수로 사용하면 클라이언트를 중단시킬 것입니다. 그리고 이렇게하면 강력한 추상화가 가능해지기 때문에 확실한 의지가 있습니다.
따라서 상위 순서 함수로 전달할 때 추출기를 사례 클래스와 동일한 방식으로 작동하게하려면 어떻게해야합니까?
질문에 대한 답변을 수락하는 것을 당혹스럽게 생각하지 마십시오. 정말로 사회적으로 받아 들일 만하며, 거의 모든 사람들이 어느 시점에서 그것을 해왔습니다. –