SqueakByExample:4.3: Difference between revisions
Onionmixer (talk | contribs) (번역수정) |
Onionmixer (talk | contribs) (번역수정) |
||
Line 89: | Line 89: | ||
|} | |} | ||
'''Example.''' 연습으로 하나의 단항 메시지와 하나의 키워드, 하나의 이항 메시지(그림 4.5 참조)로 구성된 Pen new go: 100 + 20 의 처리과정을 분석해 보겠습니다. | |||
{| style="border: 1px solid white;" | {| style="border: 1px solid white;" | ||
Line 94: | Line 97: | ||
|[[image:uKeyBinPar_01.png]]||[[image:uunKeyBin.png]] | |[[image:uKeyBinPar_01.png]]||[[image:uunKeyBin.png]] | ||
|- style="text-align: center;" | |- style="text-align: center;" | ||
|그림 4.4: 이항 메시지가 키워드 메시지보다 | |그림 4.4: 이항 메시지가 키워드 메시지보다 우선적으로 전달 되었습니다.||그림 4.5: Pen new go: 100 + 20 구문의 분해 | ||
|} | |} | ||
Line 105: | Line 105: | ||
<center>{{HighlightDoubleBox| | <center>{{HighlightDoubleBox| | ||
Rule Two. 괄호로 묶인 메시지는 다른 메시지 보다 먼저 | Rule Two. 괄호로 묶인 메시지는 다른 메시지 보다 먼저 전달됩니다.<br> | ||
(메시지)> 단항 메시지>이항 메시지>키워드 메시지 | (메시지)> 단항 메시지>이항 메시지>키워드 메시지 | ||
}}</center> | }}</center> | ||
Line 111: | Line 111: | ||
<syntaxhighlight lang="smalltalk"> | <syntaxhighlight lang="smalltalk"> | ||
1.5 tan rounded asString = (((1.5 tan) rounded) asString) ⇒ true " | 1.5 tan rounded asString = (((1.5 tan) rounded) asString) ⇒ true "여기에는 괄호가 필요하지 않습니다" | ||
3 + 4 factorial ⇒ 27 "( | 3 + 4 factorial ⇒ 27 "(5040이 아닙니다)" | ||
(3 + 4) factorial ⇒ 5040 | (3 + 4) factorial ⇒ 5040 | ||
</syntaxhighlight> | </syntaxhighlight> | ||
여기서 | 여기서 play 이전에 '''lowMajorScaleOn:'''을 강제로 보내려면 괄호가 필요합니다. | ||
<syntaxhighlight lang="smalltalk"> | <syntaxhighlight lang="smalltalk"> | ||
(FMSound lowMajorScaleOn: FMSound clarinet) play | (FMSound lowMajorScaleOn: FMSound clarinet) play | ||
"(1) | "(1) 클라리넷 소리를 만들기 위해 clarinet 메시지를 FMSound 클래스에 보냅니다. | ||
(2) | (2) FMSound에 인자로 보낸 소리를 lowMajorScaleOn: 키워드 메시지로 보냅니다. | ||
(3) 결과 소리를 재생합니다." | |||
(3) | |||
</syntaxhighlight> | </syntaxhighlight> | ||
'''Exmaple.''' (65@325 extent: 134 @ 100) center 라는 메시지는 상단 왼쪽 꼭지점이 (65,325)이며 그 크기가 134x100인 직사각형의 중심을 반환합니다. 예 4.3은 어떻게 메시지가 분해되며 전달되는지를 보여줍니다. 먼저 괄호 사이에 있는 메시지를 보냅니다. 여기에는 먼저 보내어 포인트 정보를 돌려 받을 (65@325)(1번) 와 134 X 100(2번) 두 개의 이항 메시지가 있으며, 그 다음에 134 X 100 의 정보를 보내고 사각형 정보를 돌려 받을 extent:(3번) 키워드 메시지가 있습니다. 마지막으로 단항 메시지 center는 직사각형에 보내지며(4번), 점 정보를 돌려 받습니다. 100 이라는 오브젝트는 center라는 메세지를 이해하지 못하기때문에 괄호없이 메시지를 처리하면 오류가 발생합니다 | |||
{| style="font-weight: bold; border: 1px solid black; background-color:#BBBBBB;" | {| style="font-weight: bold; border: 1px solid black; background-color:#BBBBBB;" | ||
Line 135: | Line 135: | ||
| || colspan= "3"|(65 @ 325 extent: 134 @ 100) center|| | | || colspan= "3"|(65 @ 325 extent: 134 @ 100) center|| | ||
|- | |- | ||
|( | |(1번)||65@325 || || ||''"binary"'' | ||
|- | |- | ||
| ||⇒ aPoint|| || || | | ||⇒ aPoint|| || || | ||
|- | |- | ||
|( | |(2번)|| || ||134@100 ||''"binary"'' | ||
|- | |- | ||
| || || ||⇒ anotherPoint|| | | || || ||⇒ anotherPoint|| | ||
|- | |- | ||
|( | |(3번)|| colspan="3"|aPoint extent: anotherPoint||''"keyword"'' | ||
|- | |- | ||
| ||⇒ aRectangle|| || || | | ||⇒ aRectangle|| || || | ||
|- | |- | ||
|( | |(4번)|| colspan="3"|aRectangle center||''"unary"'' | ||
|- | |- | ||
| ||⇒ 132@375|| || || | | ||⇒ 132@375|| || || | ||
|} | |} | ||
===왼쪽에서 오른쪽으로=== | ===왼쪽에서 오른쪽으로=== |
Revision as of 10:23, 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 | "그 다음 키워드 메시지가 전달됩니다" |
Example. 연습으로 하나의 단항 메시지와 하나의 키워드, 하나의 이항 메시지(그림 4.5 참조)로 구성된 Pen new go: 100 + 20 의 처리과정을 분석해 보겠습니다.
그림 4.4: 이항 메시지가 키워드 메시지보다 우선적으로 전달 되었습니다. | 그림 4.5: Pen new go: 100 + 20 구문의 분해 |
괄호 우선
Rule Two. 괄호로 묶인 메시지는 다른 메시지 보다 먼저 전달됩니다.
(메시지)> 단항 메시지>이항 메시지>키워드 메시지
1.5 tan rounded asString = (((1.5 tan) rounded) asString) ⇒ true "여기에는 괄호가 필요하지 않습니다"
3 + 4 factorial ⇒ 27 "(5040이 아닙니다)"
(3 + 4) factorial ⇒ 5040
여기서 play 이전에 lowMajorScaleOn:을 강제로 보내려면 괄호가 필요합니다.
(FMSound lowMajorScaleOn: FMSound clarinet) play
"(1) 클라리넷 소리를 만들기 위해 clarinet 메시지를 FMSound 클래스에 보냅니다.
(2) FMSound에 인자로 보낸 소리를 lowMajorScaleOn: 키워드 메시지로 보냅니다.
(3) 결과 소리를 재생합니다."
Exmaple. (65@325 extent: 134 @ 100) center 라는 메시지는 상단 왼쪽 꼭지점이 (65,325)이며 그 크기가 134x100인 직사각형의 중심을 반환합니다. 예 4.3은 어떻게 메시지가 분해되며 전달되는지를 보여줍니다. 먼저 괄호 사이에 있는 메시지를 보냅니다. 여기에는 먼저 보내어 포인트 정보를 돌려 받을 (65@325)(1번) 와 134 X 100(2번) 두 개의 이항 메시지가 있으며, 그 다음에 134 X 100 의 정보를 보내고 사각형 정보를 돌려 받을 extent:(3번) 키워드 메시지가 있습니다. 마지막으로 단항 메시지 center는 직사각형에 보내지며(4번), 점 정보를 돌려 받습니다. 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