이기종 목록에 대한 특정 목적이 있습니까? 나는 목록이 균질하다는 것에 익숙합니다. Lisp를 집어

C #과 Java 배경에서 왔을 때, 나는 목록이 균질하다는 것에 익숙합니다. Lisp를 집어 들었을 때 목록이 이기종 일 수 있음을 알았습니다. dynamicC # 에서 키워드로 문제를 해결하기 시작했을 때 C # 4.0부터 이기종 목록이있을 수 있음을 알았습니다.

List<dynamic> heterogeneousList

내 질문은 요점이 뭐야? 이기종 목록은 처리를 수행 할 때 훨씬 많은 오버 헤드가있는 것처럼 보이며 한 장소에 다른 유형을 저장 해야하는 경우 다른 데이터 구조가 필요할 수 있습니다. 나의 순진함이 추악한 얼굴을 키우고 있습니까? 아니면 이기종 목록을 갖는 것이 유용한 때가 있습니까?



답변

이 신문은 강하게 이기종 컬렉션 형식화 된 올렉 Kiselyov에 의해, 랄프 Lämmel, 그리고 Keean Schupke 하스켈 이종리스트의 구현뿐만 아니라, 언제, 왜 당신이 HLists을 사용 방법에 대한 동기를 부여하는 예뿐만 아니라 포함되어 있습니다. 특히 형식 안전 컴파일 타임 검사 데이터베이스 액세스에 사용하고 있습니다. (LINQ는 사실, 그들은 참조하는 용지가 생각 입니다 LINQ되었다 에릭 마이어 등으로 하스켈 종이.)

HLists 논문의 소개 단락에서 인용 :

이기종 콜렉션을 요구하는 일반적인 예제의 개방형 목록은 다음과 같습니다.

  • 다른 유형의 항목을 저장해야하는 기호 테이블은 이기종입니다. 결과 유형이 인수 값에 따라 결정되는 유한 맵입니다.
  • XML 요소는 이기종 형식입니다. 실제로 XML 요소는 정규식과 1- 모호성 속성으로 제한되는 중첩 컬렉션입니다.
  • SQL 조회에 의해 리턴되는 각 행은 열 이름에서 셀로 이기종 맵입니다. 쿼리 결과는 이종 행의 동종 스트림입니다.
  • 기능적 언어에 고급 개체 시스템을 추가하려면 확장 가능한 레코드와 하위 유형 및 열거 인터페이스를 결합하는 이종 종류의 컬렉션이 필요합니다.

귀하의 질문에 제시 한 예는 실제로 단어가 일반적으로 사용된다는 의미에서 이기종 목록이 아닙니다. 그것들은 약한 유형 이거나 유형이 지정되지 않은 목록입니다. 사실, 그들은 실제로 균일 한 모든 요소가 같은 유형이기 때문에, 목록 : objectdynamic. 그런 다음 instanceof실제로 요소에 대해 의미있게 작업 할 수 있도록 캐스트 또는 검사되지 않은 테스트 등 을 수행해야합니다 .


답변

짧고 이기종 컨테이너는 유연성을 위해 런타임 성능을 교환합니다. 특정 유형의 물건에 관계없이“물건 목록”을 원한다면 이질성이 있습니다. 리스프는 특성상 동적으로 유형이 지정되며 대부분의 경우 상자 값의 단점 목록이므로 성능 저하가 적을 것으로 예상됩니다. Lisp 세계에서 프로그래머 생산성은 런타임 성능보다 더 중요합니다.

동적으로 유형이 지정된 언어에서 동종 컨테이너는 이종 컨테이너에 비해 실제로 약간의 오버 헤드가 발생합니다. 추가 된 모든 요소는 유형 검사가 필요하기 때문입니다.

더 나은 데이터 구조를 선택하는 것에 대한 직감이 적절합니다. 일반적으로 코드에 더 많은 계약을할수록 코드 작동 방식에 대해 더 많이 알 수 있으며 더 안정적이고 유지 관리가 용이합니다. 됩니다. 그러나 때때로 당신은 정말로 이종 컨테이너를 원하고, 당신은 당신이 그것을 필요로하는 경우에 하나를 가질 수되어야한다.


답변

기능 언어 (예 : lisp)에서는 패턴 일치를 사용하여 목록의 특정 요소에 어떤 일이 발생하는지 확인합니다. C #에서 동등한 것은 요소의 유형을 확인하고이를 기반으로 작업을 수행하는 if … elseif 문의 체인입니다. 말할 필요도없이, 기능 패턴 일치는 런타임 유형 검사보다 효율적입니다.

다형성을 사용하는 것이 패턴 일치에 더 가깝습니다. 즉, 목록의 객체가 특정 인터페이스와 일치하도록하고 각 객체에 대해 해당 인터페이스에서 함수를 호출합니다. 또 다른 대안은 특정 객체 유형을 매개 변수로 취하는 일련의 오버로드 된 메소드를 제공하는 것입니다. Object를 매개 변수로 사용하는 기본 방법입니다.

public class ListVisitor
{
  public void DoSomething(IEnumerable<dynamic> list)
  {
    foreach(dynamic obj in list)
    {
       DoSomething(obj);
    }
  }

  public void DoSomething(SomeClass obj)
  {
    //do something with SomeClass
  }

  public void DoSomething(AnotherClass obj)
  {
    //do something with AnotherClass
  }

  public void DoSomething(Object obj)
  {
    //do something with everything els
  }
}

이 접근 방식은 Lisp 패턴 일치에 대한 근사치를 제공합니다. 방문자 패턴 (여기에서 구현 된 것처럼 이기종 목록 사용의 좋은 예) 다른 예는 우선 순위 큐에 특정 메시지에 대한 리스너가 있고 책임 체인을 사용하는 메시지 디스패치의 경우, 디스패처는 메시지를 전달하고 메시지와 일치하는 첫 번째 핸들러는 메시지를 처리합니다.

반대쪽은 메시지를 등록하는 모든 사람에게 알리는 것입니다 (예 : MVVM 패턴에서 ViewModel의 느슨한 결합에 일반적으로 사용되는 이벤트 집 계기 패턴). 다음 구성을 사용합니다

IDictionary<Type, List<Object>>

사전에 추가하는 유일한 방법은 함수입니다

Register<T>(Action<T> handler)

(그리고 객체는 실제로 전달 된 핸들러에 대한 WeakReference입니다). 그래서 컴파일 타임에 닫힌 유형이 무엇인지 모르기 때문에 List <Object>를 사용해야합니다. 그러나 런타임에 사전의 키가되는 유형이되도록 강제 할 수 있습니다. 이벤트를 시작하고 싶을 때

Send<T>(T message)

다시 목록을 확인합니다. 어쨌든 캐스트해야하기 때문에 List <dynamic>을 사용하면 이점이 없습니다. 보시다시피 두 접근 방식에는 장점이 있습니다. Method overloading을 사용하여 객체를 동적으로 디스패치하려는 경우 dynamic이 수행 방법입니다. 관계없이 캐스팅을 강요 받았다면 Object를 사용할 수도 있습니다.


답변

이기종이 런타임 오버 헤드를 발생시키는 것이 맞지만 유형 검사기에서 제공하는 컴파일 타임 보장을 약화시킵니다. 그럼에도 불구하고 대안이 훨씬 더 비싼 문제가 있습니다.

내 경험상 파일, 네트워크 소켓 등을 통해 원시 바이트를 처리하면 종종 이러한 문제가 발생합니다.

실제 사례를 제시하려면 선물을 사용한 분산 계산 시스템을 고려하십시오 . 개별 노드의 작업자는 직렬화 가능한 모든 유형의 작업을 생성하여 해당 유형의 미래를 산출 할 수 있습니다. 무대 뒤에서 시스템은 작업을 동료에게 보낸 다음 해당 작업 단위가 해당 작업에 대한 답변이 반환되면 채워 져야하는 특정 미래와 연결하는 레코드를 저장합니다.

이 기록들은 어디에 보관할 수 있습니까? 직관적으로, 당신이 원하는 것은과 Dictionary<WorkId, Future<TValue>>같지만 이것은 전체 시스템에서 한 가지 유형의 미래 만 관리하도록 제한합니다. Dictionary<WorkId, Future<dynamic>>근로자가 미래를 강요 할 때 적절한 유형으로 캐스팅 할 수 있기 때문에 더 적합한 유형은 입니다.

참고 :이 예는 하위 유형이없는 Haskell 세계에서 나왔습니다. C # 에서이 특정 예제에 대한 관용적 솔루션이 있는지는 놀랄 일이 아니지만 여전히 잘 설명되어 있습니다.


답변

ISTR은 리스프는 집계 데이터 객체의 모든 유형을 필요로하는 경우 그래서, 것, 목록 이외의 데이터 구조를 가지고 있지 않는 이종 목록이 될 수 있습니다. 다른 사람들이 지적했듯이 전송 또는 저장을 위해 데이터를 직렬화하는 데 유용합니다. 좋은 기능 중 하나는 개방형이므로 파이프 및 필터 유추를 기반으로 한 시스템에서이를 사용할 수 있으며 고정 된 데이터 개체 또는 워크 플로 토폴로지 없이도 처리 단계를 늘리거나 데이터를 수정하는 연속적인 처리 단계를 가질 수 있다는 것입니다. .


답변