Smalltalk 基本クラス編

# 基本クラス編
今回はおさえておくとよいSmalltalkのクラスを紹介します。SmalltalkはSystem Browserからすぐにソースコードを確認できますので、確認しながら読むとさらによいと思います。

## Number
Numberクラスは数値を扱う抽象クラスです。普段数値計算で利用する場合は、NumberクラスのサブクラスのSmalltalkInteger, LargeInteger, Floatなどが利用することが多いです。ここでは、Smalltalkの数値オブジェクトにどのようなメッセージ送れるかを見ていきます（どんな数値計算処理ができるか見ていきます）。

![Number.jpeg](https://qiita-image-store.s3.amazonaws.com/0/18287/2ccdb40e-9fb0-e152-6df0-38f7f479fa0f.jpeg)


*興味があるかたは、NumberクラスのスーパークラスにMagnitudeクラスという抽象クラスも読んでみるといいでしょう。Magnitudeクラスは数値、日付などの大きさを比較するための処理が書かれております。*

では、まずは基本文法のおさらいもしながら以下のプログラムを実行してみましょう。

```smalltalk
1 + 2. "print it. ==> 3"
```
`1` のオブジェクトに`2`という引数をもった`+`メッセージを送るプログラムです（説明すると長いですね・・・）。

次のこたえは分かりますか。

```smalltalk
1 + 2 * 3. "==> 9"
```
プログラム内に２項メッセージしかないため左優先で実行されます。

文法のおさらいはここまでにして、数値計算の一例を書いていきます。

```smalltalk
10 * 1.3. "整数と浮動小数の混在 print it ==> 13.0"
2.0 squared. "2.0の２乗 ==> 4.0"
2 raisedTo:3. "2の３乗 ==> 8"
121 negated. "符号反転 ==> -121"
-121 abs. "絶対値 ==> 121"
Float pi. "3.141592653589793"
1 sin. "単位はラジアン ==> 0.8414709848078965"
3 asFloat. "浮動小数に変換 ==> 3.0"
3 factorial. "3の階乗 ==> 6"
```

一般的な計算はできそうですね。

Smalltalkで数値計算がしたくなった人には、以下の本がおすすめ？（買っていますが、私は読めていない）。
<a href="http://www.amazon.co.jp/gp/product/1558606793/ref=as_li_ss_tl?ie=UTF8&camp=247&creative=7399&creativeASIN=1558606793&linkCode=as2&tag=ringosseed-22">Object-Oriented Implementation of Numerical Methods: An Introduction with Java & Smalltalk (The Morgan Kaufmann Series in Software Engineering and Programming)</a><img src="http://ir-jp.amazon-adsystem.com/e/ir?t=ringosseed-22&l=as2&o=9&a=1558606793" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />

## String

Smalltalkの文字列は，基本文法でも説明したようにシングルクオーテーション（'）で文字列を囲みます．以下に例を示します．

```smalltalk	
'Pharo Smalltalk'
```

シングルクオーテーションで囲むことにより文字列のオブジェクトが生成されます．シングルクオーテーション自体を文字列としたい場合は，連続で記述します．

```smalltalk
'I''am Smalltalker' "私はスモールトーカー（Smalltalkを話す人）です"
```

### 文字列の長さ

```smalltalk
'I''am Smalltalker' size "==>16"
```
16と得られました（17ではありませんね）。日本語の文字列も調べてみましょう。

```smalltalk
'すもーるとーく' size "==>7"
```
日本語も正しく長さを調べることができました。この章では，Stringクラスについて説明していますが、Pharoでは、実際に生成される文字列のオブジェクトはStringではなく、別のクラスのオブジェクトです。英語の文字列（適切な表現ではないかもしれない）と日本語の文字列のクラスについて調べてみましょう。

```smalltalk
#('I''am Smalltalker'  'すもーるとーく') do:[:v |
	Transcript show: v class; cr ].
```

```smalltalk
ByteString
WideString
```

Stringクラスは、ByteStringとWideStringの抽象クラスです。日本語のようなマルチバイトの文字列は、Pharoの内部でUnicode（ユニコード）の32ビットで扱われています。

### 文字列の検索

文字列の操作の定番、検索について説明します。一言で検索と言ってもいろいろな検索があると思います。検索文字列が含まれているのか、検索文字列の開始位置を知りたいなど、順番に説明していきます。まずは、単純に文字列が含まれているかどうかです。

```smalltalk
'<small>smalltalk</small>' includesSubString:'small'. "==>true"
'<small>smalltalk</small>' includesSubString:'strong'. "==>false"
```

文字列の開始位置を調べるには、findString:を使います。

```smalltalk
'<small>smalltalk</small>' findString:'small'. "==>2"
'<small>smalltalk</small>' findString:'strong'. "==>0"
```

この例では、smallという文字列は３つあります。２番目の文字列の開始位置を知りたい場合は、findString:startingAt:を用います。先ほどの例より開始位置２番目以降であればいいので、開始位置を３とします。

```smalltalk
'<small>smalltalk</small>' findString:'small' startingAt:3 "==>8"
```

### 文字列の置換

```smalltalk
'<small>smalltalk</small>' copyReplaceAll: 'small>' with: 'strong>'. "==><strong>smalltalk</strong> "
'<small>smalltalk</small>' copyReplaceFrom: 2 to: 6 with: 'strong'.  "==><strong>smalltalk</small> "
```

### 文字列の連結
文字列の連結は、カンマ（,）で行います。

```smalltalk
'<strong>', 'smalltalk', '</strong>'. "==><strong>smalltalk</strong> "
```

### 文字列の分割

文字列の分割は、findTokens:メッセージを送ることでできます。

```smalltalk
'apple,1,100yen' findTokens: ','. "==>an OrderedCollection('apple' '1' '100yen')"

```

### 小文字から大文字へ変換

```smalltalk
'smalltalk' asUppercase.
```

### 大文字から小文字へ変換

```smalltalk
'SMALLTALK' asLowercase.
```

### 最初の文字を大文字へ変換
Smalltalkのsは大文字です（どこかのサイトのタイトルみたい）。

```smalltalk
'smalltalk' capitalized.
```

### HTTPエンコード

```smalltalk
encodeString := 'あ' encodeForHTTP. "==>'%E3%81%82'"
encodeString unescapePercents. "==> 'あ'"
```

# Collection
Collectionクラスは要素の集合体を扱う抽象クラスです。Smalltalkには様々なCollection系クラスが存在します。Collection系クラスを覚える際には、クラスの特性とCollection系共有のメッセージを覚えるとよいでしょう。


### 順序なしCollection
### Set
Setは集合内に重複がない順序なしの集合を扱うクラスです。

```smalltalk
s := Set new.
s add: 13.
s add: 5.
s add: 5.
s size. " print it ==> 2" 
```
5を２回使い加えましたが、要素数は２と返却されています。
中身を確認しましょう。

```smalltalk
s includes: 13. "true"
s includes: 5. "true"
s includes: 1. "false"
```

`include:`は集合内に存在するかどうかを確認するメッセージです。

要素を削除するには`remove:`メッセージを使います。

```smalltalk
s remove: 5.
s size. "1"
```

### Bag
BagはSetと異なり、重複を許可した順序なしの集合を扱うクラスです[^1]。要素を追加するには`add:`メッセージを送ります。

[^1]: 中身の順序が保証されていません 

```smalltalk
b := Bag new.
b add: 13.
b add: 5.
b add: 5.
b size. "3"
```

要素を削除してみます。

```smalltalk
b remove: 5.
b size.
```

## 順序ありCollection
### Array
Arrayは配列を扱うクラスで、サイズが固定されたコレクションです。**他の言語と異なり、先頭要素を取り出す際は0ではなく1を使います。**

```smalltalk
array := #($a $b $c).
array at:1. "$a"
array first. "$a"
```

別の方法でArrayオブジェクトを作成してみます。Arrayクラスに`with:`メッセージを送って作成することが可能です。`with:with:with:with:with:`メッセージまであります。

```smalltalk
array1 := Array with:$a.
array2 := Array with:$a with:$b.
array3 := Array with:$a with:$b with:$c.
array4 := Array with:$a with:$b with:$c with:$d.
array5 := Array with:$a with:$b with:$c with:$d with:$e.
```

さらに別の方法で作成します。オブジェクトを生成する際には要素数を与えることで、要素数のサイズを持ったArrayオブジェクトが作成できます。

```smalltalk
array := Array new:6.
array at:1 put:$a.
array at:2 put:$b.
array at:3 put:$c.
array at:4 put:$d.
array at:5 put:$e.
array at:6 put:$f.
```

`at:put:`メッセージで要素の値を置き換えることが可能です。また、サイズ以外の要素を置き換えようとするとエラーとなります。


### OrderedCollection
OrderedCollectionは順序ありのサイズが可変するCollectionです。つまり自動的にサイズ拡張をしてくれます。


```smalltalk
order := OrderedCollection new.
order add:$a.
order add:$b.
order. "print it"
```

要素を削除する際には、`removeAt:`を使います。

```smalltalk
order removeAt:2.
```

ArrayオブジェクトをOrderedCollectionに変換するには`asOrderedCollection`メッセージを送ることが可能です。

```smalltalk
#($a $b $c) asOrderedCollection. "print it"
```

##キー付きCollection

### Dictionary
DictionaryはキーでアクセスするCollectionです。名前のとおり辞書の索引のように値の検索ができます。

```smalltalk
dict := Dictionary new.
dict at:$a put:1.
dict at:$b put:2.
dict at:$c put:3.
dict keys. " ==> #($a $b $c)"
dict valyes. " ==>  #(1 2 3)"
```

値を削除するには`removeKey:`を使います。

```smalltalk
dict removeKey: $b.
dict.
```

##イテレータ
Smalltalkのループ処理は他の言語のようなfor, whileに相当する`to:do:`を使っての処理はあまり行われません。イテレータ系のメッセージ（イテレートプロトコルとも言われます）を活用することで記述して、繰り返し処理をコンパクトに記述します。

### do:
`do:`は各要素に対して順番に処理を行う際に使います。引数にブロック（Block）を与えます。

例えば，配列の各要素をTranscriptに出力してみます。

```smalltalk
array := #(#a #b #c).
array do:[:v | Transcript cr; show: v].
```

### select:
`select:`はCollectionの要素の中から特定の要素を取り出す際に使います。

例えば、Collectionから奇数だけを取り出してみます。数値が奇数かどうか判断するのは"odd"を使います。

```smalltalk
col := (1 to: 10). "1から10までの要素. Intervalクラスのオブジェクト"
col select:[:v | v odd.]. "print it"
```

`select:`の引数のBlockが`true`になる要素だけを取り出すことがわかります。

### collect:
`collect:`はCollectionの各要素に対して加工する際に使います。

あまりいい例ではありませんが、配列の各要素を大文字に修正したCollectionを作成します。

```smalltalk
col := #('a' 'b' 'c'). 
col collect:[:v | v asUppercase  ]. "print it"
```

### detect:

`detect:`はCollectionの要素の中からBlock内の条件にあった要素を１つ取り出す際に使います。

```smalltalk
col := (1 to: 10). "1から10までの要素. Intervalクラスのオブジェクト"
col detect:[:v | v odd.]. "print it ==? 1"
```

### reject:

`reject:`は`select:`と逆に動作するメッセージです。条件に一致した要素を取り除いたCollectionを生成します。`reject:`の引数のBlockが`true`になる要素だけを取りのぞきます。

```smalltalk
col := (1 to: 10). "1から10までの要素. Intervalクラスのオブジェクト"
col reject:[:v | v odd.]. "print it ==>  #(2 4 6 8 10)"
```

### inject:into:
今回は説明しません。

##Collectionまとめ
Collection系クラスは多くのクラスがあります。一部だけの説明となりましたが、よろしければ参考資料を読んだりやSystem Browserで探索していみることをおすすめします。


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

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