「WebプログラマのためのScala入門勉強会@渋谷」を開催しました。
初心者向けのScala勉強会として、「WebプログラマのためのScala入門勉強会@渋谷」というのを開催しました。(2週間も前の話ですが。)
参加者は20人強で、大半がPHPエンジニア(あとはJava, Ruby, Perl, Pythonあたり)だったようです。
開催概要とかは上記リンクのATNDのページのとおりですが、ざっと以下のような内容でした。
ScalaでHello, World!
Hello, World!からやってやる、という強い意志のもと、20分ほどかけてHello, World!を解説しました。
途中、環境的な理由によりHello, World!が動かないというまさかの事態が発生したり、時間不足で応用編が紹介できなかったりしました。
なお、応用編の内容はそんなに面白いものではないのですが、以下に紹介しておきます。
コンパイラプラグインでHello, World!
Scalaには、コンパイル時に独自のプラグインを実行させる仕組みがあります。コンパイラがソースコードをパースした後のフェーズに処理を挿し込んで、構文木を受け取って、それを操作して次のフェーズに渡すことができます。
差し込めるフェーズは、parser, typer, pickler, liftcode, tailcalls, erasure, cleanup, jvm, terminalとあります。詳しい内容については、こちらを参照してください。
ここでは、parserフェーズの後にHello, World!するコンパイラプラグインを書いてみます。
package wpscala import scala.tools.nsc import nsc.Global import nsc.Phase import nsc.plugins.Plugin import nsc.plugins.PluginComponent class EverythingHello(val global: Global) extends Plugin { import global._ val name = "everything_hello" val description = "say hello to everything." val components = List[PluginComponent](Component) private object Component extends PluginComponent { val global : EverythingHello.this.global.type = EverythingHello.this.global val runsAfter = List("parser") val phaseName = EverythingHello.this.name def newPhase(_prev: Phase) = new SayHelloPhase(_prev) class SayHelloPhase(prev: Phase) extends StdPhase(prev) { override def name = EverythingHello.this.name def apply(unit: CompilationUnit) { println("Hello, World!") } } } }
いろいろとめんどくさいですが、parserフェーズの後に、SayHelloPhaseというフェーズを挟み込む処理を記述しています。
これをコンパイルして以下のXMLと一緒にJarにまとめたものを作成したうえで...
scalac-plugin.xml
<plugin> <name>everything_hello</name> <classname>wpscala.EverythingHello</classname> </plugin>
以下のように使います。
scalac -Xplugin:everything_hello.jar hoge.scala
すると、hoge.scalaの内容とは無関係に、とりあえずコンパイル時にHello, World!が出ます。
ホントはこれじゃ面白くないので、ちゃんと構文木を操作して中身をHello, World!に書き換えてやろうと思ったのですが、そのためには構文木がどうなっているのかを調べたりしないといけないので挫折してしまいました。すみません。。。
source-readerでHello, World!
先程のコンパイラプラグインでは、パース処理の前に処理を差し込むことはできません。そのため、Scalaの文法としてパースできないソースコードについてはどうしようもありませんでした。
source-readerはパースよりも前、ソースコードを読み込むフェーズに処理を差し込みます。読み込んだソースコードを改変してコンパイラに渡すことができます。
これを応用して、コンパイラディレクティブを記述して、マクロを定義・展開したり、テンプレートエンジンを組み込んでコンパイル時にコード生成をするなんてことも可能です。
というわけで、何を読み込んでも全部Hello, World!にしてしまうsource-readerのコードは以下のとおりです。
package wpscala import scala.tools.nsc.io.SourceReader import java.nio.charset.CharsetDecoder import scala.tools.nsc.reporters._ class EverythingHelloReader(decoder : CharsetDecoder, reporter : Reporter) extends SourceReader(decoder, reporter) { def this() = this(null, null) override def read(file : java.io.File) : Array[Char] = { """object Hello { def main(args : Array[String]) { println("Hello, World!") } }""".toCharArray } }
これをコンパイルしてJarファイルにしたものを$SCALA_HOME/libに配置したうえで、以下のように使います。
scalac -Xsource-reader wpscala.EverythingHelloReader hoge.scala
すると、hoge.scalaの中身がなんであろうと、コンパイラにはHello, World!のコードが渡される、というわけです。
Scala開発環境構築
sbt, ENSIME, codefellow, Eclipse, NetBeans, IntelliJ IDEAの紹介をしました。
アンケートによると、大半がEclipseユーザーだったのですが、Scala + Eclipseはあまりおすすめできません。メモリ8Gでメモリ8G積んで高級なSSDマシンだったりするのならいいんですが、とにかく重いし遅いし固まります。
個人的にはNetBeans6.9.1がいい感じなのと、巷の評判ではIntelliJ IDEAが良かったりします。
素のエディタを使っている人も多いようでしたので、そういう人にはemacs + ENSIMEも便利かと思います。vim + codefellowは、どうしてもvimじゃないとダメな人にしかおすすめしません。動かすまでが大変なので。
コップ本読書会
コップ本(Scalaスケーラブルプログラミング)の第1章〜第3章を対象として、読書会を行いました。
と言ってもいきなりすぎるので、第1章については軽く解説して、残りを各小テーブルで進める形式にしました。
結果、テーブルごとに全然違うことをやっていたようで、環境構築の続きをやっていた人達もいれば、Scalaについてひたすら論議してた人たちもいました。
小テーブルだと話がし易いですし、各自やりたいことは違ったりもするので、この形式は良かったかなと思います。
事前アンケートの結果
当日発表しようと思って忘れていたんですが、事前にATNDでアンケートを取った結果です。
「この勉強会に何を期待しますか?」という設問で、目立った回答は以下のとおりです。
- Scalaを基礎から勉強したい 5人
- 仕事のため 3人
- Scala再入門 2人
- 参加者同士の交流 2人
- Javaからの脱却
- 関数型言語を学びたい
- 手を動かしながら学びたい
- GAEでFacebookアプリ作りたい
- Scala自体に期待している
やっぱり基礎から勉強したいという人が多いですね。というわけで、この勉強会のターゲットは、主にそこを主眼としていこうと思います。
次回
そもそも勉強会の主催は初めてだし、いきあたりばったりなコンセプトのない状態で開催してしまいましたが、「Scala」という単語のおかげで予想以上の人にお越しいただきました。
期待していただいた内容とは違ったかもしれませんが、継続希望の声もいただけました。本当にありがとうございます。
というわけで、第2回を本日(2010/11/16)開催しますので、よろしくお願い致します。