LL脳がscalaの勉強を始めたよ その3

第3章の前半

コップ本の第3章にすすんでみようー

とりあえず、この章をやることで小規模なスクリプトがかけるようになるという事みたい。

そんなわけでscalaっぽい(javaっぽい?)要素が満載な雰囲気で盛りだくさんなので、前半後半にわけてみる。正確に言うとまだ全部消化できていないので時間稼ぎともいうケレドモ

インスタンスのパラメータ化

しょっぱなから( ゚д゚)ポカーン、さっぱりイメージがつかめない

例えば配列だったらこんなかんじのことをして、配列の型と要素を形成するっぽい

val hoges: Array[String] = new Array[String](3)

上の例だと、要素数3のString型の配列を用意する…と

ちなみに省略形

val hoges = new Array[String](3)

たぶん…クラスはざっくりとした表現しかもっていないので、インスタンスを生成する際に具体的な設定を行う。配列だったら要素数や型を設定したりして実際に使える入れ物にする…

…くらいに思って先に進むことにしよう。使ってるうちにわかるんじゃねーかな?不安(´・ω・`)

配列操作ー

作った配列の要素を参照したり、更新したりするよーって内容。

配列要素の参照は

hoges(2)

配列要素の更新は

hoges(2) = "ヒャッハー"

…とよくある形での配列操作なんだけども実際は配列オブジェクトのメソッドによる操作なので

// 要素の参照
hoge.apply(2)
// 要素の更新
hoge.update(2, "ヒャッハー")

てな感じで内部処理されますよーという、ちょっと面白い内容

実際3章でくりかえされるのは、scalaでの処理や操作はオブジェクトのメソッドだぜ!という内容で、例えば 3 + 4 なんていう演算操作ですら下のようなメソッドで定義されます(`・ω・´)キリ

 (3).+(4)

普通に使うだけだったらあまり気にしなくても良さそうなんだけど、ここらへんを覚えておくと先の説明が飲み込みやすくなりそうな雰囲気なのでメモ

配列はvalでも要素は変更できるぜ

配列のimmutable定義はあくまでも入れ物(型、要素数)に対してなので中身はいくらでも入れられるとのこと

んじゃ、mutable定義の配列は入れ物変更できんのか?と疑問に思ったのでテストコード書いてみる

// 配列定義
var hugas = new Array[String](6)
// 要素数を変更:これはOK
hugas = new Array[String](3)
// 型を変更:これはエラー
hugas = new Array[Int](3)

素数は配列の特性だから変更可能だけども、それ以前に静的型付けなんだから一度定義した型は変更できないとの結果。よく考えれば当たり前なんだろうけど…自分、LL脳ですから

配列定義めんどくさいから簡単に

上の手順で配列の要素定義をすると

val hoges = new Array[String](3)
hoges(0) = "Hello"
hoges(1) = "The"
hoges(2) = "World"

...と非常にめんどくさいので下のように一気にやろうぜベイベー(ミッチー風に)

val hoges = Array("Hello", "The", "World")

以上

リスト

配列は要素を変更できるので、要素を変更できないリストの話

まずリストの定義はこんな感じ

val moge = List(1, 2, 3)

型を省略しないとこんなかんじ

val moge = List[Int](1,2,3)

Listの性質をためしてみたいので要素を変更してみる

// 当たり前だけどエラーが発生 
moge(1) = 3
// エラーメッセージ
error: value update is not a member of List[Int]

Listには更新メソッドが存在しないから値変更できませんよエラーが発生。

ここらへんで"全ての処理はオブジェクトのメソッド”っていうのを思い出して、メソッド定義のやりかたで各オブジェクトの性質を決めてるんだなーとなんとなく納得。

役に立たないかも知れないけど、イメージできるとチト嬉しい。

リストへの疑問

ちょっぴり疑問なのが配列と同様の方法で生成するとエラーがでること

// 無理やり生成
 val h = new List[String]()
// Listはアブストラクトクラスだから具象化できませんという感じ?
error: class List is abstract; cannot be instantiated

ちらっとググッてみると、アブストラクトクラスからはインスタンスを生成できないから継承して拡張して使うとのこと。

…ということは、Listのオブジェクトの生成は下の流れになるのか?教えてエロイ人

  1. List classを継承したクラスを生成
  2. 生成したサブクラスをnewしてインスタンスを生成
  3. インスタンスを1,2,3の要素を持つように拡張する

ちなみにPHP5にもあんのね、abstract ... orz、ちゃんと使えば規約をがっちり適用出来そうだからちゃんと覚えよう…abstractとかinterfaceってのは個人的に規約用の仕組みってイメージなんだけど合ってるかな?

リスト操作

リストの結合方法をつらつらと

リストの同士の結合は":::"というのを使う

// 結合してみる
List(1,2,3) ::: List(4,5,6)
// 結合した結果の生成されるリスト
List[Int] = List(1, 2, 3, 2, 3, 4)

リストに新しい値を追加する場合は"::"というのを使う

// 結合してみる
2 ::: List(4,5,6)
// 結合した結果の生成されるリスト
List[Int] = List(2,4,5,6)

"::"に関しては上のような書き方にも関わらず、Listオブジェクトのメンバらしく、コロンが絡む演算の場合は記述順序が前後するとのこと

つまり内部的には下のように処理されている人のことで

List(4,5,6).::(2)

下みたいに書くとIntオブジェクトのメンバじゃないからエラーが出ますよってことらしい

List(4,5,6) :: 2

あと次のような書き方でListを構成することも可、みたい

3::4::5::6::Nil

NilはNullみたいな扱いなんだけど、もっと広い意味での空とかになるのかしら?

List操作もろもろ

List操作のメソッドについていくつか説明がある中で引っかかったものについて

List内の要素の存在チェックをするexistsについて、下みたいな書き方(結果はBoolean)

val test = List("hoge", "huga", "muga")
test.exists(s=>s == "hoge")

個人的にこういうふうに使いたくなるんだけど、エラーになる

test.exists("hoge")

とりあえずListのメソッドはListの要素をイテレータみたいな感じで処理するのかしら?…と、後から詳しく出てくるらしいので独りごちておく。

タプル

複数の型を要素として使いたかったらタプル使おうぜ!というノリ

// タプル定義
val moge = (1, "one", 2, "two", 3, "three")
// 1番目の要素(1)へのアクセス
moge._1
// 4番目の要素(two)へのアクセス
moge._4

要素へのアクセスは"._<要素番号>"で、要素番号は1始まりとのこと。MLとかHaskellの伝統を守ってるそうな。

ちなみにタプルの値は更新できないっすね、あとタプルの要素は現状では22個までしか作れないとの注意あり

以上ー

この後はSetやらMapやら盛りだくさんなので、ちょっと一息入れてみる。