SqueakByExample:9.4

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

주요 클래스에 대한 예제

지금부터 일반적이거나 중료한 컬렉션 클래스를 이용한 간단한 예제를 제시할 것입니다. 컬렉션의 주요 프로토콜들은 -구성요소에 접근하기 위한 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 에서 찾아보실 수 있습니다.