2009-06-28 4 views
4

나는 this question을 만났고 무 프로그래밍 프로그래밍 클래스에서 많은 것들을 잊어 버렸습니다.erlang 및 함수 프로그래밍에 대한 중요하지 않은 질문

코드를 이해하려고 노력하면서 코드가 너무 길어서 코드를 짧게하려고했습니다. 이것은 원래 코드가하는 것과 동일한 일을합니까?

merge([X|Xs], Ys) -> [X | merge(Ys, Xs)]; 
merge([], []) -> []. 

는 ... 내가 전에 얼랑 함께 일한 적이없는, 그래서 어쩌면 네, 제대로 작동

답변

3

:-) 일부 구문 오류를했다. 프레젠테이션이 더욱 우아합니다. 그러나 올바르게 배웠다면 Zs 변수를 누적기로 사용하지 않으면 꼬리 재귀가 아니므로 효율성이 떨어집니다. 또한 누산기와 함께 역방향을 사용하면 올바른 순서로 함께 더하는 것보다 더 효율적입니다. 이것이 제가 원했던 이유가 원작이 더 적절한 경우입니다. 그러나 효율성이 중요하지 않은 경우에는 가독성이 효율성보다 우선되어야합니다. 아마도

:

merge(Xs, Ys) -> lists:reverse(merge(Xs, Ys, [])). 

merge([X|Xs], Ys, Zs) -> merge(Ys, Xs, [X|Zs]); 
merge([], [], Zs) -> Zs. 

이것은 당신의 간결하고 이해도 함께 원래의 효율성을 병합합니다.

2

당신은 더 갈 수 :

merge(Xs, Ys) -> lists:reverse(merge1(Xs, Ys, [])). 

merge1([], [], Zs)    -> Zs. 
merge1([X | Xs], [Y | Ys], Zs) -> merge1(Xs, Ys, [X, Y | Zs]). 

이것은 당신이 (적어도 놀라움의 원칙을 위반) 매개 변수 순서를 전환하지 않는 feonixrift의 제안을 통해 상당한 이점이있다.

도우미 함수 (이 경우 merge1)에 다른 이름을 지정하는 것이 좋습니다.이 이름을 사용하면 변경 사항을 쉽게 파악할 수 있습니다. 이는 병합/2가 내보내지지 않고 병합 1/3이 아닌 경우에 특히 그렇습니다. 그것은 기본적으로 "나는 도우미 fn 전화하지 마 직접!"

원하는 종결자를 먼저 작성하는 것이 좋습니다. 재귀의 본질을 명시 적으로 나타내므로이 fn이 목록 고갈에서 종료되는 함수 정의를 읽는 즉시 알 수 있습니다.

+0

목록을 빈 목록과 병합하면이 코드가 원래 목록을 반환합니까? 패턴 일치가 나에게 완전하지 않습니다. –

+0

원래 작업은 같은 길이의 두 목록에 대한 것이 었습니다. – cube

+0

큐브가 옳았습니다. 동일하지 않은 길이의 두 목록에서 원래 코드를 실행하려고 시도하면 실패하게됩니다. MergeR ([], [], Zs)에 일치하는 terminal 절 Xs와 Ys의 길이가 다른 경우 하나의 목록이 다른 목록보다 먼저 소모됨에 따라 오류가 발생합니다. –