SqueakByExample:4.3: Difference between revisions
Onionmixer (talk | contribs) (번역수정) |
Onionmixer (talk | contribs) (번역수정) |
||
Line 74: | Line 74: | ||
'''Example.''' 메시지 aPen go:100 + 20 은, 바이너리 메시지 + 20 과 키워드 메시지 go: 를 가지고 있습니다. 바이너리 메시지는 키워드 메시지 전에 전달되므로, 100 + 20 이 먼저 전달됩니다. (1번): 메시지 + 20 은 오브젝트 100에 전달되며, 숫자 120을 리턴합니다. 그 다음, 메시지 aPen go: 120 에서, 120은 go: 인수로서 함께 전달됩니다(2번). 예 4.2는 메시지가 어떻게 실행되는지를 보여줍니다. | '''Example.''' 메시지 aPen go:100 + 20 은, 바이너리 메시지 + 20 과 키워드 메시지 go: 를 가지고 있습니다. 바이너리 메시지는 키워드 메시지 전에 전달되므로, 100 + 20 이 먼저 전달됩니다. (1번): 메시지 + 20 은 오브젝트 100에 전달되며, 숫자 120을 리턴합니다. 그 다음, 메시지 aPen go: 120 에서, 120은 go: 셀렉터의 인수로서 함께 전달됩니다(2번). 예 4.2는 메시지가 어떻게 실행되는지를 보여줍니다. | ||
{| style="font-weight: bold; border: 1px solid black; background-color:#BBBBBB;" | {| style="font-weight: bold; border: 1px solid black; background-color:#BBBBBB;" |
Revision as of 10:08, 4 March 2013
메시지 구성하기
3종류의 메시지는, 명쾌한 방식으로 메시지가 작성될 수 있도록 해주는 각각 다른 우선순위를 가지고 있습니다.
- 단항 메시지는 항상 먼저 전달되며, 그 다음 바이너리 메시지이고, 마지막으로 키워드 메시지가 보내집니다.
- 괄호 안에 있는 메시지는 어떤 종류의 메시지 보다 먼저 보내집니다.
- 동일한 종류의 메시지는 왼쪽에서부터 오른쪽으로 계산됩니다.
이 규칙들은 매우 자연스러운 읽기 순서로 이어집니다. 지금, 만약 여러분이, 여러분이 원하는 순서대로 메시지가 전달되기를 원한다면, 그림 4.3에서 볼수있듯이 원하는만큼 괄호들을 추가로 사용하면 됩니다. 이 그림에서, 메시지 yellow는 단항 메시지이며, 메시지 color:는 키워드 메시지이므로, 우선순위에 의해 메시지 전송식 Color yellow 가 먼저 전달됩니다. 하지만 굳이 Color yellow 주위에(필요없는) 괄호를 넣은 것은 단지 이 메세지전송식이 먼저 보내진다는것을 강조하는 의미가 있습니다. 나머지 장에서는 이 강조할 점을 설명합니다.
단항 > 바이너리 > 키워드
단항 메시지를 먼저보내고, 그 다음이 바이너리 메시지이며, 마지막으로 키워드 메시지가 전달됩니다. 또한 다른 종류의 메시지보다 단항 메시지가 더 높은 우선순위를 가지게 됩니다.
Rule One.단항 메시지가 먼저 전달되고, 그 다음이 바이너리 메시지이며, 마지막으로 키워드 메시지가 전달됩니다.
Unary > Binary > Keyword
아래의 예제에서 볼 수 있듯이, 스몰토크의 문법 규칙은 일반적으로 보내는 메시지가 자연스럽게 보여질 수 있도록 합니다:
1000 factorial / 999 factorial | ⇒ 1000 |
2 raisedTo: 1 + 3 factorial | ⇒ 128 |
안타깝게도, 보내지는 산술메시지들은 단순하게 처리되기 때문에, 바이너리 연산자들에 대한 우선순위를 원할 때마다 괄호를 넣는것이 좋습니다.
1+2*3 | ⇒ 9 |
1 + (2 * 3) | ⇒ 7 |
약간 더 복잡한 (!) 다음 예는 심지어 복잡한 스몰토크 표현식도 자연스럽게 보여질 수 있다는 것을 훌륭하게 보여줍니다:
[:aClass | aClass methodDict keys select: [:aMethod | (aClass>>aMethod) isAbstract ]]
value: Boolean ⇒ an IdentitySet(#or: #| #and: #& #ifTrue: #ifTrue:ifFalse: #ifFalse: #not #ifFalse:ifTrue:)
이제 우리가 알아보려는것은 어떤 Boolean클래스의 메서드가 추상요소인가 하는 것입니다[1]. 메서드 사전dictionary의 키를 위해, aClass 라는 인자클래스를 이 클래스의 추상메서드를 선택합니다. 그 다음, Boolean이라는 실체적인 값 에 인수 aClass 를(arugument aClass)를 바인딩합니다. 단항 메시지 isAbstract를 메서드에 보내기 전에, 클래스에서 메서드를 선택하는 >> 이항 메시지를 보내는 용도로만 쓰일 괄호가 필요합니다. 결과적으로 Boolean의 실체적 하위클래스인 True와 False로 구현한 메서드를 볼 수 있습니다.
Exmaple. 메시지 aPen color: Color yellow 메시지는, 클래스 Color로 보내지는 단항메세지와 aPen으로 보내지는 Color: 라는 키워드 메시지를 가지고 있습니다. 예 4.1을 보면 우선순위에 의해 단항 메시지가 먼저 전달되기때문에 Color yellow가 전달됩니다(1번). 이 메시지 전달식은 보신바와 같이 메시지 aPen color: aColor 의 인수로서 전달되는 color 오브젝트입니다(2번). 그림 4.3은 어떻게 메시지가 발송되는지 그림으로 보여줍니다.
예 4.1: aPen color: Color yellow의 처리 분석하기 | |||
aPen color | : Color yellow | ||
(1번) | Color yellow | "단항 메시지가 먼저 전덜되고" | |
⇒ aColor | |||
(2번) | aPen color | : aColor | "그 다음 키워드 메시지가 전달됩니다" |
Example. 메시지 aPen go:100 + 20 은, 바이너리 메시지 + 20 과 키워드 메시지 go: 를 가지고 있습니다. 바이너리 메시지는 키워드 메시지 전에 전달되므로, 100 + 20 이 먼저 전달됩니다. (1번): 메시지 + 20 은 오브젝트 100에 전달되며, 숫자 120을 리턴합니다. 그 다음, 메시지 aPen go: 120 에서, 120은 go: 셀렉터의 인수로서 함께 전달됩니다(2번). 예 4.2는 메시지가 어떻게 실행되는지를 보여줍니다.
예 4.2: aPen go: 100 + 20 분해하기 | |||
aPen go | : 100 + 20 | ||
(1번) | 100 + 20 | "이항 메시지가 먼저 전달되고" | |
⇒ 120 | |||
(2번) | aPen go | : 120 | "그 다음 키워드 메시지가 전달됩니다" |
그림 4.4: 이항 메시지가 키워드 메시지보다 빨리 전달 되었습니다. | 그림 4.5: Pen new go: 100 + 20 구문의 분해 |
Example. 연습으로서, 우리는 여러분이 한 개의 단항 메시지와 한 개의 키워드 메시지 그리고 한 개의 이항 메시지(그림 4.5를 보십시오)로 구성되어 있는 Pen new go:100+20의 계산을 분해합니다.
괄호 우선
Rule Two. 괄호로 묶인 메시지는 다른 메시지 보다 먼저 발송됩니다.
(메시지)> 단항 메시지>이항 메시지>키워드 메시지
1.5 tan rounded asString = (((1.5 tan) rounded) asString) ⇒ true "parentheses not needed here"
3 + 4 factorial ⇒ 27 "(not 5040)"
(3 + 4) factorial ⇒ 5040
여기서 우리는 실행하기 전 lowMajorScaleOn:을 강제로 보내기 전에 괄호가 필요합니다.
(FMSound lowMajorScaleOn: FMSound clarinet) play
"(1) send the message clarinet to the FMSound class to create a clarinet sound.
(2) send this sound to FMSound as argument to the lowMajorScaleOn: keyword
message.
(3) play the resulting sound."
Exmaple. 메시지 (65@325 extent: 134 @ 100) center는 상단 왼쪽 꼭지점이 (65,325)이며 그 크기가 134x100인 직사각형의 중심을 반환합니다. 예 4.3은 어떻게 메시지가 분해되며 발송되는지를 보여줍니다. 괄호안에 있는 메시지가 제일 먼저 발송됩니다: 65@325 와 134@100, 두 개의 바이너리 메시지를 포함한 괄호로 묶인 메시지가 제일 먼저 발송되며, 이어서 꼭지점들을 리턴하고, 그 다음 키워드 메시지 extent:가 발송되며, 직사각형을 반환합니다. 마지막으로 단항 메시지 center가 직사각형에 발송되며, 꼭지점이 리턴 됩니다. 괄호 없는 메시지를 분해하는 작업은 오류를 발생합니다. 그 이유는 오브젝트 100이 메시지 center를 이해하지 못하기 때문입니다.
예 4.3: 괄호 예제 | ||||
(65 @ 325 extent: 134 @ 100) center | ||||
(1) | 65@325 | "binary" | ||
⇒ aPoint | ||||
(2) | 134@100 | "binary" | ||
⇒ anotherPoint | ||||
(3) | aPoint extent: anotherPoint | "keyword" | ||
⇒ aRectangle | ||||
(4) | aRectangle center | "unary" | ||
⇒ 132@375 |
왼쪽에서 오른쪽으로
이제 우리는 다양한 종류의 메시지와 우선권이 취급되는 방식을 알게 되었습니다. 제기되어야 할 마지막 질문은, 동일한 우선권을 가진 메시지가 어떤 순서로 발송될까? 입니다. 동일한 우선권을 가진 메시지들은 왼쪽에서 오른쪽 순서로 발송됩니다. 예시 4.3에서 여러분이 두 개의 꼭지점 생성 메시지 (@)가 다른 것보다 먼저 발송되었던 것을 보셨던 것을 상기해 주십시오.
Exmaple. 메시지 보내기 Pen new down 모든 메시지는 단항 메시지이므로, 가장 왼쪽의 Pen new가 가장 먼저 발송됩니다. 이것은 그림 4.6에서 보이는 것 처럼, 두 번째 메시지 down 이 발송된 새롭게 만들어진 Pen을 리턴합니다.
그림 4.6: Pen new down 분해하기 |
산술적 비일관성
메시지 작성 규칙들은 단순하지만, 바이너리 메시지로 표현된 산술적 메시지 보내기의 실행에 있어 비일관성을 유발합니다. 여기서, 우리는 괄호가 필요한 일반적인 상황들에 대해 알아볼 것입니다.
3+4*5 | ⇒ 35 "(not 23) 왼쪽에서 오른쪽으로 이항 메시지를 보냈습니다" |
3 + (4 * 5) | ⇒ 23 |
1 + 1/3 | ⇒ (2/3) "and not 4/3" |
1 + (1/3) | ⇒ (4/3) |
1/3 + 2/3 | ⇒ (7/9) "and not 1" |
(1/3) + (2/3) | ⇒ (7/9) |
Exmaple. 메시지 보내기 20+2 * 5에서, 바이너리 메시지는 +와 * 뿐 입니다. 그럼에도 불구하고, 스몰토크에서는 연산 +와 *를 위한 특정 우선권은 존재하지 않습니다. 이것들은 단지 바이너리 메시지 이므로, *는 +에 우선권을 갖지 않습니다. 예시 4.4에서 보이듯이, 여기서는 제일 왼쪽의 +가 발송되었으며 (1) 그 다음 *가 결과에 발송되었습니다.
예시 4.4: 20+2*5 분해하기 | |
"바이너리 메시지들 사이에 우선권이 존재하지 않듯이, 제일 왼쪽의 메시지 +는 , 산술적 규칙 *가 첫 번째로 발송되어야 함에도 불구하고, 첫 번째로 평가됩니다" | |
20 + 2 * 5 | |
(1) | 20 + 2 ⇒ 22 |
(2) | 2 * 5 ⇒ 110 |
그림 4.4에서 보이듯이, 이 메시지 보내기의 결과는 30이 아니며 110입니다. 이 결과는 아마도 기대하지 못했던 것이지만, 메시지를 보내기 위해 사용된 규칙을 직접 따른 것입니다.
그림 4.7 괄호를 사용하는 등가 메시지 |
괄호사용은 스몰토크 모델의 단순성을 위해 어느 정도 들일 필요가 있는 수고입니다.
우리는 정확한 결과를 얻기 위해, 괄호를 사용해야만 합니다. 메시지에 괄호를 넣으면, 첫 번째로 평가됩니다. 그러므로 메시지 보내기 20+(2*5)는 예시 4.5에서 보이는 것과 같은 결과를 리턴합니다.
예시 4.5: 20+(2*5) 분해하기 | ||
"괄호로 싸인 메시지가 처음으로 평가되며, 그러므로 *는 정확한 동작을 유발하는 + 이전에 전송됩니다" | ||
20 + | (2 * 5) | |
(1) | (2 * 5) ⇒ 10 | |
(2) | 20 + | 10 ⇒ 30 |
스몰토크에서는 연산 +와 * 와 같은 산술 연산자는 다른 우선권을 갖지 않습니다.
+와 *는 단지 바이너리 메시지일 뿐이므로, *는 +에 대해 우선권을 갖지 않습니다.
원하는 결과를 얻기 위해 괄호를 사용합니다.
첫 번째 규칙이 바이너리 메시지와 키워드 메시지 이전에 발송된 단항 메시지는 명확한 괄호 넣기를 피한다는 진술에 유의하십시오. 표 4.8은 규칙들이 존재하지 않을 경우, 규칙들과 동등한 메시지들을 따라 메시지 보내기를 작성함을 보여줍니다.
그림 4.8: 메시지 보내기와 괄호를 넣은 등가물 | |
aPen color: Color yellow | aPen color: (Color yellow) |
aPen go: 100 + 20 | aPen go: (100 + 20) |
aPen penSize: aPen penSize + 2 | aPen penSize: ((aPen penSize) + 2) |
2 factorial +4 | 2 factorial + 4 (2 factorial) + 4 |
Notes
- ↑ 사실, 비슷한 수준으로 작성할 수 있지만 이지만 더 간단한 표현을 쓰겠습니다: Boolean methodDict select: #isAbstract thenCollect: #selector