2010-08-03 3 views
14

얼랑 (Erlang)에서는 실제로 다루지 않는 패턴과 일치하지 않는 것이 좋습니다. 예를 들어 :패턴 매칭, F # vs Erlang

case (anint rem 10) of 
    1 -> {ok, 10} 
    9 -> {ok, 25} 
end; 

badmatch 결과의 결과로 다른 가능한 결과를 장려하는 스타일입니다. 이는 얼랑 (Erlang)의 "추락 시키자"철학과 일치합니다.

한편 F #은 here과 같은 F # 코드에서 "불완전한 패턴 일치"를 발행합니다.

질문 : 왜 F하지 #이

|_ -> failwith "badmatch" 

하고 "이 충돌하자"철학을 사용하는 것과 성명과 일치하는 모든 패턴을 보강하여 효과적으로 경고를 제거 할 것인가?

편집 : 두 가지 흥미로운 해답은 지금까지 : 대수 데이터 유형의 모든 경우를 처리하지 않을 때 발생할 수있는 버그를 방지하거나, 또는 .Net 플랫폼 때문에. OCaml을 확인하는 방법 중 하나를 찾으려면. 그렇다면 OCaml의 기본 동작은 무엇입니까?

편집 : Erlang을 배경으로하지 않는 .Net 사람들이 오해를 제거하십시오. Erlang 철학의 요점은 항상 충돌하는 나쁜 코드를 생성하는 것이 아니라는 것입니다. 그것을 깨뜨리게하자. let some other process fix the error. 가능한 모든 경우를 처리 할 수 ​​있도록 함수를 작성하는 대신 호출자가 자동으로 throw되는 불량 사례를 처리하도록합니다. 자바를 사용하는 사람들은 가능한 예외가 발생할 때마다 반환 할 모든 것을 선언해야하고, 함수가 명시 적으로 선언되지 않은 예외를 발생시킬 수있는 언어를 가져야하는 확인 된 예외가있는 언어와 다른 점이 있습니다.

+0

필자는이 기능이 사용자의 함수가 예상되는 전체 도메인을 처리해야한다는 철학이라고 생각하며 컴파일러가이 점을 상기시킵니다. 함수가 2보다 많은 경우를 처리하지 못하면 형식에 따라 인수를 제한해야하며, 그렇지 않으면 모두 인수를 사용해야합니다. 그것이 내 이해입니다. 나는이 철학에 대해 스스로 배우고있다. – grettke

+0

@ grettke : 정확합니다. 이 철학은 얼랑 철학과 정반대입니다. 그리고 제 질문은 왜이 철학이 선호되는지입니다. 아래 답변은 아주 밝게 빛납니다. –

답변

23

F # (및 Haskell 및 O'Caml과 같은 패턴 일치가있는 다른 언어)은 암시 적으로 예외를 throw하는 사례를 추가합니다.

완벽하게 패턴을 일치시키고 경고에주의를 기울이는 가장 중요한 이유는 컴파일러가 아직 작성하지 않은 코드에 대해 경고하기 때문에 데이터 유형을 확장하여 쉽게 리팩토링 할 수 있다는 것입니다. 새 사례로 업데이트되었습니다.

한편, 때로는 거기에 빠뜨려야 할 사례가 있으며, 종종 오류 메시지가 빈발하여 포괄적 인 상황에 놓여 야하는 것은 귀찮습니다. 따라서 그것은 절충점입니다.

O'Caml (및 -Wall이있는 하스켈)에서 편집에 대한 응답으로이 경고 메시지가 기본적으로 표시됩니다.

+0

감사합니다. 나는 리팩토링이 좋은 이유라는 것을 알 수있다. 그리고 OCaml/Haskell 정보에 감사드립니다. –

13

대부분의 경우, 특히 대수 데이터 유형의 경우 사례를 잊어 버리는 것은 사고 일 수 있으며 사례를 무시하려는 의도가 아닙니다. 강력하게 형식화 된 함수형 언어에서는 대부분의 함수가 합계라고 생각하므로 모든 경우를 처리해야합니다. 부분 함수의 경우에도 일반적인 패턴 일치 실패 (예 : List.head은 빈 목록이 제공된 경우 ArgumentException을 던짐)를 사용하는 대신 특정 예외를 throw하는 것이 이상적입니다.

따라서 일반적으로 컴파일러가 개발자에게 경고하는 것이 합리적이라고 생각합니다. 이 동작이 마음에 들지 않으면 자체적으로 예외를 throw하는 포괄 패턴을 추가하거나 경고를 끄거나 무시할 수 있습니다.

11

왜 F # 당신이 물어 것이라고

재미있는 경고를 제거하지 않을 것입니다. 런타임 오류의 소스를 자동으로 주입하는 것은 F # 및 그 친척 뒤에있는 철학에 절대적으로 위배됩니다. 그것은 그로테스크 한 가증으로 간주됩니다. 이 언어 군은 유형 검사 시스템이 근본적으로 이러한 종류의 정적 검사를 용이하게하기 위해 설계된 범위 내에서 정적 검사에 관한 것입니다.

이 철학과 완전히 다른 점은 정확하게 F #과 Python이 비교되고 대조되는 이유입니다. "두 사람은 결코 만나지 않을 것"이라고 그들은 말한다.

그럼 OCaml의 기본 동작은 무엇입니까?

F #과 동일 : 컴파일시 패턴 매치의 중복성 및 중복성을 검사하고 일치하는 항목이 의심스러운 경우 경고가 발행됩니다. 관용적 스타일도 동일합니다. 이러한 경고가 나타나지 않도록 코드를 작성해야합니다.

이 동작은 .NET과는 아무런 관련이 없습니다. 실제로 OCaml의이 기능은 F #에서 제대로 구현되었습니다.

예를 들어, 목록을 알고 있기 때문에 당신이 목록의 첫 번째 요소를 추출하기 위해 let 바인딩의 패턴을 사용하는 경우는 항상이 적어도 하나의 원소 : 언어의 가족에서

let x::_ = myList 

, 이는 거의 항상 디자인 결함을 나타냅니다. 올바른 해결책은 비어있는 목록을 나타내는 것이 불가능한 유형을 사용하여 비어 있지 않은 목록을 나타내는 것입니다. 정적 유형 검사는 목록이 비어있을 수 없으므로 런타임 오류의 소스가 코드에서 완전히 제거되었음을 보증합니다.

예를 들어 비어 있지 않은 목록을 머리 및 꼬리 목록이 들어있는 튜플로 나타낼 수 있습니다. 그러면 패턴 일치는 다음과 같습니다.

let x, _ = myList 

이것은 포괄적이므로 컴파일러는 만족하고 경고를 발행하지 않습니다. 이 코드 은 런타임에 잘못 놓일 수 없습니다..

나는 응용 프로그램에서 런타임 오류의 주요 출처였던 상업용 OCaml 코드에 대해 약 1kLOC를 리팩토링 한 2004 년에이 기법을지지했습니다 (비록 catch- 예외를 발생시킨 모든 일치 사례). 리팩토링으로 인해 대부분의 코드에서 런타임 오류가 모두 제거되었습니다. 전체 애플리케이션의 안정성이 엄청나게 향상되었습니다. 또한 디버깅을 통해 버그를 사냥하는 데 수 주일이 걸렸지 만 리팩토링은 2 일 이내에 완료되었습니다. 따라서이 기술은 실제로 현실 세계에서 배당금을 지불합니다.

+2

Nitpick : 코드 동작이 변경된 경우 리팩토링을하지 못했습니다. – Douglas

+2

@ 존 : 파이썬 문제에 빠져 들었습니다. Erlang 철학이 그렇게 나쁘지 않은 이유에 대한 저스틴 니 스너 (Justin Niessner)의 대답에서 JSBands에 대한 제 의견을 참조하십시오. 얼랭 (Erlang)은 .Net이 지금까지 달성 한 것보다 훨씬 더 안정적인 통신 애플리케이션을 보유하고 있습니다. 응답하기 전에 질문의 다른 측면을 이해하려고 노력하십시오. 얼랑 (Erlang)에서 번역을 오류로 만들어 다른 프로세스가 오류를 수정하도록하십시오. 자세한 내용은 [조 암스트롱의 논문] (http://www.erlang.org/download/armstrong_thesis_2003.pdf)을 참조하십시오. –

+2

재미있게, "자동으로 런타임 에러의 소스를 주입"한다는 것은 Erlang이'| _ ->()'를 제거하기 만하면됩니다. Erlang은 주어진 사례 중 하나와 일치하지 않으면 항상 'badmatch'를 반환합니다. –

3

OCaml은 기본적으로 불완전한 일치에 대해 경고합니다. "-w"플래그에 "p"를 추가하여 비활성화 할 수 있습니다. 이 경고의 아이디어는 프로그래머 오류를 나타내는 것보다 더 자주 (적어도 내 경험에서). 특히 모든 패턴이 Node (Node (Leaf 4) x) (Node y (Node Empty _))처럼 실제로 복잡하면 사례를 놓치기 쉽습니다. 프로그래머가 잘못 될 수 없다고 확신 할 경우 명시 적으로 | _ -> assert false 사례를 추가하는 것은이를 나타내는 명확한 방법입니다.

GHC는 기본적으로 이러한 경고를 해제합니다. 하지만 활성화 할 수 있습니다 -fwarn-incomplete-patterns

3

어레인지 (Erlang)는 동적 유형으로 인해 철저한 패턴 매칭을 할 수 없습니다. Ocaml은 다른 한편으로는 할 수 있습니다. 또한 Ocaml은 컴파일 타임에 잡힐 수있는 모든 문제를 컴파일 타임에 푸시하려고합니다.

+0

동적 타이핑 문제가 중요합니다. 감사. –