Edited at

Smalltalk 基本クラス編

More than 3 years have passed since last update.


基本クラス編

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


Number

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

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

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

1 + 2. "print it. ==> 3"

1 のオブジェクトに2という引数をもった+メッセージを送るプログラムです(説明すると長いですね・・・)。

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

1 + 2 * 3. "==> 9"

プログラム内に2項メッセージしかないため左優先で実行されます。

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

10 * 1.3. "整数と浮動小数の混在 print it ==> 13.0"

2.0 squared. "2.0の2乗 ==> 4.0"
2 raisedTo:3. "2の3乗 ==> 8"
121 negated. "符号反転 ==> -121"
-121 abs. "絶対値 ==> 121"
Float pi. "3.141592653589793"
1 sin. "単位はラジアン ==> 0.8414709848078965"
3 asFloat. "浮動小数に変換 ==> 3.0"
3 factorial. "3の階乗 ==> 6"

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

Smalltalkで数値計算がしたくなった人には、以下の本がおすすめ?(買っていますが、私は読めていない)。

Object-Oriented Implementation of Numerical Methods: An Introduction with Java & Smalltalk (The Morgan Kaufmann Series in Software Engineering and Programming)


String

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

'Pharo Smalltalk'

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

'I''am Smalltalker' "私はスモールトーカー(Smalltalkを話す人)です"


文字列の長さ

'I''am Smalltalker' size "==>16"

16と得られました(17ではありませんね)。日本語の文字列も調べてみましょう。

'すもーるとーく' size "==>7"

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

#('I''am Smalltalker'  'すもーるとーく') do:[:v |

Transcript show: v class; cr ].

ByteString

WideString

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


文字列の検索

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

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

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

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

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

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

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

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


文字列の置換

'<small>smalltalk</small>' copyReplaceAll: 'small>' with: 'strong>'. "==><strong>smalltalk</strong> "

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


文字列の連結

文字列の連結は、カンマ(,)で行います。

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


文字列の分割

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

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


小文字から大文字へ変換

'smalltalk' asUppercase.


大文字から小文字へ変換

'SMALLTALK' asLowercase.


最初の文字を大文字へ変換

Smalltalkのsは大文字です(どこかのサイトのタイトルみたい)。

'smalltalk' capitalized.


HTTPエンコード

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

encodeString unescapePercents. "==> 'あ'"


Collection

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


順序なしCollection


Set

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

s := Set new.

s add: 13.
s add: 5.
s add: 5.
s size. " print it ==> 2"

5を2回使い加えましたが、要素数は2と返却されています。

中身を確認しましょう。

s includes: 13. "true"

s includes: 5. "true"
s includes: 1. "false"

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

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

s remove: 5.

s size. "1"


Bag

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

b := Bag new.

b add: 13.
b add: 5.
b add: 5.
b size. "3"

要素を削除してみます。

b remove: 5.

b size.


順序ありCollection


Array

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

array := #($a $b $c).

array at:1. "$a"
array first. "$a"

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

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オブジェクトが作成できます。

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です。つまり自動的にサイズ拡張をしてくれます。

order := OrderedCollection new.

order add:$a.
order add:$b.
order. "print it"

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

order removeAt:2.

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

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


キー付きCollection


Dictionary

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

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:を使います。

dict removeKey: $b.

dict.


イテレータ

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


do:

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

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

array := #(#a #b #c).

array do:[:v | Transcript cr; show: v].


select:

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

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

col := (1 to: 10). "1から10までの要素. Intervalクラスのオブジェクト"

col select:[:v | v odd.]. "print it"

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


collect:

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

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

col := #('a' 'b' 'c'). 

col collect:[:v | v asUppercase ]. "print it"


detect:

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

col := (1 to: 10). "1から10までの要素. Intervalクラスのオブジェクト"

col detect:[:v | v odd.]. "print it ==? 1"


reject:

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

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/





  1. 中身の順序が保証されていません