스칼라 컴파일러가 봉인되지 않은 클래스 / 특성에 대해 패턴 일치 경고를 표시 할 수없는 이유는 무엇입니까?


10

내가 사용하는 경우 취소 밀봉 trait또는 abstract class스칼라 후 사용 패턴 매칭을 궁금해 사용할 수 있습니다이 특성 / 클래스의 수 어떻게 구현이 특정 patternmatch에 대한 컴파일시에 컴파일러 알고하지 않는 이유는 무엇입니까? 따라서 그렇다면 가능한 모든 종속성 / 가져 오기를 확인하여 사용할 있는 유형을 알고 있기 때문에 trait/ abstract class가 봉인되어 있지 않아도 패턴 일치 경고를 표시 수 없습니까?

예를 들어 Option[A]및에 대해서만 패턴 일치를하고 패턴이 일치 Some[A]하지 않으면 None컴파일러 Option가 봉인 되기 때문에 불평 합니다.

컴파일러가 그것을 알 수 없거나 해결할 수 없다면 왜 할 수 없습니까? 컴파일러가 이론적으로 그렇게 할 수 있다면 스칼라에서 사용되지 않는 이유는 무엇입니까? 이런 종류의 행동을 지원하는 다른 언어가 있습니까?


당신이 무엇을 요구하는지 명확하지 않습니다. 일치 표현식이 가능한 모든 입력을 포함하지 않는 경우 컴파일러에서 경고를 표시하도록 하시겠습니까? 아마도 예를 들어 질문을 더 명확하게 만들 수있을 것입니다.
kdgregory

2
누구든지 새로운 서브 클래스를 도입 할 수 있다면 패턴 일치는 결코 철저하지 않을 수 있습니다. 예를 들어 , Foo서브 클래스 A, B및을 사용 하여 추상 클래스 를 생성하면 C모든 패턴 일치가 해당 세 개만 일치합니다. D패턴 일치를 날려 버릴 새로운 서브 클래스 를 추가하는 것을 막을 수 있는 것은 없습니다 .
Doval

@kdgregory 예, 알겠습니다. 좀 더 명확하게하기 위해 예제를 추가했습니다.
valenterry

3
모든 임포트를 점검하는 것만으로는 가능한 모든 서브 클래스를 발견 할 수 없습니다. 다른 하위 클래스는 나중에 런타임 동안을 통해로드되는 별도의 클래스 파일로 선언 될 수 있습니다 java.lang.ClassLoader.
amon

답변:


17

클래스의 모든 하위 클래스를 파악하는 것을 클래스 계층 분석이라고하며 동적 코드로드가있는 언어에서 정적 CHA를 수행하는 것은 중지 문제를 해결하는 것과 같습니다.

또한 Scala의 목표 중 하나는 독립적 인 모듈의 개별 컴파일 및 배포입니다. 따라서 컴파일러는 클래스가 다른 모듈에서 서브 클래 싱되는지 여부를 알 수 없습니다. 하나 이상의 모듈을 보지 않기 때문입니다. (결국 시스템에 해당 모듈이없는 다른 모듈의 인터페이스에 대해 모듈을 컴파일 할 수 있습니다!) 따라서 sealed모든 서브 클래스를 동일한 컴파일 단위로 정의해야합니다.

이것이 JVM이 C ++ 컴파일러와 경쟁하기 쉬운 이유 중 하나입니다. C ++ 컴파일러는 일반적으로 정적 컴파일러이므로 일반적으로 메소드가 재정의되는지 여부를 알 수 없으므로 인라인 할 수 없습니다. JVM OTOH는 일반적으로 동적 컴파일러이며 메소드가 재정의되었는지 여부를 파악하기 위해 CHA를 수행 할 필요가 없으며 런타임시 클래스 계층을 볼 수 있습니다. 그리고 나중에 프로그램 실행의 새로운 시점에 새로운 하위 클래스가 나오더라도 그다지 중요하지 않고 인라인없이 해당 코드 조각을 다시 컴파일하십시오.

참고 :이 모든 것은 스칼라 내에서만 적용됩니다. JVM에는 개념이 없으므로 다른 언어와 통신 할 수있는 방법이 없으므로 다른 JVM 언어 에서 클래스 sealed를 서브 클래 싱하는 것이 가능합니다 . 속성에 기록 주석 있지만, 다른 언어 '컴파일러는 분명히 계정으로 그 주석을하지 않습니다.sealedsealedScalaSig


3

(적어도 컴파일 타임에 알려진 모든 클래스), 그냥 비싼 할 수. 패턴 일치가 포함 된 모든 항목은 다른 파일이 변경 될 때마다 효과적으로 재 컴파일해야하므로 증분 컴파일을 완전히 중단해야합니다.

그리고 당신은 무엇을 사고 있습니까? 새로운 파생 클래스가 추가 될 때 자주 변경해야하는 패턴 일치를 작성하는 것은 코드 냄새입니다. 그것은 개방 / 폐쇄 원칙을 위반하는 입니다. 상속을 올바르게 사용하면 이런 종류의 패턴 일치를 작성할 필요가 없습니다. 그리고 개방 / 폐쇄 원칙은 클래스 기반 상속이없는 기능적 언어에도 적용됩니다. 실제로 타입 클래스, 멀티 메소드, 단순한 고차 함수와 같은 기능 사이에서 기능적 언어는 수정없이 확장을 훨씬 쉽게 해줍니다.


1
It can be done (at least for all classes known at compile time), it's just expensive.그러나 프로그램이 100 % 자체 포함되어 있지 않은 경우 (즉, 외부 .jar파일에 따라 다름 ) s 중 하나를 통해 컴파일 한 새 하위 클래스를 몰래 넣을 수 jar없습니까? 따라서 컴파일러는 "패턴 일치는 이제 철저하지만, 종속성이 변경되면 변경 될 수 있습니다" 라고 말할 수 있습니다. 외부 종속성이 있다는 점은 재 컴파일하지 않고 업데이트 할 수 있기 때문에 매우 가치가 없습니다!
Doval

따라서 면책 조항. 실제로 외부 또는 외부의 종속성에 대해 철저한 일치가 필요할 정도로 단단히 결합 된 경우 어쨌든 다시 컴파일해야합니다.
Karl Bielefeldt

@Doval 그런 다음 어떤 형태의 위임을 사용해야하며 호출되는 클래스가 수행 할 작업을 결정하고 제어를 반전시켜야합니다. 이것이 OOP를위한 것입니다. 원하지 않으면 현재 문제가 있습니다.
썰매

@ArtB 나는 제어와 관련된 위임 또는 반전이 무엇과 관련이 있는지 알지 못한다.
Doval

사람들이 외부에 추가 할 수있는 사람들과 함께 작동하려면 클래스를 호출하고 논리를 해당 클래스로 이동하십시오.
썰매
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.