Smalltalk基本文法編


# Smalltalk基本文法編
Smalltalkはよく「言語 + 開発環境」と言われますが、他の言語と違い少し慣れない点かもしれません。
そのため、Smalltalkを始めて学ぶ人には２つのことを分けて学ぶことをお勧めします。
1. Smalltalkの基本的な文法
2. Smalltalkの開発環境

今回はSmalltalkの基本的な文法について紹介します。Smalltalkの文法は他の言語と比べると覚えることがないので、非常に分かりやすいです。下記のプログラムの実行は[Smalltalk環境入門編](http://qiita.com/newapplesho/items/4a90c0771e15506c8484)にて紹介します。

## コメント
Smalltalkのコメントは対象のプログラムをダブルクオーテーションで囲みます。

```smalltalk
"これはコメントです. 0 notNil"
```

ダブルクオーテーションをコメントに加える場合は以下のように記述します。

```smalltalk
"このように「""」2回記述します"
```

## 文の区切り
文の区切りはピリオドです（セミコロンではないですよ）。

```smalltalk
. 
```

## 代入
値やオブジェクトの代入は`:=`（コロン，イコール）を記述します。

```smalltalk
x := 1. "変数xに1を導入"
```

## リテラル
### 数字

```smalltalk
5.
1.414.
-1.
122244567.
10e7.
2r100. "2進数 "
8r12. "8進数"
16rFF. "16進数"
```

### 文字
文字は文字の前に`$`をつけます。

```smalltalk
$i.
$b.
$m.
$-.
```

### 文字列
文字列はシングルクオーテーションで囲みます。

```smalltalk
'Smalltalk' "シングルクオーテーションで囲む"
```
「`'`」を文字列に含める場合は2回続けて書く

```smalltalk
'I''m a Smalltalker.'
```
ちなみに、文字列結合は「`,`」です。

```smalltalk
'Hello, ', 'world!'
``` 

### シンボル
シンボルはシステム内に一つしか存在しない文字列です。

```smalltalk
#apple
```

```smalltalk
#pineapple
```

### 配列
配列は#から始める括弧で表現します。配列内のオブジェクトは統一しなくてもかまいません（他のプログラミング言語を学んだ人には型をそろえる必要がないというと分かりやすいでしょうか）。

```smalltalk
#(1 2 3)
```

```smalltalk
#('alpha' 'beta' 'gammma')
```

```smalltalk
#('one' 2 'three' 4.0) "色々なオブジェクトを格納できます"
```

配列内に配列も格納可能です。

```smalltalk
#(#(1 2 ) 3) 
```

```smalltalk
#(a b c) "#(#a #b #c) と扱う"
```

### 擬変数
擬似変数は参照のみ利用できる変数（予約語）。self, super, thisContextは参照する度変化します。

* true
* false
* nil
* self
* super
* thisContext

## メッセージ式
Smalltalkは**オブジェクトにメッセージを送るというプログラムから構成**されております。
![object-message.png](https://qiita-image-store.s3.amazonaws.com/0/18287/6bb82bec-e09e-ed69-b334-09fb3ce0d4b8.png)

オブジェクトに送るメッセージには以下の３種類があります。

* 単項メッセージ(Unary Messages)
* 2項メッセージ(Binary Messages)
* キーワードメッセージ(Keyword Messages)

順番に説明していきます。

### 単項メッセージ(Unary Messages)
単項メッセージは**引数を取らないメッセージ**を言います。

```smalltalk
4 sqrt. "4の平方根"
12 i. "虚数"
3 asFloat. "浮動小数とする"
#('one' 'two' 'three') last. "配列の最後の要素を取り出す"
#(5 6 7) size. "配列の要素数を調べる"
```

### 2項メッセージ(Binary Messages)
2項メッセージは主に数学の２項演算子（２つのデータに対する演算）を表すときに多く使われます。

``` smalltalk
4 + 1. 
10 / 2. "(10/2)という分数"
5 // 3. "商"
5 \\ 3. "剰余"
1 < 2.
```

```smalltalk
'Small','talk'. "文字列を結合"
```
記号 `+, -, ,,!, /, &, =, >, ¦, <, ~, @`を組み合わせた名前をもつメッセージが特徴です。

### キーワードメッセージ(Keyword Messages)
引数を取るメッセージのうち2項メッセージ以外のメッセージ。メッセージの終わりにはコロン(:)が必ず付く。

```smalltalk
#($z $y $x) at: 3. "３番目の要素を取り出す"
11 between: 10 and: 100. "10から100の間の数ならばtrueを返す. 他の言語風に書くと 11.between(10,100)" 
#($a $b $c) at: 2 put: 'hello'. "2番目の要素をhelloに置き換える"
```

### メッセージの優先順位
Smalltalkのメッセージ式には以下のルールに基づき優先順位があります。これを覚えれば、Smalltalkのプログラム解読ができるようになります。

* 基本は左優先順
* 単項、２項、キーワードメッセージが１つの文に含まれていた場合には以下の優先順位で実行

**単項 > 2項 > キーワード**

Smalltalkは四則演算の優先順位がないため、プログラムを記述する際には注意が必要です。そのため、優先順位を付けるには括弧を付ける必要があります。   

#### メッセージの優先順位の例
メッセージの優先順位の例を示します。基本は左優先ですが、以下の場合、単項および２項メッセージが１つの文に含まれているため、`4 sqrt`の単項メッセージが先に実行されます。

![message-priority1.png](https://qiita-image-store.s3.amazonaws.com/0/18287/711b885c-9f84-8121-d386-92a4e763367b.png)

```smalltalk
3 + 4 sqrt. "実行結果は5"
```

先に`3 + 4`を実行したい場合は、括弧を記述します。
![message-priority2.png](https://qiita-image-store.s3.amazonaws.com/0/18287/cf5c92d6-6c34-aaa8-4829-eac1f8f08f42.png)

```smalltalk
(3 + 4) sqrt. "実行結果は2.6457513110645907"
```

#### メッセージの優先順位の練習問題
以下の実行順序を考えましょう。答えは[Smalltalk環境入門編](http://qiita.com/newapplesho/items/4a90c0771e15506c8484)にて紹介します。


```smalltalk
3 + 4 * 5.
```

```smalltalk
3 + 4 sqrt.
```

```smaltalk
50 + 4 sqrt between: 10 and: 100.
```


## ブロック
ブロックは、任意の時点で実行可能なプログラムの固まり、オブジェクトです。他の言語を学んだ方は

* ```function(x){x + 1}```
* ```(lambda (x) (+ x 1)) ```

のようなものと説明すると分かりやすいかもしれません。ブロックは、主に制御構造に用いられます。***任意の時点***で実行する際には、引数なし、引数ありに応じて`value`、`value:`等のメッセージを送信します。

```smalltalk
block := [:x :y | x + y]. "ブロックの生成"
block value: 1 value: 2.  "ブロック内のプログラムを引数を与えて実行"
block valueWithArguments: #(3 4)  "ブロック内のプログラムを引数を与えて実行"
```

制御構造で用いるの一例

```smalltalk
(x > 1) ifTrue:[ x := 0 ]. "xが１より大きい場合、xに0を代入する"
```

## カスケード

先頭オブジェクトに対してメッセージを連続的にメッセージ送信する際に用います。セミコロン`;` で記述します。

カスケード用いるとプログラムを短く記述できます。

```smalltalk
Transcript show: 'Hello '. 
Transcript cr. 
Transcript show: 'Squeak'.  
```

上記のプログラムをカスケードで記述した例。

```smalltalk
Transcript show: 'Hello '; 
  cr; show:'Squeak'. 
```

## リターン
リターンは、その名前の通り、値を返す時に用います。キャレット`^`で記述します。 

```smalltalk
^ 1 + 2. "1+2した値を返す" 
^ true. "trueを返す"
```

## 制御
### 条件分岐
Smalltalkの条件分岐は、`true`, `false`オブジェクトに対して`ifTrue:`、`ifFalse:`、`ifTrue:ifFalse:`などのメッセージを送ることで記述可能です。前述で説明したブロックが活躍しているところが分かります。プログラミング言語好きな方には、Smalltalkは制御構造もオブジェクトとメッセージで成り立っているところが分かり面白いところではないでしょうか。

```smalltalk
"trueにifTrue: ifFalse:メッセージを送っている例"
Float infinity > 0 
  ifTrue:[ Transcript show:'Yes!'. ] ifFalse:[ Transcript show: ' NO... ' ].
```

### 繰り返し

繰り返し処理内容もブロックで記述します。

```smalltalk
1 to: 10 by: 2 do:[:v | v ]. 
```
他の言語では `for(int i=1; i<=10; i=i+2)`と記載するforにあたるプログラムです。

他の言語のwhileに相当するメッセージもあります。`ifTrue:`、`ifFalse:`というメッセージがあるように`whileTrue:`、`whileFalse:`というメッセージもあります。**注意点としては、`whileTrue:`などを送るオブジェクトはブロックであるということです。**

```smalltalk
 | i | "一時変数"
 i := 1.
 [i < 10] whileTrue:[:v | v. i := i + 2. ].
```
 
```smalltalk
"他の言語でいう。 
 int i=1; while(i<10;){ i=i+2; }
"
```

その他には、以下のようなものもあります。

```smalltalk
3 timesRepeat:[ Transcript show:'Hello']. "ブロックのプログラムを3回繰り返す"
```

他の言語でいうイテレータも存在します。

```smalltalk
#(1 2 3) do:[:v | Transcript cr; show:v ]. "配列の要素を１つずつ取り出しブロックの引数に与え、ブロック内プログラムを実行"
```

# Smalltalkの基本文法のポイント

* 大文字小文字は区別されるので注意
* 変数名にダラーは使えない
* 擬変数には代入できない
* 算術演算の時は優先順位を注意する
* whileTrue:はブロックオブジェクトに送る
* 配列の添字は1からはじまる

# 参考
自由自在 Squeakプログラミング PDF版
http://swikis.ddo.jp/squeak/13

今日から使おうSmalltalk
http://www.slideshare.net/newapplesho/smalltalk-32627289

Pharo by Example
http://www.pharobyexample.org/