業務外でもScalaは伸ばせる #Scala
この記事はdots.女子部 Advent Calendar 2016の18日目です。
昨日は私のQiitaの軽くバズった記事にコメントしてくださったTamilyさんです。
この記事について
業務でScalaがやれなくて何やれば良いのかわからない人でも、業務外でScalaのスキル上げられるっていう話をします。ただ、Scalaに限っていないので他の言語でも参考になると思います。
本題の前に
昨日はMashup Awardsのfor Pro部門決勝戦がありました。結果は優勝!!!初代チャンピオンになりました。やったぜ!
okoysm.hatenablog.jp
本題
TL;DR
伸ばしたいスキルがあれば「師匠(Sensei)」を見つけよう!
Scalaできるようになりたいけど・・・
私はScalaがやりたくてちょっと触ったり、コップ本買ったりしてました。でも分かんないんです、何から手を付ければ。しかも、その書いたコードがどれだけのレベルなのか。Scalaの良いところをつかえているのか・・・
初心者が行けそうな勉強会が少ない・・・
Scalaの勉強会って圧倒的に少ないし、あったとしても参加者みると「あ、あのヤバイ人だ」ってなって、なかなかいけませんでした。この前やっと初めてScala勉強会行きました。とても和やかな雰囲気でしたが、やっぱりレベルの高い人ばかりでした。自分はここに居ていいのだろうかという感じにもなりました。
自信つけるしかないしスキルあげよう!
でも、いつまでも自信がないままでも駄目なのでスキルを粛々と上げています。現在はGitHubでstudy-scalaというリポジトリを公開し、そこに勉強して書いたコードをアップロードしています。でも、書いただけじゃうまくなりませんよね。そこでコードレビューです。
業務外レビュワーを見つけよう!
私はTwitterで以下のように呼びかけてみました。
すると @kmizu さんが手を挙げてくださいました。現在色々基本的なところから見ていただいています。本当に感謝しています。ありがとうございます。業務だったら上司だったり同僚がコードレビューしますが、業務外だとコードレビューなかなかしませんからね。SNSを使って先生を見つけましょう!
できれば英語で書こう!
少なくともこのリポジトリでは、日本語は日本人しか読めないのでやりたいことや何を考えてるかは基本的に英語で書いています。
まとめ
伸ばしたいスキルがあれば「師匠(Sensei)」を見つけよう!
明日の担当はyuunaさんです。楽しみー!
Mashup Awards優勝したぞおおおおお #MA_2016
明日に向けての意気込み #MA_2016
明日はついにMashup Awards for Pro決勝戦!しかも初の360度ステージでのプレゼン!
ドキドキとわくわくが止まりません!
私たちの作品
「全社員早押上司争奪戦」です! hacklog.jp
デモ展示やります!
11:00〜14:00に会場内でデモ展示やります!発表前に触ってみたい方是非お越しください! 当日は限定ポストカードも配布予定です!
発表はfor Proの最後!
決勝は15:10から開始予定で私たちは最後です。 チームメンバー全員登壇します。
意気込み
狙うはもちろんfor Pro優勝です!
いいかお前らー! 私たちは逃げも隠れもしないぞー! 360度? 上等だ! 私たちの覚悟をしっかりと受け止めろー!
ちなみにこの言葉の元ネタはももいろクローバーZのしおりんの最初の言葉です。私の今の気持ちそのままなので引用しました!
ももクロ春の一大事2012~見渡せば大パノラマ地獄~ [DVD]
- アーティスト: ももいろクローバーZ
- 出版社/メーカー: キングレコード
- 発売日: 2012/09/05
- メディア: DVD
- 購入: 1人 クリック: 3回
- この商品を含むブログ (4件) を見る
どうやったら見に行ける?
下のDoorkeeper リンクから登録してください! 様々な作品があるので、2000円の価値はあるとおもいます! 是非お越しください!そして応援してください!
学習メモ: クラス (1/2) #dwango #Scala
この記事について
ドワンゴScala研修テキストを学習したときのメモです。 okoysm.hatenablog.jp
DOING
クラス
クラス定義
- 記述方法以外はJavaと同じ (パラメータの指定方法くらい?)
class ClassName(parameter1: Type1, parameter2: Type2, ...) { (a field or method definition)の0回以上の繰り返し }
例)点を表すクラスを定義する場合
class Point(_x: Int, _y: Int) { val x = _x val y = _y }
コンストラクタの引数をそのまま公開したい場合は以下のように短く書ける
class Point(val x: Int, val y: Int)
疑問点
使うからクラスを定義するんだろうし、そのまま公開するケースのほうが多い気がしたのだけどどうなのだろう?
ポイント
この書き方のポイントは大きく2点。
- クラス名の直後にコンストラクタの定義がある
- Scalaでは1クラスに付き、基本的には1つのコンストラクタしか使わない
- 文法上は複数のコンストラクタを定義できるようになっていますが、実際に使うことはまずないので覚える必要はない
- 最初の1つのコンストラクタをプライマリコンストラクタとして特別に扱っている
- val/varによって、コンストラクタ引数をフィールドとして公開することができる
- プライマリコンストラクタの引数にval/varをつけるとそのフィールドは公開され、外部からアクセスできるようになる
- コンストラクタ引数のスコープはクラス定義全体におよびます。
これを使うと、メソッド定義の中から直接コンストラクタ引数を参照できる。
このプログラムの場合+
メソッド定義の中から直接コンストラクタ引数を参照している
class Point(val x: Int, val y: Int) { def +(p: Point): Point = { new Point(x + p.x, y + p.y) } override def toString(): String = "(" + x + ", " + y + ")" }
この章での疑問点
- コンストラクタの引数をそのまま公開したくない場合などあるのだろうか(Javaでいうprivateな変数にしてgetter/setterで取らせたいみたいなやつかな)
進捗
DONE
DOING
- クラス
TODO
学習メモ:Scalaの制御構文 #Scala #dwango
この記事について
DOING
Scalaの制御構文
言葉の定義
ScalaはCやJavaなどの手続き型の言語に比べて、文よりも式になる構文が多いため、変数などの状態をできるだけ排除したわかりやすいコードが書きやすい。
構文 (Syntax)
- そのプログラミング言語内でプログラムが構造を持つためのルール
- プログラミング言語内で特別扱いされるキーワード(class, val, ifなど)
- 正しいプログラムを国姓するためのルール(クラスの中身は{}で括られる)
式 (Expression)
- プログラムを構成する部分のうち、評価することで値になるもの
1
や1+2
は数値になり、"hoge"
は文字列の値になる
文 (Statement)
- プログラムを構成する部分のうち、評価しても値にならないもの(⇔式(Expression))
val i = 1
は、定義全体としては値を持たない。(変数iは定義され,iの値は1になるけれど)
{}式
- {}構文の一般形は
{exp1; exp2; ... expN; }
- ;は改行で区切られていれば省略できる。
- exp1からexpNを順番に評価し、expNを評価した値を返す。
Scalaにおける一般的なメソッド定義
scala > def foo(): String = { "foo" + "foo" }
if式
Javaとほぼ同じだったのでスキップ
練習問題
var age: Int = 5という年齢を定義する変数とvar isSchoolStarted: Boolean = falseという就学を開始しているかどうかという変数を利用して、 1歳から6歳までの就学以前の子どもの場合に“幼児です”と出力し、それ以外の場合は“幼児ではありません”と出力するコードを書いてみましょう。
自分の回答
var age: Int = 5 var isSchoolStarted: Boolean = false if(1 <= age && 6 <= age && !isSchoolStarted){println("幼児です")}else{println("未熟児です")}
while式
Javaとほぼ同じだったのでスキップ
練習問題
do whileを利用して、0から数え上げて9まで出力して10になったらループを終了するメソッドloopFrom0To9を書いてみましょう。loopFrom0To9は次のような形になります。???の部分を埋めてください。
def loopFrom0To9(): Unit = { var i = ??? do { ??? } while(???) }
自分の回答
i++みたいなのってScala使えないんですね・・・
def loopFrom0To9(): Unit = { var i = 0 do { println(i) i += 1 } while(i < 10) }
for式
Javaの制御構文と似た使い方ができるものの、全く異なる構文です。for式の本当の力を理解するには、flatMap, map, withFilter, foreachといったメソッドについて知る必要がありますが、ここでは基本的なfor式の使い方のみを説明します。
とあるので、心してかかりたいと思います。
基本的な構文
for(ジェネレータ1; ジェネレータ2; ... ジェネレータn) A # ジェネレータ1 = a1 <- exp1; ジェネレータ2 = a2 <- exp2; ... ジェネレータn = an <- expn
- ジェネレータって言ってるのが条件っぽい(a1 <- exp1など)
- exp1〜expnには、ある数の範囲を表す式を使える
1 to 10
→1から10まで (10を含む)1 until 10
→1から10まで (10を含まない)
scala> for(x <- 1 to 5; y <- 1 until 5){ println("x = " + x + " y = " + y) } x = 1 y = 1 x = 1 y = 2 x = 1 y = 3 x = 1 y = 4 x = 2 y = 1 x = 2 y = 2 x = 2 y = 3 x = 2 y = 4 x = 3 y = 1 x = 3 y = 2 x = 3 y = 3 x = 3 y = 4 x = 4 y = 1 x = 4 y = 2 x = 4 y = 3 x = 4 y = 4 x = 5 y = 1 x = 5 y = 2 x = 5 y = 3 x = 5 y = 4
ループ変数の中から条件にあったものだけを絞りこめる
以下の例だと x!=y
が追加されたことによってx, y同じ値のものが表示されなくなっています。
scala> for(x <- 1 to 5; y <- 1 until 5 if x != y){ println("x = " + x + " y = " + y) } x = 1 y = 2 x = 1 y = 3 x = 1 y = 4 x = 2 y = 1 x = 2 y = 3 x = 2 y = 4 x = 3 y = 1 x = 3 y = 2 x = 3 y = 4 x = 4 y = 1 x = 4 y = 2 x = 4 y = 3 x = 5 y = 1 x = 5 y = 2 x = 5 y = 3 x = 5 y = 4
コレクションの要素を1つ1つ辿って処理を行うために使うことも可能
例えばListの中身の文字列をすべて出力する処理
scala> for(e <- List("A", "B", "C", "D", "E")) println(e) A B C D E
コレクションの要素を辿って、加工して新しいコレクションを作成できる
この場合ジェネレータで指定したリストの要素の前にPreが付いた要素を持つリストが新しく作成されています。
scala> for(e <- List("A", "B", "C", "D", "E")) yield { | "Pre" + e | } res9: List[String] = List(PreA, PreB, PreC, PreD, PreE)
yieldキーワードを使ったfor式はfor式ではない
- for-comprehensionと呼ぶ事がある
- yieldキーワードを使うことで、コレクションの要素を加工して返すという異なる用途に使える
練習問題
1から1000までの3つの整数a, b, cについて、三辺からなる三角形が直角三角形になるような a, b, cの組み合わせを全て出力してください。直角三角形の条件にはピタゴラスの定理を利用してください。 ピタゴラスの定理とは三平方の定理とも呼ばれ、a ^ 2 == b ^ 2 + c ^ 2を満たす、a, b, c の長さの三辺を持つ三角形は、直角三角形になるというものです。
自分の回答
^
が使えなくて微妙にハマった・・・
for (a <- 1 to 1000; b <- 1 to 1000; c <- 1 to 1000) if (a * a == b * b + c * c) { println("a=" + a + ", b=" + b + ", c=" + c) }
模範解答と違ったところ
for文の中にif文を入れ込むかfor文とif文を分けるか。
模範解答はfor (a <- 1 to 1000; b <- 1 to 1000; c <- 1 to 1000 if a * a == b * b + c * c)
で
自分の回答はfor (a <- 1 to 1000; b <- 1 to 1000; c <- 1 to 1000) if (a * a == b * b + c * c)
match式
match式は使い方によって非常に幅のある制御構造です
基本構文
- Javaのswitch-caseみたいなやつ
- Scalaはbreakしなくていい(フォールスルー動作がない)
_
はdefaultのようなもの(ワイルドカードパターン)- match式を使う際は漏れがないように、ワイルドカードパターンを利用することが多い。
マッチ対象の式 match { case パターン1 [if ガード1] => 式1 case パターン2 [if ガード2] => 式2 case パターン3 [if ガード3] => 式3 case ... case パターンN => 式N case _ => "nothing" }
パターンをまとめる
Javaのswitch-caseのときはフォールスルーさせていたけど、Scalaの場合はOR(|)でつなげられる。
"abc" match { case "abc" | "def" => println("first") println("second") }
パターンマッチによる値の取り出し
switch-case以外の使い方として、コレクションの要素の一部にマッチさせる使い方もある。
下の場合、「リストの先頭要素が"A"で5要素」のパターンにマッチすると残りが表示され、しなければ"nothing"が表示される。
scala> val lst = List("A", "B", "C", "D", "E") lst: List[String] = List(A, B, C, D, E) scala> lst match { | case List("A", b, c, d, e) => | println("b = " + b) | println("c = " + c) | println("d = " + d) | println("e = " + e) | case _ => | println("nothing") | } b = B c = C d = D e = E
+ガード式なパターンマッチもできる
さっきのプログラムにガード式(今回の場合if b != "B"
)を追加すると"nothing"が表示されるようになる。
scala> val lst = List("A", "B", "C", "D", "E") lst: List[String] = List(A, B, C, D, E) scala> lst match { | case List("A", b, c, d, e) if b != "B" => | println("b = " + b) | println("c = " + c) | println("d = " + d) | println("e = " + e) | case _ => | println("nothing") | } nothing
パターンマッチのパターンのネストが可能
- Listを要素として持つListをパターンマッチすることもできる
- パターンの前に
@
がついているのはasパターンと呼ぶ@
の後に続くパターンにマッチする式を@
の前の変数(今回の場合a)に束縛する。
- このプログラムの場合パラメータがListで先頭要素がList("A")で2要素もつ場合matchし、List(A)ともう一つの要素が表示されている
scala> val lst = List(List("A"), List("B", "C", "D", "E")) lst: List[List[String]] = List(List(A), List(B, C, D, E)) scala> lst match { | case List(a@List("A"), x) => | println(a) | println(x) | case _ => println("nothing") | } List(A) List(B, C, D, E)
パターンマッチの場合、値をとりだすことはできない
scala> (List("a"): Any) match { | case List(a) | Some(a) => | println(a) | } <console>:14: error: illegal variable in pattern alternative case List(a) | Some(a) => ^ <console>:14: error: illegal variable in pattern alternative case List(a) | Some(a) => ^
値を取り出さないパターンマッチは可能。ただこれいつ使うんだろう。型を見たい時とかだろうか・・・
(List("a"): Any) match { case List(_) | Some(_) => println("ok") }
型によるパターンマッチ
- Scalaではcaseに値ではなく型を指定することも可能
- 特定の型に所属する場合にのみマッチするパターンは
名前:マッチする型
と書く - AnyRef=JavaでいうObject型(なんでも格納できる)
- 例外処理やequalsの定義などで使うことがある
- しばしばキャストの代わりにパターンマッチが用いられるので覚えておくこと
このプログラムの場合AnyRefがStringにマッチしているので、すべてを大文字にした結果が表示されています。
scala> import java.util.Locale import java.util.Locale scala> val obj: AnyRef = "String Literal" obj: AnyRef = String Literal scala> obj match { | case v:java.lang.Integer => | println("Integer!") | case v:String => | println(v.toUpperCase(Locale.ENGLISH)) | } STRING LITERAL
JVMの制約による型のパターンマッチの落とし穴
- 型変数を使った場合、正しくパターンマッチが行われない。
- このプログラムだとcaseにList[Int]とList[String]を書いているが、パターンマッチでは区別できない
scala> val obj: Any = List("a") obj: Any = List(a) scala> obj match { | case v: List[Int] => println("List[Int]") | case v: List[String] => println("List[String]") | } <console>:16: warning: non-variable type argument Int in type pattern List[Int] (the underlying of List[Int]) is unchecked since it is eliminated by erasure case v: List[Int] => println("List[Int]") ^ <console>:17: warning: non-variable type argument String in type pattern List[String] (the underlying of List[String]) is unchecked since it is eliminated by erasure case v: List[String] => println("List[String]") ^ <console>:17: warning: unreachable code case v: List[String] => println("List[String]") ^ List[Int]
型変数を含む方のパターンマッチはワイルドカードパターンを使うと良い
obj match { case v: List[_] => println("List[_]") }
練習問題
new scala.util.Random(new java.security.SecureRandom()).alphanumeric.take(5).toList
以上のコードを利用して、 最初と最後の文字が同じ英数字であるランダムな5文字の文字列を1000回出力してください。 new scala.util.Random(new java.security.SecureRandom()).alphanumeric.take(5).toListという値は、呼びだす度にランダムな5個の文字(Char型)のリストを与えます。なお、以上のコードで生成されたリストの一部分を利用するだけでよく、最初と最後の文字が同じ英数字であるリストになるまで試行を続ける必要はありません。これは、List(a, b, d, e, f)が得られた場合に、List(a, b, d, e, a)のようにしても良いということです。
自分の回答
うまくいかずギブアップ・・・
var i = 0 while(i <= 1000){ val lst: List[Char] = new scala.util.Random(new java.security.SecureRandom()).alphanumeric.take(5).toList lst match { case List(a, b, c, d, e) if a == e => i += 1 println(lst) } }
模範解答
問題文の
なお、以上のコードで生成されたリストの一部分を利用するだけでよく、最初と最後の文字が同じ英数字であるリストになるまで試行を続ける必要はありません。これは、List(a, b, d, e, f)が得られた場合に、List(a, b, d, e, a)のようにしても良いということです。
これを実装すると実にすっきりします。あとforかwhileどっちで回すといいとかあるのかな。
for(i <- 1 to 1000) { val s = new scala.util.Random(new java.security.SecureRandom()).alphanumeric.take(5).toList match { case List(a,b,c,d,_) => List(a,b,c,d,a).mkString } println(s) }
この章での疑問点
if文の順序
age => 1 && age <=6 && !isSchoolStarted
だとNGで
1 <= age && 6 <= age && !isSchoolStarted
だとコンパイルが通るのはなぜだろうか・・・
値を取り出さないパターンマッチの使い所
- 値を取り出さないパターンマッチは可能なのはわかったけど、これいつ使うんだろう。
進捗
DONE
TODO
- クラス
- オブジェクト
- トレイト
- 型パラメータと変位指定
- 関数
- Scalaのコレクションライブラリ
- ケースクラスとパターンマッチング
- エラー処理
- Implicit
- 型クラスの紹介
- FutureとPromise
- テスト
- Javaとの相互運用
- S99の案内
- トレイトの応用編:依存性の注入によるリファクタリング
次回はクラスをやります。次回はいつだろう・・・年内にドワンゴテキスト終わらせたい。
ドワンゴScala研修テキスト学習中 #dwango #scala
私がdodosoftで得られたもの #dodosoft
この記事はdodosoft Advent Calendar 2016 2日目です。
昨日はddddbirdでした!
この記事について
私がdodosoftに参加して得られたものをまとめて、dodosoftメンバーに感謝の意を伝えたいための記事です。
dodosoftで得られたもの
- 旦那
- 勉強する習慣
- ソフトウェア工学の基礎
旦那
旦那とはdodosoftで出会いました。
出会いが勉強会なので、土日に勉強したり、勉強会に参加することに理解があります。
最近だともくもくデートしよう!って12時から21時くらいまでYahoo!のLODGEにこもって個室で勉強したり、エンジニアとしてのびのび活動するために支えてくれる最高のパートナーをdodosoftで見つけられました。
みんなありがとう!
勉強する習慣
これは一番大きいかなと思います。
学生時代まで専門的な勉強なんてテスト前と卒業研究くらいでしかやっていなかった自分にとって、同期は色々知っててすごいなと思って勉強しなきゃと焦ってたんですよね。今も焦ってますが。笑
そんなときに、入社して2,3ヶ月くらいかな?、定期的にすごい同期と時間かけて基礎的な部分を議論しながら勉強していると聞いて参加したいってなって。
ここに参加していなかったら技術もっとやりたいとは思ってなかっただろうし、本棚が技術書であふれることもなかっただろうし、仕事がこなせればいやーくらいにしかやってなかったと思います。
ソフトウェア工学の基礎
自分は高専卒で周りはほとんど大学院修士卒だったので、圧倒的に学んできた量が違って、それに負い目を感じていました。
しかも、ソフトウェア工学の基礎の部分ってなかなか社外イベントでもやらない。結構流行りのフレームワークとかが多い。
でも、新しいものを理解するためにやっぱり基礎って大事だなってすごい思うので、ソフトウェア工学の基礎を取り上げて時間かけて輪読することができて本当によかった。
これからもよろしく!
こんなにたくさんのものが得られるdodosoftなのでこれからも続けていきますー!
次回予告
明日の担当はYSKNです!前職同期だと最年少(私)から最年長(YSKN)へのバトン!w