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