x12. Scala(1/2)
eclispe で Scala プログラム開発の準備:
eclipse
-> パッケージエクスプローラを右クリック
-> 新規
-> その他
->Scala ウィザード
-> Scalaプロジェクト
プロジェクト名 Project7
練習用アプリケーション作成:
src フォルダ
→右クリック Scalaアプリ 作成
名前 Test
2017年度用変更点:
Scala ConsoleのREPLは不便な点があるので、Scala Interpreter を利用することにする。
ウインドウ → ビューの表示 → Scala Interpreter
コードを入力後、 Ctrl + Enter で実行。
複数行のコードを書いて、Ctrl + Enterでまとめて実行できる。カーソルの位置はどこにあってもOK
複数の式を評価できる。ブロックにしたり、; で複数の式を記述して実行できる。
※ 1+2;3+4;5+6 の実行結果は 11 になるが、1+2 と 3+4 の式は無駄なコードになるので、warning がでる。
Ctrl + ↑ ↓ で、履歴を辿れる。(行単位でなく、実行単位)
メニューに、コードのリセットや再実行のボタンがある。
:help など ScalaのREPLコマンドは使えない。
REPL(Read Eval Print Loop)の準備:
コンソール(+マークの付いたアイコン) ▼メニュー
→ Scala Console
REPLコンソールで以下を実行:
scala> 1+1
res0: Int = 2
scala> 2*3
res1: Int = 6
scala> "Hello world!"
res2: String = Hello world!
scala> "Hello world!".size
res3: Int = 12
scala> "abc" + "xyz"
res4: String = abcxyz
scala> println("Hello world!")
Hello world!
scala> println("Hello world!");
Hello world!
scala> println("Hello world!");1+1
Hello world!
res7: Int = 2
Test.scala ファイルを編集:
object Test {
def main(args: Array[String]) = {
println("Hello World!")
}
}
実行ボタンから実行:
次を実行 → Scala アプリケーション
・コンソールの出力を確認する
練習: Scala は 行末に ;(セミコロン) を置かず、そのまま改行して次の行にコマンドを並べておくことができる。
・println の行を増やしてメッセージを変えてみよう
・println を横に増やしてみよう(要 ; )
↑実行ボタンから動作を確認
main メソッドに以下を追記:
args.foreach( println )
↑実行ボタンから動作を確認
新しく、REPL(Read Eval Print Loop)を準備:
コンソール(+マークの付いたアイコン) ▼メニュー
→ Scala Console
REPLコンソールで以下を実行:
scala> Test
res11: Test.type = Test$@48075da3
scala> Array(1,2)
res14: Array[Int] = Array(1, 2)
scala> Test.main(Array())
Hello World!
Hello World!
scala> Test.main(Array("1","2"))
Hello World!
Hello World!
1
2
Test.scala ファイルを編集し以下を追記:
object Fib extends App {
val fib:Stream[Int] = 0 #:: 1 #:: fib.zip(fib.tail).map(p => p._1 + p._2)
println(fib.take(8).toList)
}
実行ボタンから実行:
次を実行 → Scala アプリケーション
アプリケーションの選択 → Fib
・コンソールの出力を確認する
※ フィボナッチ数列 について → 質問: 9番目 と 10番目のフィボナッチ数は?
take(8) を take(10) に書き変えて動作確認する。
動作原理:
・fib.take(3).toList
・fib.tail.take(3).toList
・fib.zip(fib.tail).take(3).toList
・fib.zip(fib.tail).map(p=>p._1+p._2).take(3).toList
コンソールをREPLに戻す:
コンソール(+マークが無いアイコン) ▼メニュー
→ Project7
REPLコンソールで以下を実行:
・遅延リストの利用例
・複数の値を処理するメソッド sum take foldLeft を利用してリストを処理
scala> List(1,2,3).zip("abc")
res7: List[(Int, Char)] = List((1,a), (2,b), (3,c))
scala> (0 to 10).zip(1 to 9)
res8: scala.collection.immutable.IndexedSeq[(Int, Int)] = Vector((0,1), (1,2), (2,3), (3,4), (4,5), (5,6), (6,7), (7,8), (8,9))
scala> (0 to 10).zip(1 to 11)
res9: scala.collection.immutable.IndexedSeq[(Int, Int)] = Vector((0,1), (1,2), (2,3), (3,4), (4,5), (5,6), (6,7), (7,8), (8,9), (9,10), (10,11))
scala> (0 to 10).zip(1 to 12)
res10: scala.collection.immutable.IndexedSeq[(Int, Int)] = Vector((0,1), (1,2), (2,3), (3,4), (4,5), (5,6), (6,7), (7,8), (8,9), (9,10), (10,11))
scala> List(1,2,3).zip("abc")
res7: List[(Int, Char)] = List((1,a), (2,b), (3,c))
scala> val fib:Stream[Int] = 0 #:: 1 #:: fib.zip(fib.tail).map(p => p._1 + p._2)
fib: Stream[Int] = <lazy>
scala> fib.take(10).toList
res20: List[Int] = List(0, 1, 1, 2, 3, 5, 8, 13, 21, 34)
scala> fib.take(20).toList
res21: List[Int] = List(0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181)
scala> fib.take(3).toList
res14: List[Int] = List(0, 1, 1)
scala> fib.tail.take(3).toList
res15: List[Int] = List(1, 1, 2)
scala> fib.zip(fib.tail).take(3).toList
res16: List[(Int, Int)] = List((0,1), (1,1), (1,2))
scala> fib.zip(fib.tail).map(p=>p._1+p._2).take(3).toList
res17: List[Int] = List(1, 2, 3)
scala> fib.take(10).sum
res22: Int = 88
scala> fib.take(8).foldLeft("")(_+_)
res23: String = 011235813
※
REPLコンソールで以下を実行:
・変数 と 値
・型推論
scala> var str = "Hello World"
str: String = Hello World
scala> str
res25: String = Hello World
scala> val str = "Hello World"
str: String = Hello World
scala> var a = 1
a: Int = 1
scala> var b = 1.0
b: Double = 1.0
scala> var c = "abc"
c: String = abc
scala> a
res26: Int = 1
scala> b
res27: Double = 1.0
scala> c
res28: String = abc
scala> var d = List("A","B")
d: List[String] = List(A, B)
scala> d(0)
res12: String = A
scala> d(1)
res13: String = B
scala> var str1 = "cat"
str1: String = cat
scala> str1
res29: String = cat
scala> str1 = "dog"
str1: String = dog
scala> str1
res30: String = dog
scala> val str2 = "cat"
str2: String = cat
scala> str2
res31: String = cat
scala> str2 = "dog"
<console>:12: error: reassignment to val
str2 = "dog"
^
scala> var str = "Cat"
str: String = Cat
scala> str = "Dog"
str: String = Dog
scala> str = 5
<console>:12: error: type mismatch;
found : Int(5)
required: String
str = 5
^
scala> List(1,2,3)
res32: List[Int] = List(1, 2, 3)
scala> List(1.0,2.0,3.0)
res33: List[Double] = List(1.0, 2.0, 3.0)
scala> List(1.0,2,3.0)
res34: List[Double] = List(1.0, 2.0, 3.0)
scala> List(1.0,"1",3.0)
res35: List[Any] = List(1.0, 1, 3.0)
REPLコンソールで以下を実行:
・メソッドの関数化
・関数オブジェクト
scala> def ninja(name:String) = println(name + "=san")
ninja: (name: String)Unit
scala> ninja("kobashi")
kobashi=san
scala> def sannin( f:String=>_ ) = List("kobashi","hasegawa","tajika").foreach( f )
sannin: (f: Function1[String, _])Unit
scala> sannin(println)
kobashi
hasegawa
tajika
scala> sannin(print)
kobashihasegawatajika
scala> sannin(ninja)
kobashi=san
hasegawa=san
tajika=san
scala> val f = ninja
<console>:12: error: missing argument list for method ninja
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `ninja _` or `ninja(_)` instead of `ninja`.
val f = ninja
^
scala> val f = ninja _
f: String => Unit = <function1>
scala> f("kobashi")
kobashi=san
scala> sannin(f)
kobashi=san
hasegawa=san
tajika=san
scala> sannin( (a:String) => f(a.take(4)))
koba=san
hase=san
taji=san
※↑の演習の参考元 http://www.slideshare.net/takeuchi-tk/scala-29314069?related=1 Scala勉強会 初心者向けハンズオン前編
2017年度向け例題変更案↑
List のアイテムを Talbe や ol ul としてHTMLで整形表示する。Sclaa ファンクショナルデザインの例題参照。
演習内容の保管:
コンソールパネルの”ファイルへ保管”アイコンから保存。
※2016年度ここまで※2016年度ここまで※2016年度ここまで※2016年度ここまで※2016年度ここまで※
以下、2015年度用資料
※以下のコードで、 main メソッドにコードを記述する必要は無い。例題のコードは修正予定。 App trait を利用しているので。
(参考記事1)
(参考記事2)
15分でざっくり分かるScala入門 #kzrb http://www.slideshare.net/SatoYu1ro/scala-36162790
遅延評価ストリームによるフィボナッチ数列の計算例)
object Fib extends App {
override def main(args: Array[String]) = {
lazy val fib:Stream[Int] = 0 #:: 1 #:: fib.zip(fib.tail).map(p => p._1 + p._2)
println(fib.take(8).toList)
}
}
ストリーム fib は、フィボナッチ数列として順に Int が取り出せる無限ストリーム。
ストリームから take で個数を指定してInt 列を取り出し、リストや文字列に加工して利用できる。
例)
scala> fib.take(8).toList
res1: List[Int] = List(0, 1, 1, 2, 3, 5, 8, 13)
scala> fib.take(8).toList.last
res2: Int = 13
scala> fib.take(8).foldLeft("")(_+_)
res3: String = 011235813
この様に、フィボナッチ数列の性質だけをプログラムしておけば、後からその使用個数や使用方法を変更しても、元のプログラムには修正が不要になる。
ブラウザ上の Scala 実行環境(コンパイル版) ideone こちらから、Scala で以下のコードを実行。
2015年度用指示: ↑は eclipse に scala プロジェクトを作成して scala app を作成から実行。
ハローワールド
object Main extends App {
override def main(args:Array[String]) = {
println("Hello World!")
}
}
↓サイトが消滅していた。
ブラウザ上の Scala 実行環境(REPL版) http://www.simplyscala.com/
解説記事 http://www.ne.jp/asahi/hishidama/home/tech/scala/scala.html
http://www.simplyscala.com/ の Tutorial-I の最初の方 と Tutorial-II の関数型プログラミングの部分で演習を行う。
ここのハンズオンの練習問題に、手を動かして取り組む。
http://www.slideshare.net/takeuchi-tk/scala-29314069?related=1 Scala勉強会 初心者向けハンズオン前編
2015年度用指示: ↓の 演習課題 の記述に従い scala 環境を D:ドライブにコピーして、 Scala REPL で↑を実行確認。
つづきは、次のWeb連載記事で、
http://itpro.nikkeibp.co.jp/article/COLUMN/20080613/308019/ 刺激を求める技術者に捧げるScala講座
第2回のScalaの基本文法 に取り組む。
応用 「エンジニアでも恋がしたい!」 http://paiza.jp/poh/enkoi の問題に Scala で挑戦
ヒント: 競技プログラミングにおけるScalaの標準入力を楽にする http://qiita.com/cohalz/items/a54bfc70e4bbc33440cb
例)標準入力からの INT値 の読み込み
object Main extends App { override def main(args:Array[String]) = { val sc = new java.util.Scanner(System.in) val a,b,c = sc.nextInt //a,b,cと順番にnextIntで代入されていく }}
提出物:
実行結果のテキストを、ブラウザから OneNote にコピーして提出。 ページを 第11回課題 で新規作成。
演習課題:
・環境構築
レポートフォルダ オブジェクト指向(小橋) にある scala フォルダを D: ドライブにコピー。 もしも時間がかかり過ぎるようなら、コピーしない方式も検討。
環境変数に java のパスを設定(2015年度の演習質環境では環境変数は設定済みなので作業不要)
JAVA_HOME = D:\java\8
windowsのコマンドプロンプトを開く
scala REPL の起動
Scalaのインストールされたフォルダに移動
> d:
> cd \scala\bin
> scala
(参考)
Javaでピコピコシンセを作ってみよう!(1) - ピコピコ音の正体を暴く http://www.hakkaku.net/articles/20090423-422
Programming music http://vigtig.it/blog/blog/2011/04/12/programming-music/
ビープ音の合成
import javax.sound.sampled._
// オーディオ形式を指定
val SAMPLE_RATE = 44100; // 44.1KHz
val audio_format = new AudioFormat(SAMPLE_RATE, 8, 1, true, true)
val line = AudioSystem.getSourceDataLine(audio_format)
line.open()
line.start()
// バイト列に適当な矩形波を作成
val frequency = 440
val b = new Array[Byte](SAMPLE_RATE)
for (i <- 0 to b.size) {
val r = i / (SAMPLE_RATE / frequency)
if( r % 2 == 0) { b(i) = 100 } else { b(i) = -100 }
}
// 再生(バイト列を line に書き込む)
line.write(b, 0, b.length);
line.drain(); // 終了まで待機
波形を修正する。
ループ部分の式を 調整して 音を変えてみる。
調整結果を、↑のテキストファイルに追記して提出。
(以下メモ)
C11情報実習室で、環境構築失敗
環境設定:
レポートフォルダから D:ドライブへコピー
activator-1.2.10
環境変数の設定
JAVA_HOME の追加
環境変数の設定変更:
HTTPS_Proxy
HTTP_Proxy
activator のフォルダに移動:
コマンドラインで以下を実行。
set HTTPS_Proxy=https://202.236.100.6:8080
set HTTP_Proxy=http://202.236.100.6:8080
(参照)
http://codezine.jp/article/detail/7580
Docker開発環境 - Typesafe ActivatorでScalaをインストール
http://masato.github.io/2014/06/29/docker-devenv-scala-typsafe-activator/
activator ui の起動:
コマンドプロンプトで
activator ui
REPL 環境でコマンド実行: