nFact

n!

Scala Matsuriに参加してきました

お久しぶりです。 30〜31日の2日間で開催されたScala Matsuriに参加してきました。
Java系以外のイベントに出るのは初めてかつ
普段がっつりScalaいじっていない私でしたが楽しめました!
運営の方々、楽しいイベントを開催していただきありがとうございます!
お弁当も美味しかったです!!

参加したセッション

1日目

  • Refactoring Scala
  • Scalaの深みへダイブ
  • 猫という考え方
  • バッチをAkka Streams で再実装したら100倍(295倍)速くなった話
  • ScalaコードはJVMでどのように表現されているのか
  • 実用関数型アーキテクチャのパターン
  • Playソースコード完全マスターの道

2日目(アンカンファレンス)

印象に残ったもの

Refactoring Scala

Scalaの表現力すごい(小並感)
Type AliasとかはJavaに導入するのそこまで難しそうに思えないのですが、
何で入んないんでしょうねぇ...。
これ以上言うとなんか後でものすごい
マサカリが飛んできそうなのでこれ以上は言わないことにしますw

スライド上のソースも読みやすく、楽しめました!後で資料としても活用出来そうですね

Scalacの深みへダイブ

これだけでもScala Matsuri参加してよかった!という気分になれました。
Scalacがどんな処理の流れでFoo.scalaからFoo.classを作るのか?がメインでしたが、
過去の歴史等も含めて触れていました。

REPL上でASTを表示させているスライドがありましたがこれがめっちゃ便利

REPLで

import scala.reflect.runtime.universe._

してから、

val tree = q"a + b"
showRaw(tree)

をタイプするとScalacが生成したASTがさくっと見れるっぽいことがわかりました。
(今までScalaのASTを見たい時はずっとscalac -Ybrowse:typer Main.scalaしてました。。。)
showRaw使えば見たいところだけ見れて便利ですね。
全体を俯瞰したいときは今までの方-Ybrowse:typerしたほうが良さそうですが。

ちなみに上のを実行すると、

scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._

scala> val tree = q"a + b"
tree: reflect.runtime.universe.Tree = a.$plus(b)

scala> showRaw(tree)
res0: String = Apply(Select(Ident(TermName("a")), TermName("$plus")), List(Ident(TermName("b"))))

このようになります。

+演算子$plusに変換されているのとか関数適用のApplyとかいろいろ見れて楽しいですね。

ScalaとSparkによる日本語テキストマイニング

初心者向けのセッションで、機械学習を理解するための前提となる キーワードの解説から説明があったのでだいぶ分かりやすかったです。

英語はスペースなどの区切り文字があるため、
それで区切ってから処理をするのに対し、
日本語はそのような区切り文字が無いため、
形態素解析で確率的なアプローチをしてから処理を始める違いがあることがわかりました。
ただそれで分けられたところで「ヤバい」などの単語があった時に
プラスの意味でもマイナスの意味でも取れるので機械学習難しいと言ってましたw

機械学習をするのはライブラリ側のコードを呼び出す1行で済んでしまい、
事前準備のコードがほとんどでした。

Word2vecはこの事前準備が必要ないようですが未知のデータを渡した時の動作が
事前に渡したデータセットにかなり依存するので
どんなデータを渡すかが非常に重要になりそうです。

そのほか

あとこれ私でした。1日目はWiFiの存在に気づかず
しばらくテザリングしてましたすみませんw

NullPointerExceptionがスローされないstaticフィールドアクセス

こんなコードがあった時に、

コメントにある通りNullPointerExceptionがスローされずにhogeが表示されます。
普段メソッド呼び出ししてフィールドにアクセスする書き方しないので割りと衝撃的でした。

この動作はJava言語仕様に同じ例があります。

http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#d5e24400

Even though the result of favorite() is null, a NullPointerException is not thrown. That "Mount " is printed demonstrates that the Primary expression is indeed fully evaluated at run time, despite the fact that only its type, not its value, is used to determine which field to access (because the field mountain is static).

だそうです(適当

JVM言語がHello Worldを表示するまでの実装(JavaとScala編)

JVM言語

Java Virtual Machine上で動作するプログラミング言語JVM言語と言います。

JVM言語で有名なものだとScalaとかClojureとかGroovyなどが挙げられます。
KotlinとかCeylonとかもこれから流行りそうな雰囲気です。

どの言語も1 + 1レベルだと生成されるバイトコードはほぼ同じ
(iconst_1 iconst_1 iaddとか)ですが、
Hello worldを出力するバイトコードが各言語で違うのでまとめてみました。今のところ2つです。

Java

まずはJava(javac 1.8.0_25)

まずSystemクラスのoutフィールドを取得します。
outPrintStreamクラスのオブジェクトです。
PrintStreamprintlnメソッドに"Hello World"を渡して呼んでいます。
これが基本形になります

Scala

次はScala(2.11.4)です

HelloWorldを表示する部分がSystem.out.println(...)からprintln(...)になっています。
ScalaPredefオブジェクトにprintlnメソッドが定義されていて、そのprintlnメソッドが使用されます。
importが無いじゃん!っていう話ですが、PredefオブジェクトはScala側で暗黙的にimportされています。
つまり、上のコードのprintln("Hello World!")Predef.println("Hello World!")に書き換えても同じ動作をします。

Predefオブジェクトのprintlnは、

scala/Predef.scala at 2.11.x · scala/scala · GitHub

   def println(x: Any) = Console.println(x)

となっていて、Consoleクラスに引数をそのまま渡しているようです。

Console.scalaを見ると、

scala/Console.scala at 2.11.x · scala/scala · GitHub

...
   private val outVar = new DynamicVariable[PrintStream](java.lang.System.out)
...
   def out = outVar.value
...
   def println(x: Any) { out.println(x) }

new DynamicVariable[PrintStream](java.lang.System.out)
JavaSystemクラスのoutフィールドを持ってきているようです。
DynamicVariableクラスは動的スコープをエミュレートするクラスです。
(動的スコープに関しては割愛します)
DynamicVariableを使用して、JavasetOut相当の動きを提供しているようでした。
直接System.out.printlnコンパイルせず、Predef.scalaConsole.scalaを経由して、
Hello Worldが表示されるという実装でした。