SqueakByExample:9.4: Difference between revisions

From 흡혈양파의 번역工房
Jump to navigation Jump to search
(스타일 수정)
(번역수정)
 
(5 intermediate revisions by the same user not shown)
Line 1: Line 1:
==Key 클래스들의 예==
==주요 클래스에 대한 예제==


우리는 단순한 코드 견본들을 사용하여 가장 일반적이거나 또는 중요한 컬렉션을 제시할 것입니다. 컬렉션들의 중요한 프로토콜들은 –구성요소에 접근하기 위한 at:, at:put:있으며, -구성요소들을 추가하거나 제거하기 위한 add:, remove:가 있고, -컬렉션들에 관한 몇몇 정보를 얻기 위한 size, isEmpty, include:가 있으며, -컬렉션을 반복적용(iterate)하기 위한 do:, collect:, select:가 있습니다. 각 컬렉션은 실행을 할 수 있거나 또는 이러한 프로토콜들을 사용하지 않을 수 있으며, 어떤 작업을 실행할 때에는 컬렉션들의 의미론(semantics)에 맞게 해독합니다. 우리는 여러분이 특정 프로토콜들과 좀더 진보된 프로토콜(advanced protocols)들을 식별하기 위해 클래스 자체들을 검색하실 것을 권장합니다.
지금부터 일반적이거나 중료한 컬렉션 클래스를 이용한 간단한 예제를 제시할 것입니다. 컬렉션의 주요 프로토콜들은 -구성요소에 접근하기 위한 at:, at:put: 있으며, -구성요소를 추가하거나 제거하기 위한 add:, remove:가 있고, -컬렉션에서 몇가지 정보를 얻기 위한 size, isEmpty, include: 가 있으며, -컬렉션의 반복을 위한 do:, collect:, select:가 있습니다. 각 컬렉션은 이런 프로토콜들을 실행하거나 실행하지 않을 수 있으며, 실행하는 경우에는 컬렉션의 의미에 맞게 프로토콜은 해석됩니다. 특정 프로토콜 및 좀 더 고급의 프로토콜을 식별하고싶다면 클래스 자체를 탐색하는것이 좀더 좋은 방법입니다.


우리는 가장 일반적인 컬렉션 클래스들인 OrderedCollection,Set, SortedCollection, Dictionary, Interval과 Array에 집중할 것입니다.  
여기서는 가장 일반적인 컬렉션 클래스들인 OrderedCollection, Set, SortedCollection, Dictionary, Interval 과 Array 를 집중적으로 살펴보겠습니다.




'''일반 생성 프로토콜(Common creation protocol) '''컬렉션들의 인스턴스들을 만드는 여러가지 방법이 있습니다. 가장 포괄적인 방법은 new:와 with:를 사용하는 것입니다. new: anInteger는, 구성요소들이 nil 값이 되는 anInteger인 크기(size)의 컬렉션을 만듭니다.  
'''일반 생성 프로토콜(Common creation protocol)''' 컬렉션의 인스턴스를 만드는 데에는 몇가지 방법이 있습니다. new: 와 with: 를 사용하는 것이 가장 일반적인 방법입니다. new: anInteger 는, 크기가 anInteger 이며 모든 요소가 nil 컬렉션을 만듭니다. with: anObject 는 컬렉션을 만들고, 만들어진 컬렉션에 anObject 를 추가합니다. 다른 컬렉션들은 이런 동작을 다르게 인식할 것입니다.
with:anObject는 컬렉션(collection)을 만들고 anObject를 만들어진 컬렉션에 추가합니다. 다른 컬렉션들은 동작을 다르게 인식할 것입니다.  
 
 
사용자는 초기 요소를 가지는 콜렉션을 만들기 위해 with:, with:with: 등의 메서드를 사용할 수 있습니다. 최대 6 개의 요소를 지정할 수 있습니다.


여러분은 메소드 with:, with:with: 등을 사용하여 초기 구성요소들과 함께, 여섯 개의 구성요소까지 컬렉션들을 만드실 수 있을 것입니다.
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
Array with: 1    ⇒    #(1)
Array with: 1    ⇒    #(1)
Line 20: Line 21:




여러분은 또한 어떤 종류의 모든 구성요소들을 다른 종류의 구성요소에 추가하기 위해 '''addAll:'''사용하실 수 있습니다.  
또한 어느 콜렉션의 모든 요소를 다른 종류의 콜렉션에 모두 추가하려면 addAll: 을 사용할 수 있습니다.
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
(1 to: 5) asOrderedCollection addAll: '678'; yourself    ⇒    an OrderedCollection(1 2 3 4 5 $6 $7 $8)
(1 to: 5) asOrderedCollection addAll: '678'; yourself    ⇒    an OrderedCollection(1 2 3 4 5 $6 $7 $8)
Line 26: Line 28:




'''addAll:''' 또한 그 자체의 인수를 리턴하지만 수신자(the receiver)를 리턴하지 않는다는 사실에 주의합니다.
'''addAll:''' 그 자체의 인수를 반환합니다만, 수신자를 반환하지는 않는다는것에 주의해주세요.
 
또한 많은 컬렉션에서 withAll: 또는 newFrom: 을 이용하여 만들수도 있습니다.


여러분은 또한 withAll: 또는 newFrom:으로 많은 컬렉션들을 만들 수 있습니다.
{| class="wikitable" style="border: 1px solid black;"
{| class="wikitable" style="border: 1px solid black;"
|-
|-
Line 45: Line 48:




이 두 개의 메소드들은 동일하지 않습니다. 특별히, Dictionary class»newFrom:는 associations의 컬렉션을 기대하는 반면에, Dictionary class»withAll:는 값들의 컬렉션(collection)으로서 그 자체 인수를 해독합니다.  
{| class="wikitable" style="border: 1px solid black;"
|-
|Array newFrom: #(7 3 1 3)||⇒ #(7 3 1 3)
|-
|OrderedCollection newFrom: #(7 3 1 3)||⇒ an OrderedCollection(7 3 1 3)
|-
|SortedCollection newFrom: #(7 3 1 3)||⇒ a SortedCollection(1 3 3 7)
|-
|Set newFrom: #(7 3 1 3)||⇒ a Set(7 1 3)
|-
|Bag newFrom: #(7 3 1 3)||⇒ a Bag(7 1 3 3)
|-
|Dictionary newFrom: {1 --> 7. 2 --> 3. 3 --> 1. 4 --> 3}||⇒ a Dictionary(1-->7 2-->3 3-->1 4-->3 )
|-
|Dictionary withAll: #(7 3 1 3)||⇒  a Dictionary(1-->7 2-->3 3-->1 4-->3 )
|}
 
 
이 두 개의 메서드들(withAll 과 newFrom:)은 같지 않다는 것에 주의해 주세요.  
 
Dictionary class>>newFrom: 은 인수로 관련된(비슷한) 컬렉션을 요구하지만, 이와는 다르게 Dictionary class>>withAll: 은 인수를 값(value)의 컬렉션으로 해석합니다.
 
 


===배열(Array)===
===배열===


배열(Array), 정수 인덱스들(integer indicies)에 의해 접근할 수 있는 고정된 크기의 컬렉션(fixed-sized collection)입니다. C 관례(Convention)와는 반대로, 스몰토크 배열(Smalltalk array)의 첫 번째 구성요소는 위치(position) 1에 있으며 0에 있지 않습니다. 배열 구성요소들(array elements)에 접근하기 위한 메인 프로토콜은 메소드 at:과 at:put:입니다. at:anInteger는 인덱스 anInteger에서 구성요소를 리턴합니다. at:anInteger put: anObject는 anObject를 인덱스 anInteger에 집어넣습니다. 배열들(Arrays)은 고정된 크기의 컬렉션들이므로, 우리는 배열의 끝부분에서 추가나 제거를 시행할 수 없습니다. 다음 코드는 크기 5의 배열을 만들어, 첫 번째 3 위치들(positions)에 값들을 집어넣고 첫 번째 구성요소를 리턴합니다.
Array(배열), 고정 크기 컬렉션으로서 정수의 첨자(Integer indices)접근할 수 있습니다. C 언어의 관례와는 반대로, 스몰토크 배열의 첫 번째 구성요소는 1 번 위치에 있으며 0 번 위치에서 시작하지 않습니다. 메서드 at: 과 at:put: 은 배열의 구성요소에 접근하기 위한 메인 프로토콜 입니다. at: anInteger 는 anInteger 의 내용이 의미하는 index 내 위치의 요소를 반환합니다. at: anInteger put: anObject 는 anObject 를 anInteger 에 해당하는 index 에 집어넣습니다. 배열은 고정된 크기의 컬렉션이므로, 사용자는 배열의 끝부분에서 추가나 제거를 진행할 수 없습니다. 다음 코드는 5 의 크기를 가지는 배열을 만들어, 처음부터 세번째까지 3 개의 요소에 값들을 집어넣고 index 의 첫번째 요소(index 1)를 반환합니다.


<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
Line 60: Line 85:




클래스 배열(the class Array)의 인스턴스를 만들기 위한 여러가지 방법이 있습니다. 작업을 위해 우리는 new:, with:와 constructs #( ){ }사용할 수 있습니다.  
Array 클래스의 인스턴스를 만드는데에는 몇가지 방법이 있습니다. 인스턴스를 만드는 작업을 위해서 new:, with:, 그리고 #( ) 구문과 { } 구문등을 사용할 수 있습니다.


'''Creation with new''': new: anInteger는 anInteger 크기의 배열을 만듭니다. 배열(Array) new: 5는 크기 5의 배열을 만듭니다. 


'''new: 를 이용한 배열의 생성''' new: anInteger 는 anInteger 크기의 배열을 만듭니다. Array new: 5 는 크기 5 의 배열을 만듭니다.
'''with 를 이용한 배열의 생성''' with: 메서드는 배열내 요소들의 값을 인수로 사용할 수 있습니다. 아래의 코드는 숫자 4, 분수 3/2 그리고 문자열 'lulu' 로 구성된 3 개의 요소를 가지는 배열을 생성합니다.


'''Creation with with''': with: 메소드는 구성요소들의 값을 지정할 수 있게 해드립니다. 다음 코드는 숫자 4, 분수 3/2 그리고 문자열 ‘lulu’ 로 구성된 3 개의 구성요소들의 배열을 만듭니다.
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
Array with: 4 with: 3/2 with: 'lulu'    ⇒    {4 . (3/2) . 'lulu'}
Array with: 4 with: 3/2 with: 'lulu'    ⇒    {4 . (3/2) . 'lulu'}
Line 71: Line 98:




'''#( )로 리터럴 만들기''': #()는 표현식이 컴파일 될 때, 그리고 그 표현식이 실행되지 않을 때, 열려져만 할 static(또는 “literal”) 구성요소들로 리터럴 배열들(literal arrays)을 만듭니다. 다음 코드는 첫 번째 구성요소가 (리터럴) 숫자1이고 두 번째 (리터럴) 문자열 ‘here’인 위치에 크기 2의 배열을 만듭니다.  
'''#() 로 리터럴 생성.''' #() 문법은 정적<sup>static</sup>인(또는 "literal") 요소를 가지는 리터럴 배열을 생성하는데, 이 정적<sup>static</sup> 이라고 하는 특성은 요소의 값이 실행시점이 아닌 컴파일되었을때 이미 값을 가지고있어야 한다는 의미를 가집니다. 아래의 코드에서, 첫 번째 구성요소가 (literal) 숫자 1 이고 두 번째 요소는 (literal) 문자열 'here' 가 되는 크기 2 의 배열을 생성합니다.
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
#(1 'here') size    ⇒    2
#(1 'here') size    ⇒    2
Line 77: Line 105:




이제, 만약 여러분이 #(1+2)를 평가하셨다면, 단일 구성요소 3과 함께 배열(array)을 얻게 되지 않으며, 대신 예컨데, 3 개의 구성요소: 1, 심볼 #+ 그리고 숫자2 와 함께 배열 #(1#+2)를 얻게 됩니다.
이제, 만약 #(1+2) 를 처리하셨다면, 3 이라는 숫자값을 요소로 가지는 배열을 얻는것이 아니라, 대신 3 개의 구성요소: 숫자 1, 심볼 #+ 그리고 숫자2 의 3개 요소를 가지는 #(1 #+ 2) 라는 배열을 얻게됩니다.
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
#(1+2)    ⇒    #(1 #+ 2)
#(1+2)    ⇒    #(1 #+ 2)
Line 83: Line 112:




이와 같은 현상이 발생하는 이유는 construct #()컴파일러로 하여금, 배열에 포함된 표현식을 그대로 해독하도록 만들기 때문입니다. 표현식은 스캔되며 결과 구성요소들은 새로운 배열에 보내집니다. 리터럴 배열(Literal arrays)는 숫자들, nil, true, false, 심볼(symbols) 그리고 문자열을 포함합니다.  
이런 결과가 발생하는 이유는 #() 구문이 컴파일러로 하여금, 배열에 포함된 표현식을 그대로(literal로) 해석하도록 지시하기 때문입니다. 인수로 주어지는 표현식은 조사되며 결과적으로 요소들은 새로운 배열로 수용됩니다. 리터럴 배열은 숫자, nil, true, false, symbol 그리고 문자열<sup>string</sup>을 포함합니다.




'''{ }로 동적 배열 만들기.''' 마지막으로 여러분은 contruct {}를 사용하여 동적 배열(dynamic array)을 만들 수 있습니다. { a . b } 는 : a with: b를 가진 배열의 등가물입니다. 특별히 {and}로 둘러싸인 표현식이 실행되었다는 의미 이기도 합니다.  
'''{ }로 동적 배열 만들기.''' 마지막으로 알아볼 {} 문법을 이용해서 동적배열을 만들 수 있습니다. { a . b } 는 : Array with: a with: b 와 같은 의미가 됩니다. 그리고 특수한경우 { 기호와 } 기호로 둘러쌓인 표현식을 실행한다는 의미도 됩니다.
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
{ 1 + 2 }    ⇒    #(3)
{ 1 + 2 }    ⇒    #(3)
Line 94: Line 124:




'''구성요소 접근.''' 모든 순차가능(sequenceable) 컬렉션들의 구성요소들은 at: 과 at:put:으로 접근될 수 있습니다. .
'''요소 접근(Element Access).''' 모든 순차가능 컬렉션들의 요소들은 at: 과 at:put: 으로 접근이 가능합니다.
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
anArray := #(1 2 3 4 5 6) copy.
anArray := #(1 2 3 4 5 6) copy.
Line 103: Line 134:




리터럴 배열(literal arrays)을 수정하는 코드를 다룰때 주의하십시오. 컴파일러는 리터럴 배열들을 위해 스페이스 할당을 한번 시도합니다. 여러분이 배열을 복사하지 않는 한, 두 번째 코드를 평가하면 여러분의 “리터럴” 배열은 아마도 기대한 값을 갖고 있지 않을 수 있습니다. (복제를 하지 않았다면, 두 번째 시간에는, 리터럴 #(1 2 3 4 5 6)은 실제로 #(1 2 33 4 5 6)!)이 될 것입니다. 동적 배열들은 문제를 갖고 있지 않습니다.  
리터럴 배열을 수정하는 코드를 다룰 때 주의하십시오. 컴파일러는 리터럴 배열에 대해 공간할당을 한번만 진행합니다. 사용자가 배열을 복사하지 않는 한, 두 번째 코드를 평가하면 "리터럴" 배열은 예상하는 값을 가지고 있지 않을 수 있습니다. (객체복사를 하지 않았다면, 두 번째 단계에서, 리터럴 #(1 2 3 4 5 6) 은 실제로 #(1 2 33 4 5 6) 의 값을 가지게 됩니다!) 동적 배열들은 이런 문제를 갖고 있지 않습니다.
 




===OrderedCollection===
===OrderedCollection===


OrderedCollection은 성장할 수 있는 컬렉션들 중의 하나이며, 이 컬렉션에 구성요소들은 순차적으로 추가될 수 있습니다. 이 컬렉션은 add:, addFirst:. addList:, 그리고 addAll: 등과 같은 다양한 메소드를 제공합니다:
OrderedCollection 은 크기변경이 가능한 컬렉션들 중의 하나이며, 이 컬렉션에서 요소는 순차적으로 추가할 수 있습니다. 이 컬렉션은 add:, addFirst:. addList:, 그리고 addAll: 등과 같은 다양한 메서드를 제공합니다:
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
ordCol := OrderedCollection new.
ordCol := OrderedCollection new.
Line 116: Line 149:




'''구성요소들 제거하기.''' 메소드 remove: anObject는 컬렉션으로부터 오브젝트의 첫 번째 occurrence를 제거합니다. 만약 컬렉션이 이러한 오브젝트를 포함하고 있지 않다면, 에러를 발생시킵니다.  
'''요소의 제거(Removing Elements).''' 메서드 remove: anObject 는 컬렉션내의 요소중 anObject 와 일치하는걸 찾은후 첫번째 결과에 해난하는 요소를 제거합니다. 만약 컬렉션에 이러한 객체(anObject)가 포함되어 있지 않다면, 에러를 발생시킵니다.
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
ordCol add: 'Monticello'.
ordCol add: 'Monticello'.
Line 124: Line 158:




제거되야 할 구성요소가 컬렉션에 있지 않을 때, 실행된 두 번째 인수 블록(second argument block)으로서 지정을 할 수 있도록 해드리는 remove:ifAbsent라 작명된 remove:의 변수가 있습니다.  
remove:ifAbsent: 라는 remove: 의 변형메서드가 있는데, 이 remove:ifAbsent: 메서드의 두번째 인수에는 삭제하려고 시도한 요소가 콜렉션에 없는경우의 동작을 블록으로 넣을 수 있습니다.
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
res := ordCol remove: 'zork' ifAbsent: [33].
res := ordCol remove: 'zork' ifAbsent: [33].
Line 131: Line 166:




'''변환(Conversion)''' 메시지 asOrderedCollection을 발송함으로써, 배열(Array) 또는 다른 컬렉션으로부터 OrderedCollection을 얻는 것이 가능합니다.
'''변환(Conversion)''' asOrderedCollection 이라는 메시지를 을 발송함으로써, 배열 또는 다른 컬렉션으로부터 OrderedCollection 을 얻어내는 것이 가능합니다.
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
#(1 2 3) asOrderedCollection    ⇒    an OrderedCollection(1 2 3)
#(1 2 3) asOrderedCollection    ⇒    an OrderedCollection(1 2 3)
Line 138: Line 174:




===인터벌(Interval)===


클래스 인터벌(the class Interval)은 숫자의 범위들을 나타냅니다. 예를 들면, 숫자 1에서 100까지의 인터벌은 다음과 같이 정의됩니다.  
===Interval===
 
Interval 이라는 클래스는 숫자의 범위를 제공합니다. 예를 들면, 숫자 1 에서 100 까지의 인터벌은 다음과 같이 정의됩니다.  
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
Interval from: 1 to: 100    ⇒    (1 to: 100)
Interval from: 1 to: 100    ⇒    (1 to: 100)
Line 146: Line 184:




인터벌의 printString은 클래서 번호(class Number)가 인터벌(intervals)을 만들기 위해 to:라고 지칭되는 편리한 메소드(a convenience method) 제공한다는 것을 드러냅니다:
인터벌 객체의 printString 결과를 보면, Number 클래스에 to: 라고 하는 편리한 메서드가 있고 이것을 사용해서 Interval 객체를 생성할 수 있다는걸 알 수 있습니다.
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
(Interval from: 1 to: 100) = (1 to: 100)    ⇒    true
(Interval from: 1 to: 100) = (1 to: 100)    ⇒    true
Line 152: Line 191:




우리는 다음과 같이 2 개의 숫자들 사이의 단계를 지정하기 위해 인터벌 클래스(Interval class) »from:to:by: 또는 Number»to:by:를 사용할 수 있습니다.  
다음과 같이 2 개의 숫자들 사이의 단계를 지정하기 위해 Interval Class>>from:to:by: 또는 Number>>to:by: 를 사용하는것도 가능합니다.  
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
(Interval from: 1 to: 100 by: 0.5) size    ⇒    199
(Interval from: 1 to: 100 by: 0.5) size    ⇒    199
Line 160: Line 200:




===딕셔너리(Dictionary)===


딕셔너리는 키(keys)를 사용하여 그 구성요소들에 접근할 수 있 수 있는 중요한 컬렉션 입니다. 딕셔너리의 가장 일반적을 사용되는 메시지중, 여러분은 at:,at:put:, at:ifAbsent:, keys와 values가 있습니다.  
===Dictionary===
 
Dictionary 는 키(keys)를 사용해서 요소에 접근하는 중요한 컬렉션 입니다. Dictionary 에서 가장 일반적으로 사용되는 메시지는 at:, at:put:, at:ifAbsent:, 그리고 keys 와 values 가 있습니다.
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
colors := Dictionary new.
colors := Dictionary new.
Line 174: Line 216:




딕셔너리들은 동등성으로(equality) 키들(keys)을 비교합니다. 만약 =를 사용하여 비교할 때, true가 리턴되면 2 개의 키는 동등한 것으로 간주됩니다. 버그를 찾아내는 작업에 있어 일반적인 어려움은 딕셔너리의 = 메소드가 재정의되었지만 딕셔너리의 hash 메소드가 아닌 오브젝트를 키로서 사용하는 것입니다. 두 메소드 모두 오브젝트들을 비교할 때 딕셔너리의 실행에서 사용됩니다.
Dictionary 는 키를 비교하는것으로 동일성을 검사합니다. 만약 = 를 사용하여 비교할 때, true 가 리턴되면 2 개의 키는 동일한 것으로 간주합니다.
찾기힘든 버그중 제일 많이 일어나는 상황은, Key 로서 사용되는 객체에 = 메서드를 재정의했지만, hash 메서드를 재정의하지 않는 경우입니다.
 
Dictionary 클래스는 콜렉션 계층이 서브클래스<sup>subclass</sup>에 기초하며 서브타이핑<sup>subtyping</sup> 은 아니라는것을 명확하게 보여줍니다. 심지어 Dictionary 가 Set 의 서브클래스 입니다만, 일반적으로 Dictionary 를 Set 와 같이 사용하려고 하지는 않습니다. Dictionary 는 -> 메시지를 이용해서 만들어진 key-value 연관성<sup>associations</sup>의 세트로 구성된것이 분명합니다. 그렇기때문에 Dictionary 는 연관성을 가지는 콜렉션으로부터 만들어질 수도 있으며, Dictionary 를 연관성을 가지는 배열로 변환할 수고 있습니다.


클래스 Dictionary는 명확하게 컬렉션 계층도(the collection hierarchy)가 subclassing에 기초되어 있고 subtyping에 기초되어 있지 않다는 것을 묘사합니다. 심지어 Dictionary가 세트(Set)의 서브 클래스 일지라도, 우리는 보통 세트(Set) 사용이 기대되는 위치에 Dictionary를 사용하는 것을 원하지 않을 것입니다. 그럼에도 불구하고, Dictionary의 실행시, Dictionary는 메시지-->를 사용하여 만들어진 associations(key value)의 세트로 구성된 것으로서 명확하게 보일 수 있습니다. 우리는 associations의 컬렉션으로부터 Dictionary를 만들 수 있거나 또는 dictionary를 associations의 배열로 변환할 수 있을 것입니다.
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
colors := Dictionary newFrom: { #blue-->Color blue. #red-->Color red. #yellow-->Color yellow }.
colors := Dictionary newFrom: { #blue-->Color blue. #red-->Color red. #yellow-->Color yellow }.
Line 184: Line 228:




'''IdentityDictionary.''' Dictionary 가 2개의 키가 동일한지를 결정하기 위해 메시지 =와 hash의 결과를 사용하는 반면에, 클래스 IdentityDictionary는 그것의 값들 대신에, 키(key)의 identity(메시지==)를 사용합니다. 예컨데 IdentityDictionary는 2 개의 키가 동일한 오브젝트일 경우만, 동일한 것으로 고려합니다.  
'''IdentityDictionary.''' Dictionary 에서 2 개의 키가 동일한지를 판단하기 위해 메시지 = 와 hash 의 결과를 사용하는 반면에, 클래스 IdentityDictionary 는 이런 값들 대신에, 키의 identity(메시지==)를 사용합니다. IdentityDictionary 는 2 개의 키가 동일한 객체일 경우만, 동일한 것으로 판단합니다.
 
Symbol 들은 자주 Key 로서 사용됩니다만, 이런경우 IdentityDictionary 를 사용하는 것은 자연스러운 일이며, 왜냐하면 Symbol 은 global 에서 고유하게 보증되기 때문입니다. 한편, Key 가 String 인 경우라면, Dictionary 클래스를 그대로 사용하는 것이 좋습니다. 그렇게 하지 않는다면 작업에서 문제가 생기겠지요:


종종 심볼들(Symbols)은 IdentityDictionary를 사용하는 것이 자연스러운 사례에서만 키들(Keys)로 사용되며, 그 이유는 심볼은 광범위하게 고유한(globally unique)한 것으로 보증되기 때문입니다. 한편, 만약 여러분의 키가 문자열(Strings)이라면, 있는 그대로의 Dictionary를 사용하는 것이 좋습니다. 그렇지 않으면 여러분은 작업에 많은 어려움을 겪으실 것입니다:
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
a := 'foobar'.
a := 'foobar'.
Line 198: Line 243:




a와 b는 다른 오브젝트이기 때문에, 다른 오브젝트로서 취급됩니다. 흥미롭게도, 리터럴 ‘foobar’는 단지 한번만 할당되므로, a와 실제로 동일한 오브젝트입니다. 여러분은 이와 같은 동작에 기초한 여러분의 코드를 원하시지는 않을 것입니다. 순수한 Dictionary는 ‘foobar’에 동등한 모든 Key를 위해 동일한 값을 제공해 드릴 수 있을 것입니다.  
위의 예에서 a 와 b 는 다른 객체이기 때문에, 다른 객체로서 취급됩니다. 흥미로운 부분이 있는데, 리터럴 'foobar' 는 단지 한번만 할당되므로, a 와 실제로 동일한 객체가 됩니다. 대부분 이런 명확하지 않는 동작에 의존하는 코드를 만들려고 싶어하지는 않겠죠! 일반적으로 Dictionary는 'foobar' 와 같은 Key 에 대해서는 동일한 값을 반환합니다.  


IdentityDictionary를 위한 키(keys)로서 광범위하게 고유한(globally unique) 오브젝트들을(Symbols또는 SmallIntegers와 같이) 그리고 순수한 Dictionary(plain Dictionary)를 위한 키로서 문자열들(Strings)을 사용합니다.
IdentityDictionary Key 로서는 global 하게 고유한 객채(Symbols 또는 SmallIntegers 등)만을 사용해주시길 바라며, String (또는 다른 객체)은 일반적으로 Dictionary 의 Key 로서 사용해주세요..
 
global 변수인 '''Smalltalk''' 는 '''IdentityDictionary''' 의 서브클래스인, '''SystemDictionary''' 의 인스턴스인것에 주의해주시길 바라며, 이런 이유때문에 모든 Key 는 Symbol(실제로는 8 비트 문자밖에 가질 수 없는 ByteSymbol 입니다) 이 됩니다.


global '''smalltalk'''는 '''IdentityDictionary'''의 서브클래스인, '''SystemDictionary'''의 인스턴스인것에 주목합시다. 그러므로 모든 그것의 키들(Keys)은 심볼들(Symbols)입니다. (실제로 ByteSymbols이며 이것은 오직 8비트 문자들만을 포함하고 있습니다)
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
Smalltalk keys collect: [ :each | each class ]    ⇒    a Set(ByteSymbol)
Smalltalk keys collect: [ :each | each class ]    ⇒    a Set(ByteSymbol)
Line 208: Line 254:




Dictionary에 키들과 값들을 보내는 작업은 Set를 결과로 내놓게되며 우리는 다음에 이것을 대상으로 살펴볼것입니다.
keys 또는 values 메시지를 Dictionary 에 보내면 결과는 Set 가 됩니다만, Set 클래스에 대해서는 이제부터 다시 설명하도록 하겠습니다.
 




===Set===
===Set===


클래스 Set는 예컨대 중복된 구성요소들이 없는 컬렉션이며 어떤 순서를 갖고 있지 않은 수학적 세트(mathematical set)와 같이 작동하는 컬렉션입니다. Set에서 구성요소들은 메시지 add:를 사용하여 추가되며, 메시지 at:을 사용하여 접근될 수 없습니다. Set에 집어넣은 오브젝트들은 반드시 메소드 hash와 =를 실행해야만 합니다.
Set 클래스는, 수학에서 말하는 집합처럼 작동하는 컬렉션이며, 중복요소를 가지지 않고, 요소간에 순서를 가지지 않습니다. Set 에 요소를 추가하려면 add: 메시지를 이용하지만, at: 메시지를 이용해서 요소에 접근하는건 불가능합니다. Set 에 집어넣어진 객체들은, 메서드 hash 와 메서드 = 을 가지고 있어야 합니다.
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
s := Set new.
s := Set new.
Line 221: Line 269:




여러분은 또한 Set class»newFrom: 또는 변환 메시지 Collection»asSet:를 사용하여 sets를 만드실 수 있습니다.  
Set 을 만들때에는 Set class>>newFrom: 또는 변환 메시지 Collection>>asSet: 를 사용하면 됩니다.  
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
(Set newFrom: #( 1 2 3 1 4 )) = #(1 2 3 4 3 2 1) asSet    ⇒    true
(Set newFrom: #( 1 2 3 1 4 )) = #(1 2 3 4 3 2 1) asSet    ⇒    true
Line 227: Line 276:




asSet 은 우리에게 컬렉션으로부터 중복된 사본들을 제거하는 편리한 방법을 제공합니다.  
컬렉션으로부터 중복된 사본들을 제거하는 편리한 방법으로서 asSet 을 사용할 수 있습니다.
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
{ Color black. Color white. (Color red + Color blue + Color green) } asSet size    ⇒    2
{ Color black. Color white. (Color red + Color blue + Color green) } asSet size    ⇒    2
</syntaxhighlight>
</syntaxhighlight>
red + blue + green = white인 것에 주의해 주십시오.


red + blue + green = white 가 되는것에 주의해 주세요.
Bag은 중복된 것들을 허용한다는 것을 제외하면 Set 와 매우 비슷합니다:


Bag은 중복된 것들을 허용한다는 것을 제외하면 Set와 매우 유사합니다:
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
{ Color black. Color white. (Color red + Color blue + Color green) } asBag size    ⇒    3
{ Color black. Color white. (Color red + Color blue + Color green) } asBag size    ⇒    3
Line 240: Line 292:




Set 연산들인 union, intersection 그리고 membership test는 컬렉션 메시지 union:, intersection: 그리고 includes:.에 의해 실행됩니다. 수신자(the receiver)는 Set로 먼저 변환되었으므로, 이 연산들은 모든 종류의 컬렉션들을 위해 작동됩니다!
Set 연산들인 union, intersection 그리고 membership test 는 컬렉션 메시지 union:, intersection: 그리고 includes:. 에 의해 실행됩니다. 수신자는 Set로 먼저 변환되므로, 이 연산들은 모든 종류의 컬렉션들을 위해 작동됩니다!
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
(1 to: 6) union: (4 to: 10)    ⇒    a Set(1 2 3 4 5 6 7 8 9 10)
(1 to: 6) union: (4 to: 10)    ⇒    a Set(1 2 3 4 5 6 7 8 9 10)
Line 248: Line 301:




우리가 아래에 설명드린 것처럼, set의 구성요소들에 iterators(섹션 9.5를 보십시오)를 사용하여 접근할 수 있습니다.  
이후에 설명하겠습니다만, Set 의 각 요소는 iterators(9.5장 참조) 를 사용해서 접근할 수 있습니다.
 


===SortedCollection===
===SortedCollection===


OrderedCollection과는 반대로, SortedCollection은 그 자체의 구성요소들을 분류 순서로 유지합니다. 디폴트로 분류된 컬렉션은 분류 순서를 만들기 위해 <=사용하므로, 비교 오브젝트들(<, =, >, >=, between:and:...)의 프로토콜을 정의하는 (8장을 보십시오)추상 클래스 매그니티튜드(Magnitude)의 서브클래스들이 가진 인스턴스들을 분류할 수 있습니다.
OrderedCollection 과는 반대로, SortedCollection 은 보유하고있는 요소들의 정렬순서를 유지합니다. 기본적으로 SortedCollection 은 정렬 순서를 정하는 작업에 = 메시지를 사용하므로, 비교 객체들(<, =, >, >=, between:and:...)의 프로토콜을 정의하는 (8장을 보십시오)추상 클래스 Magnitude의 서브클래스의 인스턴스들을 정렬할 수 있습니다.
 
SortedCollection 을 만들기 위해서는, 새로운 인스턴스를 만들고 요소들을 그 인스턴스에 추가하면 됩니다.


여러분은 새로운 인스턴스를 만들고 구성요소들을 그 인스턴스에 추가함으로써 SortedCollection을 만들 수 있습니다.
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
SortedCollection new add: 5; add: 2; add: 50; add: --10; yourself.    ⇒    aSortedCollection(--10 2 5 50)
SortedCollection new add: 5; add: 2; add: 50; add: -10; yourself.    ⇒    aSortedCollection(-10 2 5 50)
</syntaxhighlight>
</syntaxhighlight>




좀더 보편적으로, 유저는 변환 메시지 (the conversion message asSortedCollection)를 현존하는 컬렉션(existing collection)에 발송할 수 있습니다.
좀 더 일반적인 경우를 보자면, 사용자가 asSortedCollection 이라는 변환메시지를 현존하는 컬렉션에 전송하는 방법도 있습니다.
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
#(5 2 50 --10) asSortedCollection    ⇒    a SortedCollection(--10 2 5 50)
#(5 2 50 --10) asSortedCollection    ⇒    a SortedCollection(-10 2 5 50)
</syntaxhighlight>
</syntaxhighlight>




아래의 예제는 다음 FAQ(질답)에 대한 답변이 될 수 있습니다:
다음 FAQ(질답)에 대한 답변으로는 아래의 예제가 답이 될거같군요:
 
<center>{{HighlightDoubleBox|
<center>{{HighlightDoubleBox|
FAQ: How do you sort a collection?<br>
FAQ: collection 의 내부를 어떻게 정렬하나요?<br>
ANSWER: Send the message asSortedCollection to it.
ANSWER: asSortedCollection 메시지를 전송하면 됩니다.
}}</center>
}}</center>
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
'hello' asSortedCollection    ⇒    a SortedCollection($e $h $l $l $o)
'hello' asSortedCollection    ⇒    a SortedCollection($e $h $l $l $o)
Line 276: Line 334:




이 결과(result)로부터 여러분은 어떻게 문자열(String)을 다시 얻을 수 있을까요 불행하게도 asString은 우리가 원하지 않았던 pringString representation을 리턴합니다.
위의 예제로부터 정렬을 진행한 결과를 String 으로 되돌리기 위해서는 어떻게 하면 좋을까요? 불행하게도 asString 이 반환하는 printString 은 우리 예상대로 되지는 않습니다.
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
hello' asSortedCollection asString    ⇒    'a SortedCollection($e $h $l $l $o)'
hello' asSortedCollection asString    ⇒    'a SortedCollection($e $h $l $l $o)'
Line 282: Line 341:
   
   


정확한 답은 String class»newFrom:, String class»withAll: 또는 Object»as::를 사용하는 것입니다.
위의 내용에 대한 정확한 답은 String class>>newFrom:, String class>>withAll: 또는 Object>>as: 등을 사용하는게 되겠습니다.
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
'hello' asSortedCollection as: String                  ⇒    'ehllo'
'hello' asSortedCollection as: String                  ⇒    'ehllo'
Line 290: Line 350:




모두 비교 가능한 만큼 오랫동안 SortedCollection에서 모든 다양한 구성요소들을 갖는 것이 가능합니다. 예를 들면, 우리는 정수(integers), 플로트(floats)분수(fractions)들과 같은 다양한 종류의 숫자들을 섞을 있습니다:
모든 요소가 서로 비교가 가능하다는 전제하에, SortedCollection 은 다른종류의 요소를 가지는게 가능합니다. 예를들어 정수(integers), 부동소수점수(floats), 분수(fractions) 같은 비교가능한 다양한 종류의 숫자들을 요소로 가질 있다는 의미입니다.
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
{ 5. 2/--3. 5.21 } asSortedCollection    ⇒    a SortedCollection((--2/3) 5 5.21)
{ 5. 2/-3. 5.21 } asSortedCollection    ⇒    a SortedCollection((-2/3) 5 5.21)
</syntaxhighlight>
</syntaxhighlight>




메소드<=를 정의하지 않는 오브젝트들을 분류(sort)하기 원하거나 또는 다른 분류 기준(sorting criterion)을 갖기를 원한다고 상상해 보십시오. 여러분은 작업을 sortblock이라 불리는 두 개의 인수 블록을 분류된 컬렉션에 공급함으로써 수행할 수 있습니다. 예를 들면 클래스 Color는 매그니튜드(Magnitude)가 아니고 메소드 <=를 실행하지 않지만, 우리는 colors가 그것들의 luminance(휘도)에 따라 분류될 것을 진술하는 블록을 지정할 수 있습니다.
메서드 <= 를 정의하지 않고있는 객체들을 정렬하려하거나, <= 이외의 다른 기준으로 정렬을 하려고 한다고 생각해 보도록 하겠습니다. 사용자는 경우 sortblock 이라고 불리는 2 개로 내부가 나뉜 상태로 구성된 블록을 전달하는것으로 정렬은 가능해집니다. 예를들면 Color 클래스는 Magnitude 가 아니고 <= 메서드를 가지고 있습니다만, 아래처럼 sortblock 을 지정하는것으로, 색에 대한 값을 명도(밝기에 대한 기준)에 의해서 정렬할 수 있습니다.
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
col := SortedCollection sortBlock: [:c1 :c2 | c1 luminance <= c2 luminance].
col := SortedCollection sortBlock: [:c1 :c2 | c1 luminance <= c2 luminance].
Line 305: Line 367:




===문자열(String)===
===String===
 
스몰토크 에서 String(문자열)은 Chracter 의 컬렉션으로 표현됩니다. 이렇게 되어있는 컬렉션은 순차가능<sup>sequenceable</sup>, 색인가능<sup>indexable</sup>, 수정가능<sup>mutable</sup> 그리고 혼합가능<sup>homogeneous</sup> 하며 같은종류의 요소, 즉 Chracter 의 인스턴스만 가질 수 있습니다. String 은 일반적으로 String 리터럴을 '(single quote)로 둘러싸는것으로 생성하며, Array 처럼 String 은 전용 문법을 가지고 있습니다만, 일반적인 컬렉션 메서드도 잘 작동합니다.


스몰토크 문자열은 문자의 컬렉션을 나타냅니다. 이것은 오직 문자 인스턴스(Character instances)만을 포함하는 순차가능(sequenceable), 색인가능(indexable), 수정가능(mutable) 그리고 혼합(homogeneous)입니다. 배열처럼, 문자열은 전용 신텍스(dedicated syntax)를 갖고 있으며, 보통 작은 따옴표내부에 문자열 리터럴(String literal)을 직접 지정하여 만들어지지만, 평상시의 컬렉션 생성 메소드 또한 작동할 것입니다.
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
'Hello'    ⇒    'Hello'
'Hello'    ⇒    'Hello'
Line 316: Line 379:




실제로, 문자열은 추상적입니다. 우리가 문자열(String)예를 들어 설명할 때, 우리는 실제로 8-bit ByteString 또는 32-bit WideString을 얻는 것입니다. 우리는 이러한 것들을 단순하게 하기 위해, 보통 차이점을 무시하고 문자열의 인스턴스들에 관해서만 이야기 합니다.
사실, String 은 추상클래스입니다. String 을 인스턴스화 하는경우 실제로 얻는것은 8-bit ByteString 또는 32-bit WideString 입니다. 설명을 간단하게 하기위해서, 이런 차이는 무시하고 String 의 인스턴스에 관해서만 알아보도록 하겠습니다.
 
String 형태의 2 개의 인스턴스는 ,(comma-쉼표)로 연결될 수 있습니다.  


문자열의 2 개의 인스턴스들은 콤마로 연결될 수 있습니다.
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
s := 'no', ' ', 'worries'.
s := 'no', ' ', 'worries'.
Line 325: Line 389:




문자열은 변할 수 있는 컬렉션(mutable collection)이기 때문에, 우리는 메소드 at:put:을 사용하여 그것을 변경할 수 있습니다.
String 은 수정가능<sup>mutable</sup>한 컬렉션이기 때문에, 사용자는 메서드 at:put: 을 사용하여 내용을 변경할 수 있습니다.
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
s at: 4 put: $h; at: 5 put: $u.
s at: 4 put: $h; at: 5 put: $u.
Line 332: Line 397:




콤마 메소드(the comma method)가 컬렉션에 의해 정의되므로, 모든 종류의 컬렉션에 동작된다는 것을 기억해 주십시오!
쉼표 메서드는 Collection 에서 정의되어 있기 때문에, 모든 종류의 컬렉션에 대해서 동작이 가능하다는 것을 주의해 주십시오!
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
(1 to: 3) , '45'    ⇒    #(1 2 3 $4 $5)
(1 to: 3) , '45'    ⇒    #(1 2 3 $4 $5)
Line 338: Line 404:




우리는 또한 아래에 보이는 것 처럼 replaceAll:with: 또는 replaceFrom:to:with:를 사용하여 현존하는 문자열(string)을 수정할 수 있습니다. 여러 개의 문자들과 인터벌은 동일한 크기 이어야 한다는 사실을 유념해 주십시오.
아래의 예제에서 볼 수 있듯이, 이미 존재하는 문자열을 replaceAll:with: 또는 replaceFrom:to:with: 등을 사용해서 변경하는것도 가능합니다. 인수로 주어지는 문자수와 지정하는 간격의 길이가 같아야 하는것에(replaceFrom의 경우) 주의해주세요<ref name="역자주1">일본어버전의 Pharo by example 보면 같지 않은경우 에러가 발생한다고 되어 있습니다.</ref>.
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
s replaceAll: $n with: $N.
s replaceAll: $n with: $N.
Line 347: Line 414:




위에 기술된 메소드들과는 반대로 메소드 copyReplaceAll:새로운 문자열을 만듭니다. (신기하게도, 여기의 인수들은 개별적 문자라기 보다는 서브문자열(substrings)이며 그 크기는 동일할 필요가 없습니다)
위에서 언급된 메서드들과는 다르게도, copyReplaceAll: 메서드는 새로운 문자열을 생성합니다.(신기하게도 이 메서드의 인수는 개별의 문자보다는 부분문자열로 취급되기 때문에 크기가 같아야할 필요는 없습니다)


<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
Line 353: Line 420:
</syntaxhighlight>
</syntaxhighlight>


A quick look at the implementation of these methods reveals that they are defined not only for Strings, but for any kind of SequenceableCollection, so the following also works:\


methods 의 구현내용을 훑어보면 이것들은 단지 Strings 로 정의 ( define ) 되었을뿐만 아니라 어떤 종류의 SequenceableCollection 으로 정의 된것을 나타낸다. 따라서 이하의 내용도 동작하게 됩니다.
메서드의 구현내용을 살펴보면, 사실 String 전용으로 정의된것이 아니고 어떤 종류의 SequenceableCollection 에서도 사용이 가능하다는것을 알 수 있습니다. 따라서 아래의 내용도 동작하게 되는거죠.
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
(1 to: 6) copyReplaceAll: (3 to: 5) with: { 'three'. 'etc.' }    ⇒    #(1 2 'three' 'etc.' 6)
(1 to: 6) copyReplaceAll: (3 to: 5) with: { 'three'. 'etc.' }    ⇒    #(1 2 'three' 'etc.' 6)
Line 361: Line 428:




'''문자열 매칭(String matching)''' match: 메시지를 발송함으로써 패턴(pattern)이 문자열(string)매치되는 지의 여부를 요청하는(ask) 작업이 가능합니다. 패턴은 문자들의 임의의 시리즈들을 매치 하기 위해 *를 지정합니다. match:는 패턴으로 전송되었으며 문자열은 매치되지 않게 됩니다.
'''String Matching.''' 메시지 match: 발송함으로써 패턴이 String 매치되는지의 여부를 요청하는 작업이 가능합니다. 패턴에서 *(asterisk) 기호는 임의의 길이를 의미하며, #(sharp) 기호는 임의의 1 개문자를 의미합니다. match: 는 패턴에서 문자열을 받을는 경우로 사용하며 문자열에 패턴을 보내는 상황에 사용되는건 아니라는걸 주의해 주세요.
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
'Linux *' match: 'Linux mag'    ⇒    true
'Linux *' match: 'Linux mag'    ⇒    true
Line 368: Line 436:




다른 유용한 메소드는 findString:입니다.
다른 유용한 메서드로는 findString: 입니다.
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
'GNU/Linux mag' findString: 'Linux'                                                    ⇒    5
'GNU/Linux mag' findString: 'Linux'                                                    ⇒    5
Line 375: Line 444:




Perl의 능력을 제공하는 좀더 진보된 패턴 매칭 기구들(facilities) 또한 사용이 가능하지만, 표준 이미지(the standard image)에 포함되어 있지 않습니다.<ref name="주석9-4">우리는 Vassili Bykov의 레귤러 표현식 패키지를 강력하게 추천합니다.여러분은 패키지를 http://www.squeaksource.com/Regex.html.에서 찾아보실 수 있습니다.</ref>
Perl 수준의 좀더 진보된 패턴 매칭 도구도 사용이 가능합니다만, 표준 이미지에 포함되어 있지는 않습니다.<ref name="주석9-4">우리는 Vassili Bykov의 정규 표현식 패키지를 강력하게 추천합니다. 이 패키지는 http://www.squeaksource.com/Regex.html 에서 찾아보실 수 있습니다.</ref>




'''문자열에서 몇 가지 테스트를 시행하기''' 다음 예시들은 문자열 뿐만 아니라 좀더 보편적으로 컬렉션들에서 정의되는 메시지들인 isEmpty, includes: 와 anySatisfy의 용례를 묘사하였습니다.
'''String 에 대한 테스트.'''  
 
아래의 예제들은 String 뿐만 아니라 다른 일반적인 컬렉션들에서도 정의되고있는 isEmpty, includes: 와 anySatisfy: 등의 메시지를 string 에 사용했을때의 동작을 보여줍니다.
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
'Hello' isEmpty    ⇒    false
'Hello' isEmpty    ⇒    false
Line 387: Line 459:




'''문자열 템플레이팅(String templating)''' 문자열 템플레이팅을 관리하는 유용한 format:, expandMacros 그리고 expandMacrosWith:와 같은 3개의 메시지들이 있습니다.  
'''String templating.''' String templating 을 관리하는데 유용한 format:, expandMacros 그리고 expandMacrosWith: 와 같은 3 개의 메시지들이 있습니다.  
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
'{1} is {2}' format: {'Squeak' . 'cool'}    ⇒    'Squeak is cool'
'{1} is {2}' format: {'Squeak' . 'cool'}    ⇒    'Squeak is cool'
Line 393: Line 466:




expandMacros family의 메시지들은 캐리지 리턴(carriage return)을 위해 <n>을 사용한 변수 교체를 제공하며, 도표작성(tabulation)을 위해 <t>를 리턴하고 인수들을(<1p>, <2p>, 작은 따옴표로 문자열을 둘러싸고) 위해 <1s>, <2s>, <3s>를 리턴하고, 조건문(conditional)을 위해 <1?value1:value2>를 리턴합니다.  
expandMacros 계열의 메시지들은 캐리지 리턴을 위해 <n> 을 사용한 변수 교체를 제공하며, 도표작성을 위해 <t> 를 반환하고 인수들을(<1p>, <2p>, 작은 따옴표로 문자열을 둘러싸서) 위해 <1s>, <2s>, <3s> 를 반환하고, 조건문을 위해 <1?value1:value2> 를 반환하는것등을 지원합니다.  
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
'look--<t>--here' expandMacros                                    ⇒    'look-- --here'
'look-<t>-here' expandMacros                                    ⇒    'look- -here'
'<1s> is <2s>' expandMacrosWith: 'Squeak' with: 'cool'    ⇒    'Squeak is cool'
'<1s> is <2s>' expandMacrosWith: 'Squeak' with: 'cool'    ⇒    'Squeak is cool'
'<2s> is <1s>' expandMacrosWith: 'Squeak' with: 'cool'    ⇒    'cool is Squeak'
'<2s> is <1s>' expandMacrosWith: 'Squeak' with: 'cool'    ⇒    'cool is Squeak'
Line 404: Line 478:




'''몇 가지 다른 유틸리티 메소드''' 클래스 문자열은 메시지 asLowercase, asUppercase 와 capitalized를 포함한 여러 개의 다른 유틸리티를 제공합니다.
'''그외 유틸리티 메서드''' String 클래스는 메시지 asLowercase, asUppercase 와 capitalized 를 포함한 여러 개의 다른 유틸리티를 제공합니다.
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
'XYZ' asLowercase    ⇒    'xyz'
'XYZ' asLowercase    ⇒    'xyz'
Line 414: Line 489:




메시지 printString을 발송하여 오브젝트에게 그 자체의 문자열 표현(string representation)을 요청하는 작업과 메시지 asString을 문자열로 변환시키는 작업에는 일반적으로 차이점이 있다는 것에 주의하십시오. 여기에 그 차이의 예시가 있습니다.  
printString 메시지를 발송하여 객체에게 보유한 문자열 표현을 요청하는 작업과, asString 메시지를 이용해서 문자열로 변환하는 작업에는 일반적으로 차이점이 있다는 것에 주의하십시오. 여기에 그 차이에 대한 예제가 있습니다.
 
<syntaxhighlight lang="smalltalk">
<syntaxhighlight lang="smalltalk">
#ASymbol printString    ⇒    '#ASymbol'
#ASymbol printString    ⇒    '#ASymbol'
Line 421: Line 497:




심볼은 문자열과 유사하지만, 광범위한 고유성 유지가(globally unique) 보장됩니다. 이러한 이유 때문에 심볼들은 특별히 IdentityDictionary의 인스턴스인 경우에, Dictionary들을 위한 키들로서 문자열보다는 심볼이 선호됩니다. 문자열과 심볼에 관해 더 많은 내용을 원하신다면 8장을 보십시오.
Symbol 은 string 과 비슷하지만, global 에서 고유성 유지가 보장된다는것이 차이가 있습니다. 이러한 이유 때문에 Symbol 들은 특별히 IdentityDictionary 의 인스턴스인 경우, Dictionary 들을 위한 key 들로서 string 보다는 Symbol 을 더 선호하는 편입니다. string 과 symbol 에 관해 더 많은 내용을 원하신다면 8 장을 참고해주세요.
 
 


==Notes==
==Notes==

Latest revision as of 02:42, 17 September 2013

주요 클래스에 대한 예제

지금부터 일반적이거나 중료한 컬렉션 클래스를 이용한 간단한 예제를 제시할 것입니다. 컬렉션의 주요 프로토콜들은 -구성요소에 접근하기 위한 at:, at:put: 이 있으며, -구성요소를 추가하거나 제거하기 위한 add:, remove:가 있고, -컬렉션에서 몇가지 정보를 얻기 위한 size, isEmpty, include: 가 있으며, -컬렉션의 반복을 위한 do:, collect:, select:가 있습니다. 각 컬렉션은 이런 프로토콜들을 실행하거나 실행하지 않을 수 있으며, 실행하는 경우에는 컬렉션의 의미에 맞게 프로토콜은 해석됩니다. 특정 프로토콜 및 좀 더 고급의 프로토콜을 식별하고싶다면 클래스 자체를 탐색하는것이 좀더 좋은 방법입니다.

여기서는 가장 일반적인 컬렉션 클래스들인 OrderedCollection, Set, SortedCollection, Dictionary, Interval 과 Array 를 집중적으로 살펴보겠습니다.


일반 생성 프로토콜(Common creation protocol) 컬렉션의 인스턴스를 만드는 데에는 몇가지 방법이 있습니다. new: 와 with: 를 사용하는 것이 가장 일반적인 방법입니다. new: anInteger 는, 크기가 anInteger 이며 모든 요소가 nil 인 컬렉션을 만듭니다. with: anObject 는 컬렉션을 만들고, 만들어진 컬렉션에 anObject 를 추가합니다. 다른 컬렉션들은 이런 동작을 다르게 인식할 것입니다.


사용자는 초기 요소를 가지는 콜렉션을 만들기 위해 with:, with:with: 등의 메서드를 사용할 수 있습니다. 최대 6 개의 요소를 지정할 수 있습니다.

Array with: 1        #(1)
Array with: 1 with: 2        #(1 2)
Array with: 1 with: 2 with: 3        #(1 2 3)
Array with: 1 with: 2 with: 3 with: 4        #(1 2 3 4)
Array with: 1 with: 2 with: 3 with: 4 with: 5        #(1 2 3 4 5)
Array with: 1 with: 2 with: 3 with: 4 with: 5 with: 6        #(1 2 3 4 5 6)


또한 어느 콜렉션의 모든 요소를 다른 종류의 콜렉션에 모두 추가하려면 addAll: 을 사용할 수 있습니다.

(1 to: 5) asOrderedCollection addAll: '678'; yourself        an OrderedCollection(1 2 3 4 5 $6 $7 $8)


addAll: 은 그 자체의 인수를 반환합니다만, 수신자를 반환하지는 않는다는것에 주의해주세요.

또한 많은 컬렉션에서 withAll: 또는 newFrom: 을 이용하여 만들수도 있습니다.

Array withAll: #(7 3 1 3) ⇒ #(7 3 1 3)
OrderedCollection withAll: #(7 3 1 3) ⇒ an OrderedCollection(7 3 1 3)
SortedCollection withAll: #(7 3 1 3) ⇒ a SortedCollection(1 3 3 7)
Set withAll: #(7 3 1 3) ⇒ a Set(7 1 3)
Bag withAll: #(7 3 1 3) ⇒ a Bag(7 1 3 3)
Dictionary withAll: #(7 3 1 3) ⇒ a Dictionary(1-->7 2-->3 3-->1 4-->3 )


Array newFrom: #(7 3 1 3) ⇒ #(7 3 1 3)
OrderedCollection newFrom: #(7 3 1 3) ⇒ an OrderedCollection(7 3 1 3)
SortedCollection newFrom: #(7 3 1 3) ⇒ a SortedCollection(1 3 3 7)
Set newFrom: #(7 3 1 3) ⇒ a Set(7 1 3)
Bag newFrom: #(7 3 1 3) ⇒ a Bag(7 1 3 3)
Dictionary newFrom: {1 --> 7. 2 --> 3. 3 --> 1. 4 --> 3} ⇒ a Dictionary(1-->7 2-->3 3-->1 4-->3 )
Dictionary withAll: #(7 3 1 3) ⇒ a Dictionary(1-->7 2-->3 3-->1 4-->3 )


이 두 개의 메서드들(withAll 과 newFrom:)은 같지 않다는 것에 주의해 주세요.

Dictionary class>>newFrom: 은 인수로 관련된(비슷한) 컬렉션을 요구하지만, 이와는 다르게 Dictionary class>>withAll: 은 인수를 값(value)의 컬렉션으로 해석합니다.


배열

Array(배열)는, 고정 크기 컬렉션으로서 정수의 첨자(Integer indices)로 접근할 수 있습니다. C 언어의 관례와는 반대로, 스몰토크 배열의 첫 번째 구성요소는 1 번 위치에 있으며 0 번 위치에서 시작하지 않습니다. 메서드 at: 과 at:put: 은 배열의 구성요소에 접근하기 위한 메인 프로토콜 입니다. at: anInteger 는 anInteger 의 내용이 의미하는 index 내 위치의 요소를 반환합니다. at: anInteger put: anObject 는 anObject 를 anInteger 에 해당하는 index 에 집어넣습니다. 배열은 고정된 크기의 컬렉션이므로, 사용자는 배열의 끝부분에서 추가나 제거를 진행할 수 없습니다. 다음 코드는 5 의 크기를 가지는 배열을 만들어, 처음부터 세번째까지 3 개의 요소에 값들을 집어넣고 index 의 첫번째 요소(index 1)를 반환합니다.

anArray := Array new: 5.
anArray at: 1 put: 4.
anArray at: 2 put: 3/2.
anArray at: 3 put: 'ssss'.
anArray at: 1      4


Array 클래스의 인스턴스를 만드는데에는 몇가지 방법이 있습니다. 인스턴스를 만드는 작업을 위해서 new:, with:, 그리고 #( ) 구문과 { } 구문등을 사용할 수 있습니다.


new: 를 이용한 배열의 생성 new: anInteger 는 anInteger 크기의 배열을 만듭니다. Array new: 5 는 크기 5 의 배열을 만듭니다.


with 를 이용한 배열의 생성 with: 메서드는 배열내 요소들의 값을 인수로 사용할 수 있습니다. 아래의 코드는 숫자 4, 분수 3/2 그리고 문자열 'lulu' 로 구성된 3 개의 요소를 가지는 배열을 생성합니다.

Array with: 4 with: 3/2 with: 'lulu'        {4 . (3/2) . 'lulu'}


#() 로 리터럴 생성. #() 문법은 정적static인(또는 "literal") 요소를 가지는 리터럴 배열을 생성하는데, 이 정적static 이라고 하는 특성은 요소의 값이 실행시점이 아닌 컴파일되었을때 이미 값을 가지고있어야 한다는 의미를 가집니다. 아래의 코드에서, 첫 번째 구성요소가 (literal) 숫자 1 이고 두 번째 요소는 (literal) 문자열 'here' 가 되는 크기 2 의 배열을 생성합니다.

#(1 'here') size        2


이제, 만약 #(1+2) 를 처리하셨다면, 3 이라는 숫자값을 요소로 가지는 배열을 얻는것이 아니라, 대신 3 개의 구성요소: 숫자 1, 심볼 #+ 그리고 숫자2 의 3개 요소를 가지는 #(1 #+ 2) 라는 배열을 얻게됩니다.

#(1+2)        #(1 #+ 2)


이런 결과가 발생하는 이유는 #() 구문이 컴파일러로 하여금, 배열에 포함된 표현식을 그대로(literal로) 해석하도록 지시하기 때문입니다. 인수로 주어지는 표현식은 조사되며 결과적으로 요소들은 새로운 배열로 수용됩니다. 리터럴 배열은 숫자, nil, true, false, symbol 그리고 문자열string을 포함합니다.


{ }로 동적 배열 만들기. 마지막으로 알아볼 {} 문법을 이용해서 동적배열을 만들 수 있습니다. { a . b } 는 : Array with: a with: b 와 같은 의미가 됩니다. 그리고 특수한경우 { 기호와 } 기호로 둘러쌓인 표현식을 실행한다는 의미도 됩니다.

{ 1 + 2 }        #(3)
{(1/2) asFloat} at: 1        0.5
{10 atRandom . 1/3} at: 2        (1/3)


요소 접근(Element Access). 모든 순차가능 컬렉션들의 요소들은 at: 과 at:put: 으로 접근이 가능합니다.

anArray := #(1 2 3 4 5 6) copy.
anArray at: 3        3
anArray at: 3 put: 33.
anArray at: 3        33


리터럴 배열을 수정하는 코드를 다룰 때 주의하십시오. 컴파일러는 리터럴 배열에 대해 공간할당을 단 한번만 진행합니다. 사용자가 배열을 복사하지 않는 한, 두 번째 코드를 평가하면 "리터럴" 배열은 예상하는 값을 가지고 있지 않을 수 있습니다. (객체복사를 하지 않았다면, 두 번째 단계에서, 리터럴 #(1 2 3 4 5 6) 은 실제로 #(1 2 33 4 5 6) 의 값을 가지게 됩니다!) 동적 배열들은 이런 문제를 갖고 있지 않습니다.


OrderedCollection

OrderedCollection 은 크기변경이 가능한 컬렉션들 중의 하나이며, 이 컬렉션에서 요소는 순차적으로 추가할 수 있습니다. 이 컬렉션은 add:, addFirst:. addList:, 그리고 addAll: 등과 같은 다양한 메서드를 제공합니다:

ordCol := OrderedCollection new.
ordCol add: 'Seaside'; add: 'SqueakSource'; addFirst: 'Monticello'.
ordCol        an OrderedCollection('Monticello' 'Seaside' 'SqueakSource')


요소의 제거(Removing Elements). 메서드 remove: anObject 는 컬렉션내의 요소중 anObject 와 일치하는걸 찾은후 첫번째 결과에 해난하는 요소를 제거합니다. 만약 컬렉션에 이러한 객체(anObject)가 포함되어 있지 않다면, 에러를 발생시킵니다.

ordCol add: 'Monticello'.
ordCol remove: 'Monticello'.
ordCol        an OrderedCollection('Seaside' 'SqueakSource' 'Monticello')


remove:ifAbsent: 라는 remove: 의 변형메서드가 있는데, 이 remove:ifAbsent: 메서드의 두번째 인수에는 삭제하려고 시도한 요소가 콜렉션에 없는경우의 동작을 블록으로 넣을 수 있습니다.

res := ordCol remove: 'zork' ifAbsent: [33].
res        33


변환(Conversion) asOrderedCollection 이라는 메시지를 을 발송함으로써, 배열 또는 다른 컬렉션으로부터 OrderedCollection 을 얻어내는 것이 가능합니다.

#(1 2 3) asOrderedCollection        an OrderedCollection(1 2 3)
'hello' asOrderedCollection        an OrderedCollection($h $e $l $l $o)


Interval

Interval 이라는 클래스는 숫자의 범위를 제공합니다. 예를 들면, 숫자 1 에서 100 까지의 인터벌은 다음과 같이 정의됩니다.

Interval from: 1 to: 100        (1 to: 100)


이 인터벌 객체의 printString 결과를 보면, Number 클래스에 to: 라고 하는 편리한 메서드가 있고 이것을 사용해서 Interval 객체를 생성할 수 있다는걸 알 수 있습니다.

(Interval from: 1 to: 100) = (1 to: 100)        true


다음과 같이 2 개의 숫자들 사이의 단계를 지정하기 위해 Interval Class>>from:to:by: 또는 Number>>to:by: 를 사용하는것도 가능합니다.

(Interval from: 1 to: 100 by: 0.5) size        199
(1 to: 100 by: 0.5) at: 198        99.5
(1/2 to: 54/7 by: 1/3) last        (15/2)


Dictionary

Dictionary 는 키(keys)를 사용해서 요소에 접근하는 중요한 컬렉션 입니다. Dictionary 에서 가장 일반적으로 사용되는 메시지는 at:, at:put:, at:ifAbsent:, 그리고 keys 와 values 가 있습니다.

colors := Dictionary new.
colors at: #yellow put: Color yellow.
colors at: #blue put: Color blue.
colors at: #red put: Color red.
colors at: #yellow        Color yellow
colors keys        a Set(#blue #yellow #red)
colors values        {Color blue . Color yellow . Color red}


Dictionary 는 키를 비교하는것으로 동일성을 검사합니다. 만약 = 를 사용하여 비교할 때, true 가 리턴되면 2 개의 키는 동일한 것으로 간주합니다. 찾기힘든 버그중 제일 많이 일어나는 상황은, Key 로서 사용되는 객체에 = 메서드를 재정의했지만, hash 메서드를 재정의하지 않는 경우입니다.

Dictionary 클래스는 콜렉션 계층이 서브클래스subclass에 기초하며 서브타이핑subtyping 은 아니라는것을 명확하게 보여줍니다. 심지어 Dictionary 가 Set 의 서브클래스 입니다만, 일반적으로 Dictionary 를 Set 와 같이 사용하려고 하지는 않습니다. Dictionary 는 -> 메시지를 이용해서 만들어진 key-value 연관성associations의 세트로 구성된것이 분명합니다. 그렇기때문에 Dictionary 는 연관성을 가지는 콜렉션으로부터 만들어질 수도 있으며, Dictionary 를 연관성을 가지는 배열로 변환할 수고 있습니다.

colors := Dictionary newFrom: { #blue-->Color blue. #red-->Color red. #yellow-->Color yellow }.
colors removeKey: #blue.
colors associations        {#yellow-->Color yellow . #red-->Color red}


IdentityDictionary. Dictionary 에서 2 개의 키가 동일한지를 판단하기 위해 메시지 = 와 hash 의 결과를 사용하는 반면에, 클래스 IdentityDictionary 는 이런 값들 대신에, 키의 identity(메시지==)를 사용합니다. IdentityDictionary 는 2 개의 키가 동일한 객체일 경우만, 동일한 것으로 판단합니다.

Symbol 들은 자주 Key 로서 사용됩니다만, 이런경우 IdentityDictionary 를 사용하는 것은 자연스러운 일이며, 왜냐하면 Symbol 은 global 에서 고유하게 보증되기 때문입니다. 한편, Key 가 String 인 경우라면, Dictionary 클래스를 그대로 사용하는 것이 좋습니다. 그렇게 하지 않는다면 작업에서 문제가 생기겠지요:

a := 'foobar'.
b := a copy.
trouble := IdentityDictionary new.
trouble at: a put: 'a'; at: b put: 'b'.
trouble at: a        'a'
trouble at: b        'b'
trouble at: 'foobar'        'a'


위의 예에서 a 와 b 는 다른 객체이기 때문에, 다른 객체로서 취급됩니다. 흥미로운 부분이 있는데, 리터럴 'foobar' 는 단지 한번만 할당되므로, a 와 실제로 동일한 객체가 됩니다. 대부분 이런 명확하지 않는 동작에 의존하는 코드를 만들려고 싶어하지는 않겠죠! 일반적으로 Dictionary는 'foobar' 와 같은 Key 에 대해서는 동일한 값을 반환합니다.

IdentityDictionary Key 로서는 global 하게 고유한 객채(Symbols 또는 SmallIntegers 등)만을 사용해주시길 바라며, String (또는 다른 객체)은 일반적으로 Dictionary 의 Key 로서 사용해주세요..

global 변수인 SmalltalkIdentityDictionary 의 서브클래스인, SystemDictionary 의 인스턴스인것에 주의해주시길 바라며, 이런 이유때문에 모든 Key 는 Symbol(실제로는 8 비트 문자밖에 가질 수 없는 ByteSymbol 입니다) 이 됩니다.

Smalltalk keys collect: [ :each | each class ]        a Set(ByteSymbol)


keys 또는 values 메시지를 Dictionary 에 보내면 결과는 Set 가 됩니다만, Set 클래스에 대해서는 이제부터 다시 설명하도록 하겠습니다.


Set

Set 클래스는, 수학에서 말하는 집합처럼 작동하는 컬렉션이며, 중복요소를 가지지 않고, 요소간에 순서를 가지지 않습니다. Set 에 요소를 추가하려면 add: 메시지를 이용하지만, at: 메시지를 이용해서 요소에 접근하는건 불가능합니다. Set 에 집어넣어진 객체들은, 메서드 hash 와 메서드 = 을 가지고 있어야 합니다.

s := Set new.
s add: 4/2; add: 4; add:2.
s size        2


Set 을 만들때에는 Set class>>newFrom: 또는 변환 메시지 Collection>>asSet: 를 사용하면 됩니다.

(Set newFrom: #( 1 2 3 1 4 )) = #(1 2 3 4 3 2 1) asSet        true


컬렉션으로부터 중복된 사본들을 제거하는 편리한 방법으로서 asSet 을 사용할 수 있습니다.

{ Color black. Color white. (Color red + Color blue + Color green) } asSet size        2

red + blue + green = white 가 되는것에 주의해 주세요.


Bag은 중복된 것들을 허용한다는 것을 제외하면 Set 와 매우 비슷합니다:

{ Color black. Color white. (Color red + Color blue + Color green) } asBag size        3


Set 연산들인 union, intersection 그리고 membership test 는 컬렉션 메시지 union:, intersection: 그리고 includes:. 에 의해 실행됩니다. 수신자는 Set로 먼저 변환되므로, 이 연산들은 모든 종류의 컬렉션들을 위해 작동됩니다!

(1 to: 6) union: (4 to: 10)         a Set(1 2 3 4 5 6 7 8 9 10)
'hello' intersection: 'there'         'he'
#Smalltalk includes: $k               true


이후에 설명하겠습니다만, Set 의 각 요소는 iterators(9.5장 참조) 를 사용해서 접근할 수 있습니다.


SortedCollection

OrderedCollection 과는 반대로, SortedCollection 은 보유하고있는 요소들의 정렬순서를 유지합니다. 기본적으로 SortedCollection 은 정렬 순서를 정하는 작업에 = 메시지를 사용하므로, 비교 객체들(<, =, >, >=, between:and:...)의 프로토콜을 정의하는 (8장을 보십시오)추상 클래스 Magnitude의 서브클래스의 인스턴스들을 정렬할 수 있습니다.

SortedCollection 을 만들기 위해서는, 새로운 인스턴스를 만들고 요소들을 그 인스턴스에 추가하면 됩니다.

SortedCollection new add: 5; add: 2; add: 50; add: -10; yourself.        aSortedCollection(-10 2 5 50)


좀 더 일반적인 경우를 보자면, 사용자가 asSortedCollection 이라는 변환메시지를 현존하는 컬렉션에 전송하는 방법도 있습니다.

#(5 2 50 --10) asSortedCollection        a SortedCollection(-10 2 5 50)


다음 FAQ(질답)에 대한 답변으로는 아래의 예제가 답이 될거같군요:

FAQ: collection 의 내부를 어떻게 정렬하나요?
ANSWER: asSortedCollection 메시지를 전송하면 됩니다.

'hello' asSortedCollection        a SortedCollection($e $h $l $l $o)


위의 예제로부터 정렬을 진행한 결과를 String 으로 되돌리기 위해서는 어떻게 하면 좋을까요? 불행하게도 asString 이 반환하는 printString 은 우리 예상대로 되지는 않습니다.

hello' asSortedCollection asString        'a SortedCollection($e $h $l $l $o)'


위의 내용에 대한 정확한 답은 String class>>newFrom:, String class>>withAll: 또는 Object>>as: 등을 사용하는게 되겠습니다.

'hello' asSortedCollection as: String                      'ehllo'
String newFrom: ('hello' asSortedCollection)        'ehllo'
String withAll: ('hello' asSortedCollection)            'ehllo'


모든 요소가 서로 비교가 가능하다는 전제하에, SortedCollection 은 다른종류의 요소를 가지는게 가능합니다. 예를들어 정수(integers), 부동소수점수(floats), 분수(fractions) 와 같은 비교가능한 다양한 종류의 숫자들을 요소로 가질 수 있다는 의미입니다.

{ 5. 2/-3. 5.21 } asSortedCollection        a SortedCollection((-2/3) 5 5.21)


메서드 <= 를 정의하지 않고있는 객체들을 정렬하려하거나, <= 이외의 다른 기준으로 정렬을 하려고 한다고 생각해 보도록 하겠습니다. 사용자는 이 경우 sortblock 이라고 불리는 2 개로 내부가 나뉜 상태로 구성된 블록을 전달하는것으로 정렬은 가능해집니다. 예를들면 Color 클래스는 Magnitude 가 아니고 <= 메서드를 가지고 있습니다만, 아래처럼 sortblock 을 지정하는것으로, 색에 대한 값을 명도(밝기에 대한 기준)에 의해서 정렬할 수 있습니다.

col := SortedCollection sortBlock: [:c1 :c2 | c1 luminance <= c2 luminance].
col addAll: { Color red. Color yellow. Color white. Color black }.
col        a SortedCollection(Color black Color red Color yellow Color white)


String

스몰토크 에서 String(문자열)은 Chracter 의 컬렉션으로 표현됩니다. 이렇게 되어있는 컬렉션은 순차가능sequenceable, 색인가능indexable, 수정가능mutable 그리고 혼합가능homogeneous 하며 같은종류의 요소, 즉 Chracter 의 인스턴스만 가질 수 있습니다. String 은 일반적으로 String 리터럴을 '(single quote)로 둘러싸는것으로 생성하며, Array 처럼 String 은 전용 문법을 가지고 있습니다만, 일반적인 컬렉션 메서드도 잘 작동합니다.

'Hello'        'Hello'
String with: $A        'A'
String with: $h with: $i with: $!        'hi!'
String newFrom: #($h $e $l $l $o)    ⇒    'hello'


사실, String 은 추상클래스입니다. String 을 인스턴스화 하는경우 실제로 얻는것은 8-bit ByteString 또는 32-bit WideString 입니다. 설명을 간단하게 하기위해서, 이런 차이는 무시하고 String 의 인스턴스에 관해서만 알아보도록 하겠습니다.

String 형태의 2 개의 인스턴스는 ,(comma-쉼표)로 연결될 수 있습니다.

s := 'no', ' ', 'worries'.
s        'no worries'


String 은 수정가능mutable한 컬렉션이기 때문에, 사용자는 메서드 at:put: 을 사용하여 내용을 변경할 수 있습니다.

s at: 4 put: $h; at: 5 put: $u.
s        'no hurries'


쉼표 메서드는 Collection 에서 정의되어 있기 때문에, 모든 종류의 컬렉션에 대해서 동작이 가능하다는 것을 주의해 주십시오!

(1 to: 3) , '45'        #(1 2 3 $4 $5)


아래의 예제에서 볼 수 있듯이, 이미 존재하는 문자열을 replaceAll:with: 또는 replaceFrom:to:with: 등을 사용해서 변경하는것도 가능합니다. 인수로 주어지는 문자수와 지정하는 간격의 길이가 같아야 하는것에(replaceFrom의 경우) 주의해주세요[1].

s replaceAll: $n with: $N.
s        'No hurries'
s replaceFrom: 4 to: 5 with: 'wo'.
s        'No worries'


위에서 언급된 메서드들과는 다르게도, copyReplaceAll: 메서드는 새로운 문자열을 생성합니다.(신기하게도 이 메서드의 인수는 개별의 문자보다는 부분문자열로 취급되기 때문에 크기가 같아야할 필요는 없습니다)

s copyReplaceAll: 'rries' with: 'mbats'        'No wombats'


이 메서드의 구현내용을 살펴보면, 사실 String 전용으로 정의된것이 아니고 어떤 종류의 SequenceableCollection 에서도 사용이 가능하다는것을 알 수 있습니다. 따라서 아래의 내용도 동작하게 되는거죠.

(1 to: 6) copyReplaceAll: (3 to: 5) with: { 'three'. 'etc.' }        #(1 2 'three' 'etc.' 6)


String Matching. 메시지 match: 를 발송함으로써 패턴이 String 과 매치되는지의 여부를 요청하는 작업이 가능합니다. 패턴에서 *(asterisk) 기호는 임의의 길이를 의미하며, #(sharp) 기호는 임의의 1 개문자를 의미합니다. match: 는 패턴에서 문자열을 받을는 경우로 사용하며 문자열에 패턴을 보내는 상황에 사용되는건 아니라는걸 주의해 주세요.

'Linux *' match: 'Linux mag'        true
'GNU/Linux #ag' match: 'GNU/Linux tag'        true


다른 유용한 메서드로는 findString: 입니다.

'GNU/Linux mag' findString: 'Linux'                                                        5
'GNU/Linux mag' findString: 'linux' startingAt: 1 caseSensitive: false        5


Perl 수준의 좀더 진보된 패턴 매칭 도구도 사용이 가능합니다만, 표준 이미지에 포함되어 있지는 않습니다.[2]


String 에 대한 테스트.

아래의 예제들은 String 뿐만 아니라 다른 일반적인 컬렉션들에서도 정의되고있는 isEmpty, includes: 와 anySatisfy: 등의 메시지를 string 에 사용했을때의 동작을 보여줍니다.

'Hello' isEmpty        false
'Hello' includes: $a        false
'JOE' anySatisfy: [:c | c isLowercase]        false
'Joe' anySatisfy: [:c | c isLowercase]        true


String templating. String templating 을 관리하는데 유용한 format:, expandMacros 그리고 expandMacrosWith: 와 같은 3 개의 메시지들이 있습니다.

'{1} is {2}' format: {'Squeak' . 'cool'}        'Squeak is cool'


expandMacros 계열의 메시지들은 캐리지 리턴을 위해 <n> 을 사용한 변수 교체를 제공하며, 도표작성을 위해 <t> 를 반환하고 인수들을(<1p>, <2p>, 작은 따옴표로 문자열을 둘러싸서) 위해 <1s>, <2s>, <3s> 를 반환하고, 조건문을 위해 <1?value1:value2> 를 반환하는것등을 지원합니다.

'look-<t>-here' expandMacros                                        'look- -here'
'<1s> is <2s>' expandMacrosWith: 'Squeak' with: 'cool'        'Squeak is cool'
'<2s> is <1s>' expandMacrosWith: 'Squeak' with: 'cool'        'cool is Squeak'
'<1p> or <1s>' expandMacrosWith: 'Squeak' with: 'cool'        '''Squeak'' or Squeak '
'<1?Quentin:Thibaut> plays' expandMacrosWith: true        'Quentin plays'
'<1?Quentin:Thibaut> plays' expandMacrosWith: false        'Thibaut plays'


그외 유틸리티 메서드 String 클래스는 메시지 asLowercase, asUppercase 와 capitalized 를 포함한 여러 개의 다른 유틸리티를 제공합니다.

'XYZ' asLowercase        'xyz'
'xyz' asUppercase        'XYZ'
'hilaire' capitalized        'Hilaire'
'1.54' asNumber        1.54
'this sentence is without a doubt far too long' contractTo: 20        'this sent...toolong'


printString 메시지를 발송하여 객체에게 보유한 문자열 표현을 요청하는 작업과, asString 메시지를 이용해서 문자열로 변환하는 작업에는 일반적으로 차이점이 있다는 것에 주의하십시오. 여기에 그 차이에 대한 예제가 있습니다.

#ASymbol printString        '#ASymbol'
#ASymbol asString        'ASymbol'


Symbol 은 string 과 비슷하지만, global 에서 고유성 유지가 보장된다는것이 차이가 있습니다. 이러한 이유 때문에 Symbol 들은 특별히 IdentityDictionary 의 인스턴스인 경우, Dictionary 들을 위한 key 들로서 string 보다는 Symbol 을 더 선호하는 편입니다. string 과 symbol 에 관해 더 많은 내용을 원하신다면 8 장을 참고해주세요.


Notes

  1. 일본어버전의 Pharo by example 을 보면 같지 않은경우 에러가 발생한다고 되어 있습니다.
  2. 우리는 Vassili Bykov의 정규 표현식 패키지를 강력하게 추천합니다. 이 패키지는 http://www.squeaksource.com/Regex.html 에서 찾아보실 수 있습니다.