Programming in Scalaを読み始めた Chapter1-3

Chapter1はイントロ。Charpter2から本格的にはじまる。

まずはScalaのインストール

$ sudo port install scala

Scalaの起動とHello, world!など。すでに型推論が出てきている。

$ scala
Welcome to Scala version 2.7.4.final (Java HotSpot(TM) Client VM, Java 1.5.0_19).
Type in expressions to have them evaluated.
Type :help for more information.

scala> 1+2
res0: Int = 3

scala> res0*3
res1: Int = 9

scala> println("Hello, world!")
Hello, world!

変数宣言の方法はvalとvarがある。valだとimmutable

scala> val msg="Hello, world!"
msg: java.lang.String = Hello, world!

scala> println(msg)
Hello, world!

scala> msg="hoge"
<console>:5: error: reassignment to val
       msg="hoge"
          ^
scala> var hoge = "a"
hoge: java.lang.String = a

scala> hoge="b"
hoge: java.lang.String = b

関数はdefで宣言。Unitはvoidみたいなもん。

scala> def max(x: Int, y: Int): Int = {
     | if(x>y)x
     | else y
     | }
max: (Int,Int)Int

scala> max(1,2)
res5: Int = 2

scala> def greet() = println("Hello, world!")
greet: ()Unit

scala> greet
Hello, world!

whileループとコマンドライン引数

$ cat echoargs.scala 
var i = 0
while(i<args.length) {
  if(i!=0) {
    print(" ")
  }  
  print(args(i))
  i += 1
}
println()
$ scala echoargs.scala Scala is even more fun
Scala is even more fun

以下のような感じでも書ける

args.foreach(arg => println(arg))
args.foreach(println)
for(arg <- args)
  println(arg)

ここでChapter2終了。

Chapter3がはじまる。

Array(配列)。[0]じゃなくて(0)なのね。forの書き方が特殊ね。

$ cat greetStrings.scala 
val greetStrings = new Array[String](3)
greetStrings(0) = "Hello" 
greetStrings(1) = ", " 
greetStrings(2) = "world!\n"

for ( i <- 0 to 2)
  print(greetStrings(i))
$ scala greetStrings.scala
Hello, world!

List。これもimmutable。:::で連結。::はcons

scala> List(1,2) ::: List(3,4)
res10: List[Int] = List(1, 2, 3, 4)

scala> 1::List(2, 3)
res12: List[Int] = List(1, 2, 3)

scala> 1::2::3::Nil
res13: List[Int] = List(1, 2, 3)

タプル。これもimmutable。

scala> val tuple = (99, "Luftballons")
tuple: (Int, java.lang.String) = (99,Luftballons)

scala> tuple._1
res17: Int = 99

scala> tuple._2
res18: java.lang.String = Luftballons

ここまでがChapter3のStep9

Step10

Set。mutableとimmutableがあるらしい。

scala> import scala.collection.immutable.HashSet
import scala.collection.immutable.HashSet

scala> val hashSet = HashSet("Tomoatoes", "Chilies")
hashSet: scala.collection.immutable.Set[java.lang.String] = Set(Chilies, Tomoatoes)

scala> println(hashSet + "Coriander")
Set(Coriander, Chilies, Tomoatoes)

scala> Set("Boeing", "Airbus")
res23: scala.collection.immutable.Set[java.lang.String] = Set(Boeing, Airbus)

Map。これもmutableとimmutableがあるらしい。

scala> import scala.collection.mutable.Map
import scala.collection.mutable.Map

scala> val treasureMap = Map[Int, String]()
treasureMap: scala.collection.mutable.Map[Int,String] = Map()

scala> treasureMap += (1 -> "Go to island.")

scala> treasureMap += (2 -> "Find big X on ground.")

scala> treasureMap += (3 -> "Dig.")                 

scala> println(treasureMap(2))
Find big X on ground.

Step 11

scala> def formatArgs(args: Array[String]) = args.mkString("\n")
formatArgs: (Array[String])String

scala> val res = formatArgs(Array("zero", "one", "two"))        
res: String = 
zero
one
two

scala> assert(res == "zero\none\ntwo")

scala> assert(res == "zero\none\ntw") 
java.lang.AssertionError: assertion failed
	at scala.Predef$.assert(Predef.scala:87)
	at .<init>(<console>:7)
	at .<clinit>(<console>)
	at RequestResult$.<init>(<console>:3)
	at RequestResult$.<clinit>(<console>)
	at RequestResult$result(<console>)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.j...

Step12

IO処理なぞを。

$ cat countchars1.scala 
import scala.io.Source

if(args.length>0) {
  for(line <- Source.fromFile(args(0)).getLines)
    print(line.length + " " + line)
}
else
  Console.err.println("Please enter filename")
$ scala countchars1.scala countchars1.scala 
23 import scala.io.Source
1 
20 if(args.length>0) {
49   for(line <- Source.fromFile(args(0)).getLines)
36     print(line.length + " " + line)
2 }
5 else
47   Console.err.println("Please enter filename")

reduceLeftが関数型っぽいね。

$ cat countchars2.scala 
import scala.io.Source

def widthOfLength(s: String) = s.length.toString.length

if(args.length>0) {
  val lines = Source.fromFile(args(0)).getLines.toList

  val longuestLine = lines.reduceLeft(
    (a, b) => if(a.length > b.length) a else b
  )

  val maxWidth = widthOfLength(longuestLine)

  for(line<-lines) {
    val numSpaces = maxWidth - widthOfLength(line)
    val padding = " " * numSpaces
    print(padding + line.length + " | " + line)
  }
}
else
  Console.err.println("Please enter filename")
$ scala countchars2.scala countchars2.scala 
23 | import scala.io.Source
 1 | 
56 | def widthOfLength(s: String) = s.length.toString.length
 1 | 
20 | if(args.length>0) {
55 |   val lines = Source.fromFile(args(0)).getLines.toList
 1 | 
39 |   val longuestLine = lines.reduceLeft(
47 |     (a, b) => if(a.length > b.length) a else b
 4 |   )
 1 | 
45 |   val maxWidth = widthOfLength(longuestLine)
 1 | 
21 |   for(line<-lines) {
51 |     val numSpaces = maxWidth - widthOfLength(line)
34 |     val padding = " " * numSpaces
48 |     print(padding + line.length + " | " + line)
 4 |   }
 2 | }
 5 | else
47 |   Console.err.println("Please enter filename")