12. 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 環境でコマンド実行: