SqueakByExample:9.2

From 흡혈양파의 번역工房
Jump to navigation Jump to search

컬렉션의 다양성

컬렉션 클래스를 보다 잘 사용하기 위해, 사용자는 적어도 컬렉션 클래스들의 외형 및 컬렉션 클래스들의 공통점들과 차이점들에 대한 지식을 알고 있는것이 좋습니다.

각각의 구성요소들보다는, 컬렉션들을 사용하여 프로그래밍을 하는 것이 프로그램의 추상성의 수준을 끌어올릴 수 있는 보다 중요한 방법입니다. Lisp 언어의 map 함수는 함수와 목록을 인자로 받아서 목록의 각 요소에 각각 함수를 적용해서 결과를 목록으로 반환하며, Smalltalk-80 은 핵심원리로 (이런스타일을 따라) 컬렉션 기반 프로그래밍을 채택하였으며, ML 과 Haskell 과 같은 현대 함수기반 프로그래밍 언어들은 스몰토크의 스타일를 따랐다고 할 수 있습니다.

왜 이런것이 좋은 아이디어 일까요? 예를 들면 학생에 대한 레코드의 집합인 데이터 구조가 있고, 몇가지 기준에 부합하는 모든 학생의 레코드에 대해 같은 동작을 진행하기 원한다고 하죠. 기존의 언어를 사용하는 프로그래머라면 반복문을 바로 생각하겠지만, 스몰토크 프로그래머는 다음처럼 표현식 을 작성할 것입니다.

students select: [ :each | each gpa < threshold ]


위의 표현식은 대괄호 안의 함수가 true[1] 를 반환할때 students 의 element 를 포함하는 새 컬렉션으로 평가(evaluates)합니다. 스몰토크 코드는 도메인-특화 조회 언어의 단순성과 우아함을 갖고 있습니다.


그림 9.3: 표준 컬렉션 프로토콜

Protocol Methods
accessing size, capacity, at: anIndex, at: anIndex put: anElement
testing isEmpty, includes: anElement, contains: aBlock, occurrencesOf: anElement
adding add: anElement, addAll: aCollection
removing remove: anElement, remove: anElement ifAbsent: aBlock, removeAll: aCollection
enumerating do: aBlock, collect: aBlock, select: aBlock, reject: aBlock, detect: aBlock, detect: aBlock ifNone: aNoneBlock, inject: aValue into: aBinaryBlock
converting asBag, asSet, asOrderedCollection, asSortedCollection,asArray, asSortedCollection: aBlock
creation with: anElement, with:with:, with:with:with:, with:with:with:with:, withAll: aCollection


메시지 select: 는 스몰토크의 모든 컬렉션에 전달될 수 있습니다. students 의 데이터 구조가 배열 또는 linked list 인지를 확인할 필요는 없습니다: select: 메시지는 양쪽 모두에 전달될 수 있습니다. 반복(loop)를 사용하는경우에는 students 가 배열인지 linked list 인지를 미리 알아두어야 합니다만, 반복과는 다르다는것에 주의해주시기 바랍니다. 스몰토크에서, 특정 컬렉션을 지칭하지않고 그냥 컬렉션 이라고만 하는 경우는, element 가 대상이 되는 객체에 들어있는지를 테스트하고 열거하기위한 잘 정의된 프로토콜을 지원하는 객체를 의미합니다[2]. 모든 스몰토크의 컬렉션은 isEmpty 와 occurrencesOf: 을 포함한 테스팅 메시지를 사용할 수 있습니다. 또한 모든 컬렉션은 열거 메시지 do:, select:, reject: (select: 의 반대되는 것), collect:(Lisp 의 map 과 같은), detect:ifNone:, inject:into: (왼쪽 fold를 수행하는)과 더 많은 메시지를 사용할 수 있습니다. 이런 프로토콜의 범용성과 다양성은 컬렉션을 강력하게 만들어주는 특징입니다.


그림 9.3을 통해 컬렉션 계층의 대다수 클래스들이 지원하는 표준 프로토콜을 정리했습니다. 이 메서드들은 Collection 을 상속받은 서브클래스 내에서 정의(define), 재 정의(redefine), 최적화(optimized) 도 가능하지만, 가끔 (서브클래스를 통한)사용이 금지되기도 합니다.


기본적인 일관성을 넘어선, 다양한 프로토콜들을 지원하거나 같은 요청에 다른동작을 제공하는 다수의 다른 컬렉션이 있습니다. 이제부터 중요한 몇가지 차이점들에 대해 알아보도록 하겠습니다:


  • 순차가능(Sequenceable): SequenceableCollection 의 모든 서브 클래스의 인스턴스는, first 요소로부터 시작되어, last 요소까지 명확하게 정해진 순서로 진행됩니다(sequenceable). 반대되는 경우로서, Set, Bag, Dictionary 의 인스턴스는 순서대로 배치할 수 없습니다.
  • 분류가능(Sortable): SortedCollection 은 해당 요소들을 정렬 순서에 따라 유지합니다.
  • 색인가능(Indexable): 대부분의 sequenceable 콜렉션은 index 를 생성할 수 있으며, at: 을 이용해서 요소를 검색할 수 있습니다. Array 는 고정된 크기를 가진 친숙한 indexable 데이터 구조이며, anArray at: n 은 anArray 의 n번째(nth) 요소를 검색하고, anArray at: n put: v 는 n번째의 요소의 값을 v 로 바꿉니다. LinkedLists 와 SkipLists 은 sequenceable 이지만, indexable 은 아닙니다. 즉 first 와 last 에는 반응할 수 있습니다만, at: 메서드는 이해하지 못합니다.
  • Keyed: Dictionary 와 그 서브클래스의 인스턴스는, 색인 대신에 키(keys) 로 참조할 수 있습니다.
  • 수정가능(Mutable): 대부분의 컬렉션들은 변경이 가능하지만, Intervals 와 Symbols 는 그렇지 않습니다. Interval 은 정수의 범위를 나타내는 컬렉션으로서 수정이 불가능합니다. 예를 들어 5 to: 16 by: 2 는 5, 7, 9, 11, 13 과 15 라는 구성요소를 포함하고 있는 Interval 이 됩니다. 이런것들(Interval 또는 Symbols)은 at: 을 사용하면 색인이 가능하지만, at:put: 을 사용해서 값을 변경할 수는 없습니다.
  • 성장가능(Growable): Interval 이나 Array 의 인스턴스는 항상 고정된 크기를 가지게 됩니다. 다른 종류의 컬렉션(sorted collection, ordered collection, 그리고 linked list)은 일단 생성된 이후에 크기가 커질 수 있습니다. OrderedCollection 클래스는 배열보다 범용적이며, OrderedCollection 은 동적으로 크기가 커질 수 있고, at: 과 at:put: 은 물론이고 더 쓸모있는 addFirst: 와 addLast: 등의 메서드도 가지고 있습니다.
  • 중복 허용(Accepts duplicates): Set 컬렉션은 중복된 요소를 걸러내지만, Bag 은 그런작업을 하지는 않습니다. Dictionary, Set 그리고 Bag 은 요소의 중복을 판단할때 각 요소에서 제공되는 =(equal) 메서드를 사용합니다; 이런 클래스의 Identity 등과 같은 변종은 두개의 인자(파라메터)가 같은 객체인가를 테스트하는 ==(double equal) 을 사용하며, Pluggable 같은 변종은 컬렉션의 생성시에 주어진 임의의 동치관계(메서드)를 사용합니다.
  • 혼합가능(Heterogeneous): 대부분의 컬렉션들은 요소가 어떤 종류라 하더라도 수용이 가능합니다. 하지만, String, CharacterArray 또는 Symbol 은 Chracter 만을 수용할 수 있습니다. Array 는 여러가지 객체를 수용할 수 있지만, ByteArray 는 오직 Bytes 만 수용하며, IntergerArray 는 오직 Integer 를 수용하고, FloatArray 는 오직 Floats 만을 수용합니다. LinkedList 는 Link ▷ accessing protocol 을 준수하는 요소만 수용가능한 제약을 가집니다..


Notes

  1. 대괄호에 있는 표현식은 익명의 함수 _x.x gpa < threshold 를 정의하는 표현식으로서 간주될 수 있습니다.
  2. c++의 경우는 iterator 가 이와 비슷합니다.