@numa08 猫耳帽子の女の子

明日目が覚めたら俺達の業界が夢のような世界になっているとイイナ。

#新宿Scala座 第3回やってきた

f:id:numanuma08:20130805215651p:plain

新宿でScala勉強会 #新宿Scala座 をしてきた

嘘です。新宿ではなく、麹町です。#新宿Scala座 第3回

スイカを振舞っていただいた

今回、特に何も用意をしていなかったのですが、すごいことに隣の部屋で勉強会を開催されていた方々にスイカを振舞って頂きました。食べるのに忙しくてうっかりしていて写真を撮影していませんでしたが、みろなるさんがちゃんと写真を撮影されていました。ありがたい。Wokashi: 新宿Scala座 第3回に参加して来ました

前回から、ゆるふわな集まりにすることを意識していましたが、今回も無事にゆるふわにすることができました。参加者の皆様、ありがとうございます。

今回、俺はsbtとjarの話をして来ました。

sbt2jar

課題がでました(個人的に)

よくわからないのですが、参加者の一人の駄猫さんに2つくらい課題を出された気がします。ぶっちゃけ、2つ目は覚えてないので1個目だけここで答えます。

全ての値がSomeの場合のみ処理をしたい

Scalaの便利なOptionの話ですね。値がある場合はSome,値が無い場合はNoneが得られ、match-case文と組み合わせて利用をすることで例えばJavaに存在していたNullチェックと言った処理を削ることができます。Optionの内容についてはこちらのブログの記事がすごくわかりやすいです。ScalaのOptionステキさについてアツく語ってみる - ( ???) ゆるよろ日記

さて、いくつかのSomeかもしれないし、Noneかもしれない値があるとします。その際、全てがSomeである場合のみ処理を行いたいならどうすればいいでしょうか?駄猫さんの例はこうでした。

val a = Option("hello") //Some
val b = Option("world") //Some
val c = Option("!!")    //Some
val d = Option(null)    //None
 
val allSome = (a, b, c)
  allSome match {
    case (Some(x), Some(y), Some(z)) => println(x + " " + y + " " + z) //すべてSomeなのでここが実行される
    case _ => println("bye...")
  }
     
val withNone = (a, b, c, d)
  withNone match {
    case (Some(w), Some(x), Some(y), Some(z)) => println(w + " " + x + " " + y + " " +z)
    case _ => println("have none") //dがNoneなのでこっちに来る
  }

タプルの中にOptionなオブジェクトを入れてmatch-caseです。ぶっちゃけ、これでいいんじゃないですか?懇親会でも、これのほうが意図が分かりやすくて良いみたいな話が出ましたしとは言え、 せっかくなので別の方法を考えてみました。

val someList = List(a, b, c)
  someList.forall(_.isDefined) match {
    case true => println("all of some") //forallが成り立つのでこっち
    case _ => println("have none")
  }

val haveNonList = List(a, b, c, d)
  haveNonList.forall(_.isDefined) match {
    case true => println("all of some")
    case _ => println("have none") //foallが成り立たないのでこっち
  }

Listとforallを利用してみました。forallに引数として与えた式が全て満たされるなら真、そうでは無いなら偽なのでforallの結果でmatch-caseです。ただ、タプルを利用する場合と違って、一つ一つの値を取り出すことができません。matchの中でListに対して何か処理を行うのが自然でしょうか?

case class MyClass(x:String, y:String,z:String){
     def out {
       println(x + " " + y + " " + z + "from my class")
     }
   }

val myclass = for(x <- a; y <- b; z <- c) yield MyClass(x, y, z) //Some(MyClass)が得られる
myclass.foreach(_.out)

val myclassWithNone = for(x <- a; y <- b; z <- d) yield MyClass(x, y, z) //Noneが得られる
myclassWithNone.foreach(_.out)

最後はforを利用する方法です。無駄にcase classとか作ってますが、深い意味はないです。forブロックの中であれば各値を参照可能です。yieldと組み合わせることで、生成したインスタンスをOptionでラップできますよと言う例です。割りと俺は使うかな?

こんなトコロです。もっといい方法があると思うので教えていただけるとありがたいですね。

そういえば、Java8にはOptionalなるものが追加されるそうですね。ScalaのOptionに似てるけど、モナドだとかモナドじゃないとか色々言われててよくわかってないです。そもそもモナドって何ですか?誰か、次のScala座で教えてください。