C # , Scala, Haskell, Lisp 및 Python 의 zip
동작 은 동일 합니다. 하나의 컬렉션이 더 길면 꼬리는 자동으로 무시됩니다.
예외도 발생할 수 있지만이 방법을 사용하는 언어에 대해서는 들어 보지 못했습니다.
이것은 나를 퍼즐. 왜 그렇게 zip
설계된 이유를 아는 사람이 있습니까? 나는 다른 언어가 이런 식으로하기 때문에 새로운 언어를 생각합니다. 근본 원인은 무엇입니까?
나는 누군가가 그것을 좋아하는지, 또는 그것이 좋은지 나쁜지가 아니라 사실적이고 역사적인 기반의 질문을하고 있습니다.
업데이트 : 내가 무엇을 해야하는지 묻는다면, 배열을 인덱싱하는 것과 비슷하게 예외를 던집니다 ( “오래된”언어는 모든 종류의 마술을 했음에도 불구하고 범위, 인덱스, UB, 확장 배열을 처리하는 방법, 기타).
답변
그것은 거의 항상 당신이 원하는 것입니다. 그렇지 않을 때는 직접 채울 수 있습니다.
가장 큰 문제는를 처음 시작할 때 길이를 모르는 게으른 의미론으로 시작시 zip
예외를 던질 수 없습니다. 먼저 모든 공통 요소를 반환 한 다음 예외 를 throw해야합니다. 매우 유용하지는 않습니다.
스타일 문제이기도합니다. 명령형 프로그래머는 모든 곳에서 경계 조건을 수동으로 확인하는 데 익숙합니다. 기능 프로그래머는 설계 상으로는 실패 할 수없는 구조를 선호합니다. 예외는 매우 드 rare니다. 함수가 합리적인 기본값을 반환하는 방법이 있다면, 함수형 프로그래머가이를 취할 것입니다. 작곡은 왕입니다.
답변
꼬리를 완성하는 확실한 방법이 없기 때문입니다. 이를 수행하는 방법을 선택하면 명확하지 않은 꼬리가 생깁니다.
트릭은 가장 긴 목록의 길이를 예상 한 값과 일치하도록 가장 짧은 목록을 명시 적으로 늘리는 것입니다.
만약 zip이 당신을 위해 그렇게한다면, 당신은 그것이 어떤 값을 직관적으로 채우고 있는지 알 수 없었습니다. 목록을 순환 했습니까? 빈 값을 반복 했습니까? 귀하의 유형에 대한 빈 값은 무엇입니까?
꼬리가 길어지는 방식을 직관하는 데 사용할 수있는 지퍼의 기능에는 영향이 없으므로 소비자가 기대하지 못할 수도있는 값을 사용하는 것이 합리적입니다.
또한 잘 알려진 특정 의미론을 가진 매우 특정한 잘 알려진 함수를 참조하고 있음을 기억하십시오. 그렇다고해서 유사하지만 약간 다른 기능을 수행 할 수는 없습니다 . 을 수행하는 공통 기능이 있다고 x
해서 원하는 목표 x
와 목적을 결정할 수 없다는 의미는 아닙니다 y
.
이것과 다른 많은 일반적인 FP 스타일 함수가 일반적인 이유를 기억하지만, 간단하고 일반화되어 있기 때문에 코드를 사용하여 원하는 동작을 수행 할 수 있습니다. 예를 들어 C #에서는
IEnumerable<Tuple<T, U>> ZipDefaults(IEnumerable<T> first, IEnumerable<U> second)
{
return first.Count() < second.Count()
? first.Concat(Enumerable.Repeat(default(T), second.Count() - first.Count())).Zip(second)
: first.Zip(second.Concat(Enumerable.Repeat(default(U), first.Count() - second.count())))
}
또는 다른 간단한 것들. FP 접근 방식을 사용하면 조각을 재사용 할 수있을뿐 아니라 구현이 너무 작아서 자신 만의 수정 된 버전을 만드는 것이 매우 간단하기 때문에 수정이 매우 쉽습니다.