SlideShare una empresa de Scribd logo
1 de 30
Descargar para leer sin conexión
Scala警察のすすめ
Naoki Takezoe
@takezoen
BizReach, Inc
有名OSSでもScala的に微妙なコードが多い
● ビッグデータ、機械学習界隈のプロダクトにこの
傾向がある
● 元々関数型界隈ではなく、ビッグデータ界隈や機
械学習界隈の人がSparkやMLlibを使うために
Scalaを使っているので仕方ない
● むしろScala警察活躍のチャンス!!!!
Scala的に微妙なコードあるある
その1. Procedure Syntax
Procedure Syntax
メソッドの戻り値がUnitの場合はメソッド定義の「=」
を省略できるという記法
def hello() {
"Hello World!!"
}
なぜダメか?
● 戻り値の型がUnitになってしまう
● Javaから来た人が間違って書いてしまいがち
● 将来のバージョンのScalaでは廃止予定
def hello(): Unit = { "Hello World!!" }
def hello(): String = { "Hello World!!" }
こういうメソッドを定義しているつもりが・・・
実はこうなっている
どうすればよいか?
Procedure Syntaxは使わない
def hello(): String = {
"Hello World!!"
}
def hello() = {
"Hello World!!"
}
または
その2. Unit is not Unit value
Unit値を返すつもりでUnitと書いてしまう
def hello(): Unit = {
// ...いろいろ処理...
Unit
}
これ
なぜダメか?
● Unit値は()、UnitはUnitオブジェクト
● メソッドの戻り値など、実害はないケースが多い
ので気づきにくい
scala> val x = ()
x: Unit = ()
scala> val x = Unit
x: Unit.type = object scala.Unit
どうすればよいか?
Unitではなく()と書きましょう
def hello(): Unit = {
// ...いろいろ処理...
()
}
こう書く
その3. Auto Tupling
引数を自動的にタプルに変換する機能
def hello(x: (String, String)): String = {
x._1 + " " + x._2
}
// 本来であればこう呼び出す
hello(("Naoki", "Takezoe"))
// こう書ける
hello("Naoki", "Takezoe")
なぜダメか?
● なぜコンパイルエラーになるのかわかりにくい
ケースがある
● リファクタリング時に意図せずコンパイルが通って
しまうケースがある
どうすればよいか?
● Auto-Tuplingを使わずに記述する
● 名前付き引数で引数を渡す
● Any型の引数を持つメソッドを定義する場合や、
リファクタリング時は特に注意する
Scalaパズルにも
書いてある!
その3. Escape by "return"
def hello(name: String): String = {
return s"Hello ${name}!"
}
そもそもこういう場合はreturnは不要
引数チェックのEarly return
def hello(names: Seq[String]): String = {
// Seqが空の場合
if(names.isEmpty) return ""
// Seqに空文字列が含まれている場合
names.foreach { name =>
if(name.isEmpty) return ""
}
// 実際の処理
names.mkString(", ")
}
なぜダメか?
● メソッドの戻り値の型推論が効かなくなるので戻り
値の型を明示的に記述する必要がある
● 場合によっては例外にコンパイルされている
(ControlThrowable)
どうすればよいか?
● 不要な場合は書かない
● if elseやコレクション操作に置き換える
● 使う場合は例外処理に気をつける
def hello(names: Seq[String]): String = {
// Seqが空の場合
if(names.isEmpty) ""
// Seqに空文字列が含まれている場合
else if(names.exists(_.isEmpty) ""
// 実際の処理
else names.mkString(", ")
}
例外処理をする場合
● Throwableでキャッチしない
● Throwableもキャッチする必要がある場合は
NonFatalを使う
try {
// ...処理...
} catch {
case NonFatal(t) => t.printStackTrace()
}
ControlThrowableなどは
マッチしない
他にもよくあるパターン
● varやmutableコレクション
○ ループカウンタやコレクションの詰め替え処理など
● whileループ
○ varやmutableなコレクションと組み合わせで使用されてい
ることが多い
○ returnやbreakなどとの合わせ技担っている場合も
ループカウンタが必要な場合
var i = 1
seq.foreach { x =>
println(s"${i}: ${x}")
i = i + 1
}
zipWithIndexを使う
seq.zipWithIndex.foreach { case (x, i) =>
println(s"${i + 1}: ${x}")
}
途中で処理を止めたい場合
var line: String = null
val lines = new ListBuffer[String]()
line = reader.readLine()
while(line != null){
lines += line
line = reader.readLine()
}
Iterator.continuallyが使える
val lines = Iterator.continually(reader.readLine())
.takeWhile(_ != null)
バッドコードを検出するために
● コンパイラのオプションを設定しよう
● Lintツールを使おう
○ scalastyle
○ wartremover
scalacOptions in ThisBuild ++= Seq(
"-feature", "-unchecked", "-deprecation",
"-Xfuture", "-Yno-adapted-args", "-Ywarn-dead-code",
"-Ywarn-numeric-widen"
)
SparkがScalaの隙間産業を生み出している
● PredictionIO
● Spark MLlib
● Mahout-Spark
● Elasticsearch-Hadoop
SparkがScalaの隙間産業を生み出している
● PredictionIO
● Spark MLlib
● Mahout-Spark
● Elasticsearch-Hadoop
あなたもScala警察として
OSSコミッタになろう!

Más contenido relacionado

La actualidad más candente

La actualidad más candente (20)

YJTC19 B-6 Yahoo! JAPANの巨大インフラの運用と展望 #yjtc
YJTC19 B-6 Yahoo! JAPANの巨大インフラの運用と展望 #yjtcYJTC19 B-6 Yahoo! JAPANの巨大インフラの運用と展望 #yjtc
YJTC19 B-6 Yahoo! JAPANの巨大インフラの運用と展望 #yjtc
 
JVMのGCアルゴリズムとチューニング
JVMのGCアルゴリズムとチューニングJVMのGCアルゴリズムとチューニング
JVMのGCアルゴリズムとチューニング
 
Apache Atlasの現状とデータガバナンス事例 #hadoopreading
Apache Atlasの現状とデータガバナンス事例 #hadoopreadingApache Atlasの現状とデータガバナンス事例 #hadoopreading
Apache Atlasの現状とデータガバナンス事例 #hadoopreading
 
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
 
アジャイルな見積りと計画づくり勉強会
アジャイルな見積りと計画づくり勉強会アジャイルな見積りと計画づくり勉強会
アジャイルな見積りと計画づくり勉強会
 
CQRS+ESをAkka Persistenceを使って実装してみる。
CQRS+ESをAkka Persistenceを使って実装してみる。CQRS+ESをAkka Persistenceを使って実装してみる。
CQRS+ESをAkka Persistenceを使って実装してみる。
 
並行処理初心者のためのAkka入門
並行処理初心者のためのAkka入門並行処理初心者のためのAkka入門
並行処理初心者のためのAkka入門
 
なぜ「マイクロサービス“化”」が必要なのか
なぜ「マイクロサービス“化”」が必要なのかなぜ「マイクロサービス“化”」が必要なのか
なぜ「マイクロサービス“化”」が必要なのか
 
開発速度が速い #とは(LayerX社内資料)
開発速度が速い #とは(LayerX社内資料)開発速度が速い #とは(LayerX社内資料)
開発速度が速い #とは(LayerX社内資料)
 
Pivotal Greenplumで実現する次世代データ分析基盤のご紹介
Pivotal Greenplumで実現する次世代データ分析基盤のご紹介Pivotal Greenplumで実現する次世代データ分析基盤のご紹介
Pivotal Greenplumで実現する次世代データ分析基盤のご紹介
 
例外設計における大罪
例外設計における大罪例外設計における大罪
例外設計における大罪
 
イミュータブルデータモデル(世代編)
イミュータブルデータモデル(世代編)イミュータブルデータモデル(世代編)
イミュータブルデータモデル(世代編)
 
Unicode文字列処理
Unicode文字列処理Unicode文字列処理
Unicode文字列処理
 
Guide To AGPL
Guide To AGPLGuide To AGPL
Guide To AGPL
 
深層学習による自然言語処理入門: word2vecからBERT, GPT-3まで
深層学習による自然言語処理入門: word2vecからBERT, GPT-3まで深層学習による自然言語処理入門: word2vecからBERT, GPT-3まで
深層学習による自然言語処理入門: word2vecからBERT, GPT-3まで
 
データの価値を最大化させるためのデザイン~データビジュアライゼーションの方法~ #devsumi 17-E-2
データの価値を最大化させるためのデザイン~データビジュアライゼーションの方法~ #devsumi 17-E-2データの価値を最大化させるためのデザイン~データビジュアライゼーションの方法~ #devsumi 17-E-2
データの価値を最大化させるためのデザイン~データビジュアライゼーションの方法~ #devsumi 17-E-2
 
グラフデータベースは如何に自然言語を理解するか?
グラフデータベースは如何に自然言語を理解するか?グラフデータベースは如何に自然言語を理解するか?
グラフデータベースは如何に自然言語を理解するか?
 
マイクロサービス 4つの分割アプローチ
マイクロサービス 4つの分割アプローチマイクロサービス 4つの分割アプローチ
マイクロサービス 4つの分割アプローチ
 
テスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるなテスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるな
 
ナレッジグラフ入門
ナレッジグラフ入門ナレッジグラフ入門
ナレッジグラフ入門
 

Destacado

Scala製機械学習サーバ「Apache PredictionIO」
Scala製機械学習サーバ「Apache PredictionIO」Scala製機械学習サーバ「Apache PredictionIO」
Scala製機械学習サーバ「Apache PredictionIO」
takezoe
 

Destacado (20)

おっさんES6/ES2015,React.jsを学ぶ
おっさんES6/ES2015,React.jsを学ぶおっさんES6/ES2015,React.jsを学ぶ
おっさんES6/ES2015,React.jsを学ぶ
 
自然言語処理 Word2vec
自然言語処理 Word2vec自然言語処理 Word2vec
自然言語処理 Word2vec
 
AtCoderで始めるテスト駆動開発
AtCoderで始めるテスト駆動開発AtCoderで始めるテスト駆動開発
AtCoderで始めるテスト駆動開発
 
Scala製機械学習サーバ「Apache PredictionIO」
Scala製機械学習サーバ「Apache PredictionIO」Scala製機械学習サーバ「Apache PredictionIO」
Scala製機械学習サーバ「Apache PredictionIO」
 
The best of AltJava is Xtend
The best of AltJava is XtendThe best of AltJava is Xtend
The best of AltJava is Xtend
 
MP in Clojure
MP in ClojureMP in Clojure
MP in Clojure
 
Clojure web dev history
Clojure web dev historyClojure web dev history
Clojure web dev history
 
Non-Functional Programming in Scala
Non-Functional Programming in ScalaNon-Functional Programming in Scala
Non-Functional Programming in Scala
 
Javaでマサカリ投げてみた
Javaでマサカリ投げてみたJavaでマサカリ投げてみた
Javaでマサカリ投げてみた
 
Tensor Decomposition and its Applications
Tensor Decomposition and its ApplicationsTensor Decomposition and its Applications
Tensor Decomposition and its Applications
 
ElasticsearchとTasteプラグインで作るレコメンドシステム
ElasticsearchとTasteプラグインで作るレコメンドシステムElasticsearchとTasteプラグインで作るレコメンドシステム
ElasticsearchとTasteプラグインで作るレコメンドシステム
 
PredictionIOでSparkMLを使った開発方法
PredictionIOでSparkMLを使った開発方法PredictionIOでSparkMLを使った開発方法
PredictionIOでSparkMLを使った開発方法
 
自然言語処理
自然言語処理自然言語処理
自然言語処理
 
Elasticsearchで作る形態素解析サーバ
Elasticsearchで作る形態素解析サーバElasticsearchで作る形態素解析サーバ
Elasticsearchで作る形態素解析サーバ
 
Elasticsearchプラグインの作り方
Elasticsearchプラグインの作り方Elasticsearchプラグインの作り方
Elasticsearchプラグインの作り方
 
ESFluteによるElasticsearchでのO/Rマッパーを用いた開発
ESFluteによるElasticsearchでのO/Rマッパーを用いた開発ESFluteによるElasticsearchでのO/Rマッパーを用いた開発
ESFluteによるElasticsearchでのO/Rマッパーを用いた開発
 
LastaFluteに移行したFessとElasticsearch+ESFluteによるDBFlute環境
LastaFluteに移行したFessとElasticsearch+ESFluteによるDBFlute環境LastaFluteに移行したFessとElasticsearch+ESFluteによるDBFlute環境
LastaFluteに移行したFessとElasticsearch+ESFluteによるDBFlute環境
 
ちょっと理解に自信がないな という皆さまに贈るHadoop/Sparkのキホン (IBM Datapalooza Tokyo 2016講演資料)
ちょっと理解に自信がないなという皆さまに贈るHadoop/Sparkのキホン (IBM Datapalooza Tokyo 2016講演資料)ちょっと理解に自信がないなという皆さまに贈るHadoop/Sparkのキホン (IBM Datapalooza Tokyo 2016講演資料)
ちょっと理解に自信がないな という皆さまに贈るHadoop/Sparkのキホン (IBM Datapalooza Tokyo 2016講演資料)
 
AI社会論研究会
AI社会論研究会AI社会論研究会
AI社会論研究会
 
Apache Sparkに手を出してヤケドしないための基本 ~「Apache Spark入門より」~ (デブサミ 2016 講演資料)
Apache Sparkに手を出してヤケドしないための基本 ~「Apache Spark入門より」~ (デブサミ 2016 講演資料)Apache Sparkに手を出してヤケドしないための基本 ~「Apache Spark入門より」~ (デブサミ 2016 講演資料)
Apache Sparkに手を出してヤケドしないための基本 ~「Apache Spark入門より」~ (デブサミ 2016 講演資料)
 

Similar a Scala警察のすすめ

Scalaで萌える関数型プログラミング[エッセンシャル版]
Scalaで萌える関数型プログラミング[エッセンシャル版]Scalaで萌える関数型プログラミング[エッセンシャル版]
Scalaで萌える関数型プログラミング[エッセンシャル版]
Ra Zon
 
Scalaで萌える関数型プログラミング[完全版]
Scalaで萌える関数型プログラミング[完全版]Scalaで萌える関数型プログラミング[完全版]
Scalaで萌える関数型プログラミング[完全版]
Ra Zon
 
Scalaで萌える関数型プログラミング[1.1.RC1]
Scalaで萌える関数型プログラミング[1.1.RC1]Scalaで萌える関数型プログラミング[1.1.RC1]
Scalaで萌える関数型プログラミング[1.1.RC1]
Ra Zon
 
Object-Funcational Analysis and design
Object-Funcational Analysis and designObject-Funcational Analysis and design
Object-Funcational Analysis and design
Tomoharu ASAMI
 
activerecord-oracle_enhanced-adapterのご紹介
activerecord-oracle_enhanced-adapterのご紹介activerecord-oracle_enhanced-adapterのご紹介
activerecord-oracle_enhanced-adapterのご紹介
Kevin Toyoda
 
Scala.jsはじめました!
Scala.jsはじめました!Scala.jsはじめました!
Scala.jsはじめました!
K Kinzal
 
現在のWebフロントエンドの現状と愚痴と、それに対するHaxeフロントエンドライブラリMageについて
現在のWebフロントエンドの現状と愚痴と、それに対するHaxeフロントエンドライブラリMageについて現在のWebフロントエンドの現状と愚痴と、それに対するHaxeフロントエンドライブラリMageについて
現在のWebフロントエンドの現状と愚痴と、それに対するHaxeフロントエンドライブラリMageについて
Nobukazu Hanada
 
Why dont you_create_new_spark_jl
Why dont you_create_new_spark_jlWhy dont you_create_new_spark_jl
Why dont you_create_new_spark_jl
Shintaro Fukushima
 

Similar a Scala警察のすすめ (20)

Scala Daysに行ってみて
Scala Daysに行ってみてScala Daysに行ってみて
Scala Daysに行ってみて
 
Scalaノススメ
ScalaノススメScalaノススメ
Scalaノススメ
 
1周遅れのScala入学 #nds41
1周遅れのScala入学 #nds411周遅れのScala入学 #nds41
1周遅れのScala入学 #nds41
 
Scalaで萌える関数型プログラミング[エッセンシャル版]
Scalaで萌える関数型プログラミング[エッセンシャル版]Scalaで萌える関数型プログラミング[エッセンシャル版]
Scalaで萌える関数型プログラミング[エッセンシャル版]
 
Beginners Scala in FAN 20121009
Beginners Scala in FAN 20121009Beginners Scala in FAN 20121009
Beginners Scala in FAN 20121009
 
Reladomo in Scala #scala_ks
Reladomo in Scala #scala_ks Reladomo in Scala #scala_ks
Reladomo in Scala #scala_ks
 
Scalaで萌える関数型プログラミング[完全版]
Scalaで萌える関数型プログラミング[完全版]Scalaで萌える関数型プログラミング[完全版]
Scalaで萌える関数型プログラミング[完全版]
 
Scalaで萌える関数型プログラミング[1.1.RC1]
Scalaで萌える関数型プログラミング[1.1.RC1]Scalaで萌える関数型プログラミング[1.1.RC1]
Scalaで萌える関数型プログラミング[1.1.RC1]
 
[Japanese] Skinny Framework で始める Scala #jjug_ccc #ccc_r24
[Japanese] Skinny Framework で始める Scala #jjug_ccc #ccc_r24[Japanese] Skinny Framework で始める Scala #jjug_ccc #ccc_r24
[Japanese] Skinny Framework で始める Scala #jjug_ccc #ccc_r24
 
Object-Funcational Analysis and design
Object-Funcational Analysis and designObject-Funcational Analysis and design
Object-Funcational Analysis and design
 
Scala勉強会_2014_11_18
Scala勉強会_2014_11_18Scala勉強会_2014_11_18
Scala勉強会_2014_11_18
 
ScalaCL in ScalaKaigi
ScalaCL in ScalaKaigiScalaCL in ScalaKaigi
ScalaCL in ScalaKaigi
 
activerecord-oracle_enhanced-adapterのご紹介
activerecord-oracle_enhanced-adapterのご紹介activerecord-oracle_enhanced-adapterのご紹介
activerecord-oracle_enhanced-adapterのご紹介
 
ATN No.2 Scala事始め
ATN No.2 Scala事始めATN No.2 Scala事始め
ATN No.2 Scala事始め
 
PlaySQLAlchemy: SQLAlchemy入門
PlaySQLAlchemy: SQLAlchemy入門PlaySQLAlchemy: SQLAlchemy入門
PlaySQLAlchemy: SQLAlchemy入門
 
Scala.jsはじめました!
Scala.jsはじめました!Scala.jsはじめました!
Scala.jsはじめました!
 
現在のWebフロントエンドの現状と愚痴と、それに対するHaxeフロントエンドライブラリMageについて
現在のWebフロントエンドの現状と愚痴と、それに対するHaxeフロントエンドライブラリMageについて現在のWebフロントエンドの現状と愚痴と、それに対するHaxeフロントエンドライブラリMageについて
現在のWebフロントエンドの現状と愚痴と、それに対するHaxeフロントエンドライブラリMageについて
 
Trait in scala
Trait in scalaTrait in scala
Trait in scala
 
【LT】 怖くない恐怖のScala.js
【LT】 怖くない恐怖のScala.js【LT】 怖くない恐怖のScala.js
【LT】 怖くない恐怖のScala.js
 
Why dont you_create_new_spark_jl
Why dont you_create_new_spark_jlWhy dont you_create_new_spark_jl
Why dont you_create_new_spark_jl
 

Más de takezoe

Journey of Migrating Millions of Queries on The Cloud
Journey of Migrating Millions of Queries on The CloudJourney of Migrating Millions of Queries on The Cloud
Journey of Migrating Millions of Queries on The Cloud
takezoe
 
GitBucket: Git Centric Software Development Platform by Scala
GitBucket:  Git Centric Software Development Platform by ScalaGitBucket:  Git Centric Software Development Platform by Scala
GitBucket: Git Centric Software Development Platform by Scala
takezoe
 
Scala Warrior and type-safe front-end development with Scala.js
Scala Warrior and type-safe front-end development with Scala.jsScala Warrior and type-safe front-end development with Scala.js
Scala Warrior and type-safe front-end development with Scala.js
takezoe
 
Tracing Microservices with Zipkin
Tracing Microservices with ZipkinTracing Microservices with Zipkin
Tracing Microservices with Zipkin
takezoe
 
Type-safe front-end development with Scala
Type-safe front-end development with ScalaType-safe front-end development with Scala
Type-safe front-end development with Scala
takezoe
 
ネタじゃないScala.js
ネタじゃないScala.jsネタじゃないScala.js
ネタじゃないScala.js
takezoe
 
GitBucket: The perfect Github clone by Scala
GitBucket: The perfect Github clone by ScalaGitBucket: The perfect Github clone by Scala
GitBucket: The perfect Github clone by Scala
takezoe
 
Play2実践tips集
Play2実践tips集Play2実践tips集
Play2実践tips集
takezoe
 
Scala界隈の近況
Scala界隈の近況Scala界隈の近況
Scala界隈の近況
takezoe
 

Más de takezoe (20)

Journey of Migrating Millions of Queries on The Cloud
Journey of Migrating Millions of Queries on The CloudJourney of Migrating Millions of Queries on The Cloud
Journey of Migrating Millions of Queries on The Cloud
 
GitBucket: Open source self-hosting Git server built by Scala
GitBucket: Open source self-hosting Git server built by ScalaGitBucket: Open source self-hosting Git server built by Scala
GitBucket: Open source self-hosting Git server built by Scala
 
Testing Distributed Query Engine as a Service
Testing Distributed Query Engine as a ServiceTesting Distributed Query Engine as a Service
Testing Distributed Query Engine as a Service
 
Revisit Dependency Injection in scala
Revisit Dependency Injection in scalaRevisit Dependency Injection in scala
Revisit Dependency Injection in scala
 
How to keep maintainability of long life Scala applications
How to keep maintainability of long life Scala applicationsHow to keep maintainability of long life Scala applications
How to keep maintainability of long life Scala applications
 
GitBucket: Git Centric Software Development Platform by Scala
GitBucket:  Git Centric Software Development Platform by ScalaGitBucket:  Git Centric Software Development Platform by Scala
GitBucket: Git Centric Software Development Platform by Scala
 
Scala Warrior and type-safe front-end development with Scala.js
Scala Warrior and type-safe front-end development with Scala.jsScala Warrior and type-safe front-end development with Scala.js
Scala Warrior and type-safe front-end development with Scala.js
 
Tracing Microservices with Zipkin
Tracing Microservices with ZipkinTracing Microservices with Zipkin
Tracing Microservices with Zipkin
 
Type-safe front-end development with Scala
Type-safe front-end development with ScalaType-safe front-end development with Scala
Type-safe front-end development with Scala
 
Scala Frameworks for Web Application 2016
Scala Frameworks for Web Application 2016Scala Frameworks for Web Application 2016
Scala Frameworks for Web Application 2016
 
Macro in Scala
Macro in ScalaMacro in Scala
Macro in Scala
 
Java9 and Project Jigsaw
Java9 and Project JigsawJava9 and Project Jigsaw
Java9 and Project Jigsaw
 
Reactive database access with Slick3
Reactive database access with Slick3Reactive database access with Slick3
Reactive database access with Slick3
 
markedj: The best of markdown processor on JVM
markedj: The best of markdown processor on JVMmarkedj: The best of markdown processor on JVM
markedj: The best of markdown processor on JVM
 
ネタじゃないScala.js
ネタじゃないScala.jsネタじゃないScala.js
ネタじゃないScala.js
 
Excel方眼紙を支えるJava技術 2015
Excel方眼紙を支えるJava技術 2015Excel方眼紙を支えるJava技術 2015
Excel方眼紙を支えるJava技術 2015
 
ビズリーチの新サービスをScalaで作ってみた 〜マイクロサービスの裏側 #jissenscala
ビズリーチの新サービスをScalaで作ってみた 〜マイクロサービスの裏側 #jissenscalaビズリーチの新サービスをScalaで作ってみた 〜マイクロサービスの裏側 #jissenscala
ビズリーチの新サービスをScalaで作ってみた 〜マイクロサービスの裏側 #jissenscala
 
GitBucket: The perfect Github clone by Scala
GitBucket: The perfect Github clone by ScalaGitBucket: The perfect Github clone by Scala
GitBucket: The perfect Github clone by Scala
 
Play2実践tips集
Play2実践tips集Play2実践tips集
Play2実践tips集
 
Scala界隈の近況
Scala界隈の近況Scala界隈の近況
Scala界隈の近況
 

Scala警察のすすめ