SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新開発言語「Scala」の実体

Javaの限界を超えて実用化を目指す
新開発言語「Scala」のメリットとは~補足編

キーワードは手軽さと拡張性


case classとパターンマッチ

 次いで、case classと組み合わせて使うことで威力を発揮する、パターンマッチ機能を試していきましょう。

 今回は、 名前(name)と(age)を有するHumanクラスをcase classとして用意します。

scala> case class Human (val name:String, var age:Int)
defined class Human

 ためしに、オブジェクトを生成しておきましょう。

scala> val m0 =Human("加藤",55)
m0: Human = Human(加藤,55)

 例題として、カンマ(,)で区切られたCSV形式のデータを扱うこととしましょう。ただし、以下のように、扱うのは一癖あるCSVデータです。

田中,32
鈴木,32,ペットの名前はジョンです。
木村
斎藤,42,最近、禁煙しています。
 
山田,25
・・(続く)・・

 各行の1番目のデータは「名前」、2番目のデータは「年齢」を表していることが分かっているものとします。一見して分かるとおり、各行の列数は一定していません(コメントらしい3番目のデータがあったり、逆に年齢が記述されていなかったり、まったくデータが入っていない行もある)。たわいのない例かもしれませんが、処理するプログラムを書こうとすると、対応しなければならないケースはそこそこありそうです。

 こうしたイレギュラーなパターンの多いデータの取扱いは、Scalaが得意とするところです。今回は、CSVに擬したデータを三重引用符(""")で囲い、文字列リテラルとして表現し、その取扱いに挑戦することとします。

scala> val data = """
     | 田中,32
     | 鈴木,32,ペットの名前はジョンです。
     | 木村
     | 斎藤,42,最近、禁煙しています。
     |
     | 山田,25"""
data: java.lang.String =

       田中,32
       鈴木,32,ペットの名前はジョンです。
       木村
       斎藤,42,最近、禁煙しています。

       山田,25
※注

 縦棒(|)は、REPLが自動で出力するものです。

 文字列を三重引用符(""")で囲って定義すると、空白行を含め、改行がすべて保存されます。

 まずは、前述のコレクションクラスを用いていきましょう。String型であるdata変数に、Javaのsplitメソッドを適用すると、配列データを生成できます。

data.split("\n")
res: Array[java.lang.String] = Array(,        田中,32,        鈴木,32,ペットの名前はジョンです。,        木村,        斎藤,42,最近、禁煙しています。,        ,        山田,25)

 foreachメソッドを用いると、各要素を1行ずつ表示させることができます。

scala> data.split("\n").foreach {println _}

       田中,32
       鈴木,32,ペットの名前はジョンです。
       木村
       斎藤,42,最近、禁煙しています。

       山田,25

 今のところ、データが何もない要素が存在しています。データ長が1文字以上という条件でフィルター(filter)すると、何もない要素を取り除くことができます(※filter中でtrimが使われているのは、データ中にTab(\t)などが入っていたときの対応のためです)。

scala> data.split("\n").filter(_.trim.length > 0 ).foreach {println _}
       田中,32
       鈴木,32,ペットの名前はジョンです。
       木村
       斎藤,42,最近、禁煙しています。
       山田,25

 ここからが本番です。先ほど定義したHumanクラスに各要素を変換処理します。ここでは、要素数が2以上の場合のみHumanクラスを生成し、要素数が1の時には文字列(String)とします。こうした場合、mapによって記述できます。処理を

scala> val humanList =
     | data.split("\n").filter(_.trim.length > 0 ).map { s =>
     |     val arr = s.trim.split(",")
     |     if (arr.length >2) Human(arr(0),arr(1).toInt)
     |     else arr(0)
     | }.toList
humanList: List[java.lang.Object] = List(田中, Human(鈴木,32), 木村, Human(斎藤,42), 山田)

 humanListは、要素として、Humanクラスと、java.lang.ObjectのListとして生成されています。

 さて、このhumanListを扱うためのメソッドtryToGetAgeInfoを定義します。humanListが来る型は、ここでは、Human型(Humanクラス)か、文字列型(String)です。そのため、以下のようなパターンマッチを用います。

scala> def tryToGetAgeInfo (str:Any) = str match {
     |     case Human(n,a) => "%sさんは、%02d歳です。".format(n,a)
     |     case _ => "%sさんの年齢は不明です。".format(str)
     |   }
     
tryToGetAgeInfo: (Any)String

 リストの先頭は文字列型であるため、以下のようになります。

scala> tryToGetAgeInfo(humanList(0))
res129: String = 田中さんの年齢は不明です。

 リストの2番目の要素はHuman型であるため、以下のようになります。

scala> tryToGetAgeInfo(humanList(1))
res130: String = 鈴木さんは、32歳です。

 全体を表示させてみましょう。

scala> humanList.map { tryToGetAgeInfo _}.foreach {println _}
田中さんの年齢は不明です。
鈴木さんは、32歳です。
木村さんの年齢は不明です。
斎藤さんは、42歳です。
山田さんの年齢は不明です。

 見事に、不定形のCSVを処理できたようです。

 以上、駆け足ではありますが、case classとコレクションクラス、パターンマッチを組み合わせて使ってみました。最大のポイントは、コレクションライブラリのListに属しているmapやfilterというメソッドだと思います。これらは、Listのひとつひとつの要素(ここでは、1行1行のデータ)に対し、特定の条件をつけたり(filter)、変換処理(map)をしたりするもので、高階メソッドと呼ばれることもあります。これらのメソッドは、次々とつなげていくことができます(いわゆるメソッド・チェーン)。また、パターンマッチもポイントでした。

 これらの表現は、Scalaのパワーを活かすのに欠かせないものです。興味をお持ちになった方は、ScalaのAPIライブラリなどを参照しつつ、ぜひとも、自らの手でScalaのコードを書いてみてください。

まとめ

 今までは、動的言語のお手軽さを取るか、静的言語の厳密さを取るか、の2分の1の選択肢だった所に、Scalaは型を推論するという新しい発想で、2つを高いレベルで両立させてくれています。それ以外にも、近年の情報工学の進展を取り入れた、多くの新しい機能が実装されています。

今回の記事においては、ごく一部の機能しか説明できませんでした。このことは少し残念ではありますが、読者の皆さまにScalaを知っていただき、実際に動作させて試してもらうことができる所までは解説できたのでは、と思っています。Scalaを選択することによって得られる生産性の向上・スケーラビリティの向上などは、新しい言語を覚えるコストを払うに値するものだと考えています。読者の皆様には、ぜひともScalaに触れてもらい、Scalaの良さを感じてもらいたいと思います。

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
新開発言語「Scala」の実体連載記事一覧

もっと読む

この記事の著者

株式会社パテントビューロ 三木隆史(ミキ タカフミ)

株式会社パテントビューロ所属。マネージャー業務と平行して、Webアプリケーション開発、自然言語系の研究開発を行なう。以前はC言語による組込開発。違和感なくScalaへ移行できたことや、ロジック部分に注力できる生産性の高さに驚いている。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

株式会社パテントビューロ 木村吉博(キムラ ヨシヒロ)

政府系研究機関での研究開発を経て、現在、株式会社パテントビューロにて、プログラミング(知財関連文書(SGML/XML)の変換バッチ処理のScalaでの記述など)を担当している。複雑でイレギュラーな記述も多々見られる大量の文書を相手にする際に、Scalaの書きやすさと高速性とに大いに助けられている。か...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/4543 2011/03/28 09:55

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー