#onenote# scala

Scala Basic

      1. Exit  scala console

:quit

 

      1. Closure

closure is a function, whose return value depends on the value of one or more variables declared outside this function. Consider the following piece of code with anonymous function:

 

var factor = 3
val multiplier = (i:Int) => i * factor

There are two free variables in multiplier: i and factor. One of them, i, is a formal parameter to the function. Hence, it is bound to a new value each time multiplier is called. However, factor is not a formal parameter.

 

      1. 特质Trait

A trait  encapsulates method and field definitions, which can then be reused by mixing them into classes. Unlike class inheritance, in which each class must inherit from just one superclass, a class can mix in any number of traits.

特质是一些字段和行为的集合,可以扩展或混入(mixin)你的类中。

trait Car {
val brand: String
}

trait Shiny {
val shineRefraction: Int
}

class BMW extends Car {
val brand = “BMW”
}

 

通过with关键字,一个类可以扩展多个特质:

class BMW extends Car with Shiny {
val brand = “BMW”
val shineRefraction = 12
}

 

 

      1. Unit类型  = void

 

 

      1. Imperative Programing (Java)  – Mutable, share resource (makes race contention), control (IF THEN ELSE)

Functional Programing  (Scala)

 

Call-by-name vs. Call-by-value

Call-by-value   :  compute the passed-in expression’s value before calling the function

Call-by-name  :  recompute the passed-in expression’s value every time it is accessed.

 

Scala normally uses call-by-value

But if the type of a function param starts with => it uses call-by-name

 

def f(x: => Int, y:Int) = x

This way the parameter x will not be evaluated until it’s called in the function. If the parameter is never used, it is never evaluated. If it is used multiple times, it is evaluated each time.

 

      1. Currying

Def  f(args1)…(argN) = E  Where N >1, is equivalent to def f(arg1)..(argsN-1) = {def g(argsN) =E; g}

Where g is a fresh identifier. Or for short

Def f(args1) ..(argsN-1) = (argsn=>E)

 

 

      1. Nil是一个空的List,定义为List[Nothing],根据List的定义List[+A],所有Nil是所有List[T]的子类

 

 

  • Case Class(样本类)

 

      • Scala会给case类自动添加一个单例对象
      • 使用样本类可以方便得存储和匹配类的内容。你不用new关键字就可以创建它们
      • 默认是Immutable
      • Scala编译器负责(根据字段)给Case类重写toString()、hashCode()和equals()方法。
      • 样本类就是被设计用在模式匹配中

 

      1. 不变量val

可以给一个表达式的结果起个名字赋成一个不变量(val), 你不能改变这个不变量的值.

变量 var

能改变这个变量的值

 

 

  • 函数

 

使用def创建函数.

e.g

def addOne(m: Int): Int = m + 1

      • m:Int   <– argument
      • (Last ) Int  <–  return type
      • m+ 1 <– func body

 

 

  • 匿名函数

 

e.g  (x: Int) => x + 1

 

传递匿名函数,或将其保存成不变量

val addOne = (x: Int) => x + 1

 

 

  • 可变长度参数

 

这是一个特殊的语法,可以向方法传入任意多个同类型的参数。例如要在多个字符串上执行String的capitalize函数,可以这样写:

def capitalizeAll(args: String*) = {
args.map { arg =>
arg.capitalize
}
}

scala> capitalizeAll(“rarity”, “applejack”)
res2: Seq[String] = ArrayBuffer(Rarity, Applejack)

 

 

  • apply 方法

 

当类或对象有一个主要用途的时候,apply方法为你提供了一个很好的语法糖。

apply方法是用于在构造对象时,减少new关键字

 

scala> class Foo {}
defined class Foo

scala> object FooMaker {
|   def apply() = new Foo
| }
defined module FooMaker

scala> val newFoo = FooMaker()
newFoo: Foo = Foo@5b83f762

scala> class Bar {
|   def apply() = 0
| }
defined class Bar

scala> val bar = new Bar
bar: Bar = Bar@47711479

scala> bar()
res8: Int = 0

在这里,我们实例化对象看起来像是在调用一个方法。

apply语法糖有助于统一对象和函数式编程的二重性。你可以传递类,并把它们当做函数使用,而函数本质上是类的实例

 

 

 

  • 单例对象(object )

 

单例对象用于持有一个类的唯一实例。通常用于工厂模式。

object Timer {
var count = 0

def currentCount(): Long = {
count += 1
count
}
}

可以这样使用:

scala> Timer.currentCount()
res0: Long = 1

单例对象可以和类具有相同的名称,此时该对象也被称为“伴生对象”。我们通常将伴生对象作为工厂使用。

下面是一个简单的例子,可以不需要使用’new’来创建一个实例了。

class Bar(foo: String)

object Bar {
def apply(foo: String) = new Bar(foo)
}

 

  • Class

 

A class is a blueprint for objects. Once you define a class, you can create objects from the class blueprint with the keyword new

 

类也可以扩展Function,这些类的实例可以使用()调用。

scala> class AddOne extends Function1[Int, Int] {
|   def apply(m: Int): Int = m + 1
| }
defined class AddOne

scala> val plusOne = new AddOne()
plusOne: AddOne = <function1>
scala> plusOne(1)
res0: Int = 2
可以使用更直观快捷的extends (Int => Int)代替extends Function1[Int, Int]

class AddOne extends (Int => Int) {
def apply(m: Int): Int = m + 1
}

 

 

  • 元组 Tuple

 

元组是在不使用类的前提下,将元素组合起来形成简单的逻辑集合

scala> val hostPort = (“localhost”, 80)
hostPort: (String, Int) = (localhost, 80)

在创建两个元素的元组时,可以使用特殊语法:->

scala> 1 -> 2
res0: (Int, Int) = (1,2)

 

 

  • 映射 Map

 

它可以持有基本数据类型。

Map(1 -> 2)
Map(“foo” -> “bar”)

这看起来像是特殊的语法,不过不要忘了上文讨论的->可以用来创建二元组。

Map()方法也使用了从第一节课学到的变参列表:Map(1 -> “one”, 2 -> “two”)将变为 Map((1, “one”), (2, “two”)),其中第一个参数是映射的键,第二个参数是映射的值。

映射的值可以是映射甚或是函数

Map(1 -> Map(“foo” -> “bar”))

 

 

  • 选项 Option

 

Option 是一个表示有可能包含值的容器。

Option基本的接口是这样的:

trait Option[T] {
def isDefined: Boolean
def get: T
def getOrElse(t: T): T
}

Option本身是泛型的,并且有两个子类: Some[T] 或 None

我们看一个使用Option的例子:

Map.get 使用 Option 作为其返回值,表示这个方法也许不会返回你请求的值。

scala> val numbers = Map(1 -> “one”, 2 -> “two”)
numbers: scala.collection.immutable.Map[Int,String] = Map((1,one), (2,two))

scala> numbers.get(2)
res0: Option[java.lang.String] = Some(two)

scala> numbers.get(3)
res1: Option[java.lang.String] = None

 

      1. Scala 提供了一种普通的函数方法,打破了这一僵局。在某些方面,Option 类型或 Option[T],并不重视描述。它是一个具有两个子类 Some[T] 和 None 的泛型类,用来表示 “无值” 的可能性,而不需要语言类型系统大费周折地支持这个概念。实际上,使用 Option[T] 类型可以使问题更加清晰

注意:Option[T]里面的数据写法是Some(2)而不是2

 

 

 

 

  • 函数组合子(Functional Combinators

 

List(1, 2, 3) map squared对列表中的每一个元素都应用了squared平方函数,并返回一个新的列表List(1, 4, 9)。我们称这个操作map 组合子。 (如果想要更好的定义,你可能会喜欢Stackoverflow上对组合子的说明。)他们常被用在标准的数据结构上。

map

map对列表中的每个元素应用一个函数,返回应用后的元素所组成的列表。

scala> numbers.map((i: Int) => i * 2)
res0: List[Int] = List(2, 4, 6, 8)

或传入一个部分应用函数

scala> def timesTwo(i: Int): Int = i * 2
timesTwo: (i: Int)Int

scala> numbers.map(timesTwo _)
res0: List[Int] = List(2, 4, 6, 8)

foreach

foreach很像map,但没有返回值。foreach仅用于有副作用[side-effects]的函数。

scala> numbers.foreach((i: Int) => i * 2)

 

filter

filter移除任何对传入函数计算结果为false的元素。返回一个布尔值的函数通常被称为谓词函数[或判定函数]。

scala> numbers.filter((i: Int) => i % 2 == 0)
res0: List[Int] = List(2, 4)

 

zip

zip将两个列表的内容聚合到一个对偶列表中。

scala> List(1, 2, 3).zip(List(“a”, “b”, “c”))
res0: List[(Int, String)] = List((1,a), (2,b), (3,c))

 

Pasted from <https://twitter.github.io/scala_school/zh_cn/collections.html>

 

partition

partition将使用给定的谓词函数分割列表。

scala> val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala> numbers.partition(_ % 2 == 0)
res0: (List[Int], List[Int]) = (List(2, 4, 6, 8, 10),List(1, 3, 5, 7, 9))

 

find

find返回集合中第一个匹配谓词函数的元素。

scala> numbers.find((i: Int) => i > 5)
res0: Option[Int] = Some(6)

 

drop & dropWhile

drop 将删除前i个元素

scala> numbers.drop(5)
res0: List[Int] = List(6, 7, 8, 9, 10)

dropWhile 将删除元素直到找到第一个匹配谓词函数的元素。例如,如果我们在numbers列表上使用dropWhile奇数的函数, 1将被丢弃(但3不会被丢弃,因为他被2“保护”了)。

scala> numbers.dropWhile(_ % 2 != 0)
res0: List[Int] = List(2, 3, 4, 5, 6, 7, 8, 9, 10

 

 

flatten

flatten将嵌套结构扁平化为一个层次的集合。

scala> List(List(1, 2), List(3, 4)).flatten
res0: List[Int] = List(1, 2, 3, 4)

 

 

 

foldLeft 向左折叠

简写 /:

(0/:(1 to 100))(_+_)

等价于

(1 to 100).foldLeft(0)(_+_)

 

foldRight  向右折叠

((1 to 5):\100)((i,sum)=> sum-i)

 

 

flatMap

flatMap是一种常用的组合子,结合映射[mapping]和扁平化[flattening]。 flatMap需要一个处理嵌套列表的函数,然后将结果串连起来。

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

scala> nestedNumbers.flatMap(x => x.map(_ * 2))
res0: List[Int] = List(2, 4, 6, 8)

可以把它看做是“先映射后扁平化”的快捷操作:

scala> nestedNumbers.map((x: List[Int]) => x.map(_ * 2)).flatten
res1: List[Int] = List(2, 4, 6, 8)

这个例子先调用map,然后可以马上调用flatten,这就是“组合子”的特征,也是这些函数的本质。

函数组合

让我们创建两个函数:

scala> def f(s: String) = “f(” + s + “)”
f: (String)java.lang.String

scala> def g(s: String) = “g(” + s + “)”
g: (String)java.lang.String

compose

compose 组合其他函数形成一个新的函数 f(g(x))

scala> val fComposeG = f _ compose g _
fComposeG: (String) => java.lang.String = <function>

scala> fComposeG(“yay”)
res0: java.lang.String = f(g(yay))

andThen

andThen 和 compose很像,但是调用顺序是先调用第一个函数,然后调用第二个,即g(f(x))

scala> val fAndThenG = f _ andThen g _
fAndThenG: (String) => java.lang.String = <function>

scala> fAndThenG(“yay”)
res1: java.lang.String = g(f(yay))

 

 

In Scala arrays are immutable objects. You create an array like this:

var myArray : Array[String] = new Array[String](10);

 

 

  • to vs. until

 

You can use either the keyword to or until when creating a Range object. The difference is, that to includes the last value in the range, whereas until leaves it out. Here are two examples:

for(i <- 1 to 10) {
println(“i is ” + i);
}

for(i <- 1 until 10) {
println(“i is ” + i);
}

 

 

 

 

  • Scala  

 

Seq(“a”, “b”, “c”)   =  (Java) Arrays.asList(“a”, “b”, “c”);

 

 

Productive tips

IDE Setup for Eclipse or Intellj

      1. Open $ ~/.sbt/plugins/build.sbt (Mac/Linux) or %userprofile%\.sbt\plugins\build.sbt (Windows)
      2. Add the following lines (the empty line in between is important)
        addSbtPlugin(“com.typesafe.sbteclipse” % “sbteclipse-plugin” % “2.2.0”)

        addSbtPlugin(“com.github.mpeltonen” % “sbt-idea” % “1.4.0”)

        (see https://github.com/typesafehub/sbteclipse and https://github.com/mpeltonen/sbt-idea for more details)

      3. for Eclipse, in the project folder, type sbt eclipse, if you want to download sources addwith-source=true e.g. sbt eclipse with-source=true
      4. To open the project in Eclipse: File -> Import -> Existing Projects into Workspace
      5. for Intellij IDEA, in the project folder, type sbt gen-idea
        NOTE: Intellij just released a new early release SBT plugin (July 17, 2013) – which can import SBT projects without the need for sbt gen-idea

Pasted from <http://scalatutorials.com/beginner/2013/07/18/getting-started-with-sbt/>

 

Using Intellj

New Project

  1. create sbt project
  2. create src folder
  3. new scala class
  4. add java jdk lib
  5. run (after build)
  6. create missing output folder manually (bug in previsous scala plguin) <– if missing class folder error raised

7 new scala worksheet -> code in worksheet can be running  in console

 

Existing project

  1. create sbt project
  2. point the the project folder to the existing project folder

 

TDD

  1. create a class first
  2. update the build.sbt
  3. libraryDependencies +=”org.scalatest” % “scalatest_2.10” % “2.1.0” % “test”
  4. right click the method, select “create testing”
  5. run the test

 

Evaluation of Scala Objects in worksheet is supported since Scala plugin v0.6. The one in intellj13.16 isn’t supported yet. Use scalaIDE or Eclipse with Scala plugin instead

 

Exsiting project

  1. import from build.sbt file
  2. run the test

https://www.youtube.com/watch?v=Ok7gYD1VbNw

 

Create new test

Work with Java

您可以通过JavaConverters package轻松地在Java和Scala的集合类型之间转换。它用asScala 装饰常用的Java集合以和用asJava 方法装饰Scala集合。

import scala.collection.JavaConverters._
val sl = new scala.collection.mutable.ListBuffer[Int]
val jl : java.util.List[Int] = sl.asJava
val sl2 : scala.collection.mutable.Buffer[Int] = jl.asScala
assert(sl eq sl2)

双向转换:

scala.collection.Iterable <=> java.lang.Iterable
scala.collection.Iterable <=> java.util.Collection
scala.collection.Iterator <=> java.util.{ Iterator, Enumeration }
scala.collection.mutable.Buffer <=> java.util.List
scala.collection.mutable.Set <=> java.util.Set
scala.collection.mutable.Map <=> java.util.{ Map, Dictionary }
scala.collection.mutable.ConcurrentMap <=> java.util.concurrent.ConcurrentMap

此外,也提供了以下单向转换

scala.collection.Seq => java.util.List
scala.collection.mutable.Seq => java.util.List
scala.collection.Set => java.util.Set
scala.collection.Map => java.util.Map

 

Pasted from <https://twitter.github.io/scala_school/zh_cn/coll2.html>

 

Scala + maven

  1. Create maven project
  2. Fill

<groupId>net.alchim31.maven</groupId>

<artifactId>scala-archetype-simple</artifactId>

<version>1.6</version>

Repo url:  http://repo1.maven.org/maven2/archetype-catalog.xml

 

 

动态属性、方法

Scala 2.10.0 新特性之动态属性、方法

2013-01-20 — Yanbin

最早的介绍 Scala 语言的书都是以 Scala 的静态类型系统为傲。Scala 也算是个脚本语言,却不像其他许多脚本语言那样类型是动态的,只有执行时才确定,而 Scala 在执行前就确定了类型,比如依赖于比 Java 更强大的类型推断行为。

静态类型不光是变量类型是确定的,还有比如在使用  qual.sel 时,sel 这个属性或是方法(Scala 的访问一致性,属性和方法有时候并没有那么大的区别)必须在 qual 的类型中声明了的。

Scala 思考再三还是加入了 Dynamic Types,这个特性在 Scala 2.9 中是试验性的,必须用 -Xexperimental 进行开启,到了 Scala 2.10.0 中,只有代码中 import scala.language.dynamics 就可用了,或是编译时加 -language:dynamics 选项。

虽然 Scala 2.10.0 加进了 Dynamic Types 特性,但 Scala 仍然是静态类型的语言,因为在编译器同样会检查多出来的类型。

有了 Dynamic Types 之后,Scala 又可更 DSL 了,方法名的动态上可以让它随时包括深刻的业务含义。相比 Java  DSL 的能力就太逊了,我们几乎无法在 Java 面前提 DSL 这回事。

通俗点讲动态类型的类必须继承自 Dynamic,当使用 qual.sel,而 Qual 类未定义 sel 属性或方法时; 会调用 selectDynamic(method: String) 方法,当 qual.name = “Unmi” 时会调用类似 updateDynamic(method: String)(args: Any) 这样的方法; 还有 applyDynamicapplyDynamicNamed 这两个方法的自动调用。

所有的变化就在下面这四个方法中:

selectDynamic

updateDynamic

applyDynamic

applyDynamicNamed

看个完整的例子,我不打算把上面四个方法的应用规则分开来演示:

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

import scala.language.dynamics

class Person extends Dynamic{

    def selectDynamic(method: String){

        println(s“selectDynamic->$method called\n”)

    }

    def applyDynamic(method: String)(args: Any*){

        println(s“applyDynamic->$method called, args: $args\n”)

    }

    def updateDynamic(method: String)(args: Any){

        println(s“updateDynamic->$method called, args: $args\n”)

    }

    def applyDynamicNamed(method: String)(args: (String, Any)*) {

      println(s“applyDynamicNamed->$method called, args: $args”)

      for((key, value) <- args){

          println(s“key: $key, value: $value”)

      }

    }

}

val p = new Person

p.sayHello  //calll selectDynamic

p.config(“Hello”,“Unmi”) //call applyDynamic

p.products = (“iPhone”,“Nexus”) //call updateDynamic

p.showInfo(screenName=“Unmi”, email=“fantasia@sina.com”) //call applyDynamicNamed

上面对 p 的每一个调用都说明了会委派给哪个动态方法,执行结果输出是:

1

2

3

4

5

6

7

8

9

selectDynamic->sayHello called

applyDynamic->config called, args: WrappedArray(Hello, Unmi)

updateDynamic->products called, args: (iPhone,Nexus)

applyDynamicNamed->showInfo called, args: WrappedArray((screenName,Unmi), (email,fantasia@sina.com))

key: screenName, value: Unmi

key: email, value: fantasia@sina.com

现在来看发生了什么,Person 继承自  Dynamic,并且有引入 scala.language.dynamics。对 p 调用的方法(属性都不存在,但是都调用到了正常的动态方法。所以仍然要对这四个动态方法(确切的讲是四种类型的方法,因为比如你可以定义多个不同的 updateDynamic 方法,其余三个也同此分别加以说明:

1. selectDynamic

在调用找不到了无参方法时,会去寻找它,调用效果如下:

p.sayHello  也可以写成  p.selectDynamic(“sayHello”)

也就是说编译器在看到 p.sayHello 调用会根据  selectDynamic(method: String) 相当于创建了方法 def sayHello = …….,也就是把动态方法 selectDynamic(method: String) 换成   sayHello 却是。所以说 Scala  Dynamic 类中的 xxxDynamic 方法相当是模板方法。

applyDynamicupdateDynamic   applyDynamicNamed 这三个方法第二个括号中的参数类型,或个数需根据实际应用来定。这四个动态方法的第一个括号中的参数都是动态调用时的方法名。

2. applyDynamic

在进行有参数的方法调用时,会去找寻它,调用效果如下:

p.config(“Hello”, “Unmi”) 可以写成 p.applyDynamic(“config”)(“Hello”, “Unmi”)

还是这么理解: 把这个动态方法定义的方法名和第一个括号与参数替换成调用的方法名就知道怎么回事,例如把:

def applyDynamic(method: String)(args: Any*) 中的 applyDynamic(method: String) 替换成被调用方法名  config,就是:

def config(args: Any*)        //p.config(“Hello”, “Unmi”) 要调用的就是这么个方法

所以第二个括号中的参数由你自己来定,比如说想这么调用 p.config(“Hello”, 100, 30),那么你可的动态方法可以这么定义:

def applyDynamic(method: String)(greeting: String, high: Int, low: Int) { …… }

这个规则同样适用于 updateDynamic   applyDynamicNamed 这两个方法。

3. updateDynamic

等号赋值操作时会调用 updateDynamic 方法,调用效果如下:

p.products = (“iPhone”, “Nexus”)  可写成 p.updateDynamic(“products”)((“iPhone”, “Nexus”)),按照同样的理解方法,相当于 Person 中定义了 def products(args: Any) 方法。

4. applyDynamicNamed

同样是 apply 开头,所以这个方法是对 applyDynamic 方法的补充,即使没有 applyDynamicNamed,单用 applyDynamic 也能达成我们的要求。applyDynamicNamed 只是让你用命名参数调用时方便,也就是像

p.showInfo(screenName=”Unmi”, email=”fantasia@sina.com”) 这样用命名参数的方式来调用动态方法时会调用 updateDynamicNamed 方法。有了这个方法在命名传递参数就方便处理 key/value 值。

这四个方法在一个动态类中只能分别定义一个版本,否则会产生二义性,这和普通方法的重载不一样的。柯里化后的函数第二个括号中的参数可根据实际调用来定义,定义成  (args: Any*) 可包打天下。

Pasted from <http://unmi.cc/scala-2-10-0-new-feature-dynamic/>

Concurrency in Scala

      • Runnable/Callable

Runnable has a single method that returns no value.

trait Runnable {
def run(): Unit
}

Callable is similar to run except that it returns a value

trait Callable[V] {
def call(): V
}

Threads

Scala concurrency is built on top of the Java concurrency model.

On Sun JVMs, with a IO-heavy workload, we can run tens of thousands of threads on a single machine.

A Thread takes a Runnable. You have to call start on a Thread in order for it to run the Runnable.

scala> val hello = new Thread(new Runnable {
def run() {
println(“hello world”)
}
})
hello: java.lang.Thread = Thread[Thread-3,5,main]

scala> hello.start
hello world

When you see a class implementing Runnable, you know it’s intended to run in a Thread somewhere by somebody.

Something single-threaded

Here’s a code snippet that works but has problems.

import java.net.{Socket, ServerSocket}
import java.util.concurrent.{Executors, ExecutorService}
import java.util.Date

class NetworkService(port: Int, poolSize: Int) extends Runnable {
val serverSocket = new ServerSocket(port)

def run() {
while (true) {
// This will block until a connection comes in.
val socket = serverSocket.accept()
(new Handler(socket)).run()
}
}
}

class Handler(socket: Socket) extends Runnable {
def message = (Thread.currentThread.getName() + “\n”).getBytes

def run() {
socket.getOutputStream.write(message)
socket.getOutputStream.close()
}
}

(new NetworkService(2020, 2)).run

Each request will respond with the name of the current Thread, which is always main.

The main drawback with this code is that only one request at a time can be answered!

You could put each request in a Thread. Simply change

(new Handler(socket)).run()

to

(new Thread(new Handler(socket))).start()

but what if you want to reuse threads or have other policies about thread behavior?

Executors

With the release of Java 5, it was decided that a more abstract interface to Threads was required.

You can get an ExecutorService using static methods on the Executors object. Those methods provide you to configure an ExecutorService with a variety of policies such as thread pooling.

Here’s our old blocking network server written to allow concurrent requests.

import java.net.{Socket, ServerSocket}
import java.util.concurrent.{Executors, ExecutorService}
import java.util.Date

class NetworkService(port: Int, poolSize: Int) extends Runnable {
val serverSocket = new ServerSocket(port)
val pool: ExecutorService = Executors.newFixedThreadPool(poolSize)

def run() {
try {
while (true) {
// This will block until a connection comes in.
val socket = serverSocket.accept()
pool.execute(new Handler(socket))
}
} finally {
pool.shutdown()
}
}
}

class Handler(socket: Socket) extends Runnable {
def message = (Thread.currentThread.getName() + “\n”).getBytes

def run() {
socket.getOutputStream.write(message)
socket.getOutputStream.close()
}
}

(new NetworkService(2020, 2)).run

Here’s a transcript connecting to it showing how the internal threads are re-used.

$ nc localhost 2020
pool-1-thread-1

$ nc localhost 2020
pool-1-thread-2

$ nc localhost 2020
pool-1-thread-1

$ nc localhost 2020
pool-1-thread-2

Futures

A Future represents an asynchronous computation. You can wrap your computation in a Future and when you need the result, you simply call a blocking get()method on it. An Executor returns a Future. If you use the Finagle RPC system, you use Future instances to hold results that might not have arrived yet.

A FutureTask is a Runnable and is designed to be run by an Executor

val future = new FutureTask[String](new Callable[String]() {
def call(): String = {
searcher.search(target);
}})
executor.execute(future)

Now I need the results so let’s block until its done.

val blockingResult = future.get()

See AlsoScala School’s Finagle page has plenty of examples of using Futures, including some nice ways to combine them. Effective Scala has opinions aboutFutures .

Thread Safety Problem

class Person(var name: String) {
def set(changedName: String) {
name = changedName
}
}

This program is not safe in a multi-threaded environment. If two threads have references to the same instance of Person and call set, you can’t predict what namewill be at the end of both calls.

In the Java memory model, each processor is allowed to cache values in its L1 or L2 cache so two threads running on different processors can each have their own view of data.

Let’s talk about some tools that force threads to keep a consistent view of data.

Three tools

synchronization

Mutexes provide ownership semantics. When you enter a mutex, you own it. The most common way of using a mutex in the JVM is by synchronizing on something. In this case, we’ll synchronize on our Person.

In the JVM, you can synchronize on any instance that’s not null.

class Person(var name: String) {
def set(changedName: String) {
this.synchronized {
name = changedName
}
}
}

volatile

With Java 5’s change to the memory model, volatile and synchronized are basically identical except with volatile, nulls are allowed.

synchronized allows for more fine-grained locking. volatile synchronizes on every access.

class Person(@volatile var name: String) {
def set(changedName: String) {
name = changedName
}
}

AtomicReference

Also in Java 5, a whole raft of low-level concurrency primitives were added. One of them is an AtomicReference class

import java.util.concurrent.atomic.AtomicReference

class Person(val name: AtomicReference[String]) {
def set(changedName: String) {
name.set(changedName)
}
}

Does this cost anything?

@AtomicReference is the most costly of these two choices since you have to go through method dispatch to access values.

volatile and synchronized are built on top of Java’s built-in monitors. Monitors cost very little if there’s no contention. Since synchronized allows you more fine-grained control over when you synchronize, there will be less contention so synchronized tends to be the cheapest option.

When you enter synchronized points, access volatile references, or deference AtomicReferences, Java forces the processor to flush their cache lines and provide a consistent view of data.

PLEASE CORRECT ME IF I’M WRONG HERE. This is a complicated subject, I’m sure there will be a lengthy classroom discussion at this point.

Other neat tools from Java 5

As I mentioned with AtomicReference, Java 5 brought many great tools along with it.

CountDownLatch

A CountDownLatch is a simple mechanism for multiple threads to communicate with each other.

val doneSignal = new CountDownLatch(2)
doAsyncWork(1)
doAsyncWork(2)

doneSignal.await()
println(“both workers finished!”)

Among other things, it’s great for unit tests. Let’s say you’re doing some async work and want to ensure that functions are completing. Simply have your functionscountDown the latch and await in the test.

AtomicInteger/Long

Since incrementing Ints and Longs is such a common task, AtomicInteger and AtomicLong were added.

AtomicBoolean

I probably don’t have to explain what this would be for.

ReadWriteLocks

ReadWriteLock lets you take reader and writer locks. reader locks only block when a writer lock is taken.

Lets build an unsafe search engine

Here’s a simple inverted index that isn’t thread-safe. Our inverted index maps parts of a name to a given User.

This is written in a naive way assuming only single-threaded access.

Note the alternative default constructor this() that uses a mutable.HashMap

import scala.collection.mutable

case class User(name: String, id: Int)

class InvertedIndex(val userMap: mutable.Map[String, User]) {

def this() = this(new mutable.HashMap[String, User])

def tokenizeName(name: String): Seq[String] = {
name.split(” “).map(_.toLowerCase)
}

def add(term: String, user: User) {
userMap += term -> user
}

def add(user: User) {
tokenizeName(user.name).foreach { term =>
add(term, user)
}
}
}

I’ve left out how to get users out of our index for now. We’ll get to that later.

Lets make it safe

In our inverted index example above, userMap is not guaranteed to be safe. Multiple clients could try to add items at the same time and have the same kinds of visibility errors we saw in our first Person example.

Since userMap isn’t thread-safe, how we do we keep only a single thread at a time mutating it?

You might consider locking on userMap while adding.

def add(user: User) {
userMap.synchronized {
tokenizeName(user.name).foreach { term =>
add(term, user)
}
}
}

Unfortunately, this is too coarse. Always try to do as much expensive work outside of the mutex as possible. Remember what I said about locking being cheap if there is no contention. If you do less work inside of a block, there will be less contention.

def add(user: User) {
// tokenizeName was measured to be the most expensive operation.
val tokens = tokenizeName(user.name)

tokens.foreach { term =>
userMap.synchronized {
add(term, user)
}
}
}

SynchronizedMap

We can mixin synchronization with a mutable HashMap using the SynchronizedMap trait.

We can extend our existing InvertedIndex to give users an easy way to build the synchronized index.

import scala.collection.mutable.SynchronizedMap

class SynchronizedInvertedIndex(userMap: mutable.Map[String, User]) extends InvertedIndex(userMap) {
def this() = this(new mutable.HashMap[String, User] with SynchronizedMap[String, User])
}

If you look at the implementation, you realize that it’s simply synchronizing on every method so while it’s safe, it might not have the performance you’re hoping for.

Java ConcurrentHashMap

Java comes with a nice thread-safe ConcurrentHashMap. Thankfully, we can use JavaConverters to give us nice Scala semantics.

In fact, we can seamlessly layer our new, thread-safe InvertedIndex as an extension of the old unsafe one.

import java.util.concurrent.ConcurrentHashMap
import scala.collection.JavaConverters._

class ConcurrentInvertedIndex(userMap: collection.mutable.ConcurrentMap[String, User])
extends InvertedIndex(userMap) {

def this() = this(new ConcurrentHashMap[String, User] asScala)
}

Lets load our InvertedIndex

The naive way
trait UserMaker {
def makeUser(line: String) = line.split(“,”) match {
case Array(name, userid) => User(name, userid.trim().toInt)
}
}

class FileRecordProducer(path: String) extends UserMaker {
def run() {
Source.fromFile(path, “utf-8”).getLines.foreach { line =>
index.add(makeUser(line))
}
}
}

For every line in our file, we call makeUser and then add it to our InvertedIndex. If we use a concurrent InvertedIndex, we can call add in parallel and since makeUser has no side-effects, it’s already thread-safe.

We can’t read a file in parallel but we can build the User and add it to the index in parallel.

A solution: Producer/Consumer

A common pattern for async computation is to separate producers from consumers and have them only communicate via a Queue. Let’s walk through how that would work for our search engine indexer.

import java.util.concurrent.{BlockingQueue, LinkedBlockingQueue}

// Concrete producer
class Producer[T](path: String, queue: BlockingQueue[T]) extends Runnable {
def run() {
Source.fromFile(path, “utf-8”).getLines.foreach { line =>
queue.put(line)
}
}
}

// Abstract consumer
abstract class Consumer[T](queue: BlockingQueue[T]) extends Runnable {
def run() {
while (true) {
val item = queue.take()
consume(item)
}
}

def consume(x: T)
}

val queue = new LinkedBlockingQueue[String]()

// One thread for the producer
val producer = new Producer[String](“users.txt”, q)
new Thread(producer).start()

trait UserMaker {
def makeUser(line: String) = line.split(“,”) match {
case Array(name, userid) => User(name, userid.trim().toInt)
}
}

class IndexerConsumer(index: InvertedIndex, queue: BlockingQueue[String]) extends Consumer[String](queue) with UserMaker {
def consume(t: String) = index.add(makeUser(t))
}

// Let’s pretend we have 8 cores on this machine.
val cores = 8
val pool = Executors.newFixedThreadPool(cores)

// Submit one consumer per core.
for (i <- i to cores) {
pool.submit(new IndexerConsumer[String](index, q))
}

在Scala中创建事务

Scala中创建事务

我们之前已经看到了如何在Java中创建事务(并且我假设你已经阅读过那一部分,所以这里我们就不再赘述了),下面我们将会在Scala中用更少的代码来完成同样的功能。我们之所以能兼顾简洁与功能,部分得益于Scala自身简洁的特点,但更多还是由于Akka API使用了闭包/函数值(closures/function values)的缘故。

相比Java的繁冗,我们在Scala中可以通过很简洁的方法来创建事务。我们所需要做的只是调用一下Stm的auomic()函数就行了,如下所示:

1 atomic  {
2     //code  to  run  in  a  transaction….
3     /*  return  */  resultObject
4 }

其中,我们传给atomic()的闭包/函数值仅在当前线程所运行的那个事务内可见。

下面就是使用了Akka事务的Scala版本的EnergySource实现代码:

01 class  EnergySource  private()  {
02     private  val  MAXLEVEL  =  100L
03     val  level  =  Ref(MAXLEVEL)
04     val  usageCount  =  Ref(0L)
05     val  keepRunning  =  Ref(true)
06     private  def  init()  =  {
07         EnergySource.replenishTimer.schedule(new  Runnable()  {
08             def  run()  =  {
09                 replenish
10                 if  (keepRunning.get)  EnergySource.replenishTimer.schedule(
11                     this,  1,  TimeUnit.SECONDS)
12             }
13         },  1,  TimeUnit.SECONDS)
14     }
15     def  stopEnergySource()  =  keepRunning.swap(false)
16     def  getUnitsAvailable()  =  level.get
17     def  getUsageCount()  =  usageCount.get
18     def  useEnergy(units  :  Long)  =  {
19         atomic  {
20             val  currentLevel  =  level.get
21             if(units  >  0  &&  currentLevel  >=  units)  {
22                 level.swap(currentLevel  –  units)
23                 usageCount.swap(usageCount.get  +  1)
24                 true
25             }  else  false
26         }
27     }
28     private  def  replenish()  =
29         atomic  {  if(level.get  <  MAXLEVEL)  level.swap(level.get  +  1)  }
30 }
31 object  EnergySource  {
32     val  replenishTimer  =  Executors.newScheduledThreadPool(10)
33     def  create()  =  {
34         val  energySource  =  new  EnergySource
35         energySource.init
36         energySource
37     }
38 }

作为一个完全的面向对象语言,Scala认为静态方法是不适合放在类的定义中的,所以工厂方法create()就被移到其伴生对象里面去了。余下的代码和Java版本非常相近,只是较之更为简洁。同时,由于使用了优雅的atomic()函数,我们就可以抛开Atomic类和execute()函数调用了。

Scala版本的EnergySource的测试用例如下所示。在并发和线程控制的实现方面,我们既可以像Java版本那样采用JDK的ExecutorService来管理线程,也可以使用Scala的角色(actor)[1] 来为每个并发任务分配执行线程。这里我们将采用第二种方式。当任务完成之后,每个任务都会给调用者返回一个响应,而调用者则需要等待所有任务结束之后才能继续执行。

01 object  UseEnergySource  {
02     val  energySource  =  EnergySource.create()
03     def  main(args  :  Array[String])  {
04         println(“Energy  level  at  start:  ”  +  energySource.getUnitsAvailable())
05         val  caller  =  self
06         for(i  <-  1  to  10)  actor  {
07             for(j  <-  1  to  7)  energySource.useEnergy(1)
08             caller  !  true
09         }
10         for(i  <-  1  to  10)  {  receiveWithin(1000)  {  case  message =>  }  }
11         println(“Energy  level  at  end:  ”  +  energySource.getUnitsAvailable())
12         println(“Usage:  ”  +  energySource.getUsageCount())
13         energySource.stopEnergySource()
14     }
15 }

我们可以采用如下命令来引入Akka相关的Jar并编译运行上述代码,其中环境变量AKKA_JARS与我们在Java示例中的定义相同:

scalac  -classpath  $AKKA_JARS  *.scala
java  -classpath  $AKKA_JARS  com.agiledeveloper.pcj.UseEnergySource

 

Pasted from <http://ifeve.com/stm-4/>

 

String Interpolation

Josh Suereth

Introduction

Starting in Scala 2.10.0, Scala offers a new mechanism to create strings from your data: String Interpolation. String Interpolation allows users to embed variable references directly in processedstring literals. Here’s an example:

 

      1. val name = “James”
      2. println(s”Hello, $name”)  // Hello, James

In the above, the literal s”Hello, $name” is a processed string literal. This means that the compiler does some additional work to this literal. A processed string literal is denoted by a set of characters precedding the “. String interpolation was introduced by SIP-11, which contains all details of the implementation.

Usage

Scala provides three string interpolation methods out of the box: s, f and raw.

The s String Interpolator

Prepending s to any string literal allows the usage of variables directly in the string. You’ve already seen an example here:

 

      1. val name = “James”
      2. println(s”Hello, $name”)  // Hello, James

Here $name is nested inside an s processed string. The s interpolator knows to insert the value of the name variable at this location in the string, resulting in the string Hello, James. With the sinterpolator, any name that is in scope can be used within a string.

String interpolators can also take arbitrary expressions. For example:

 

      1. println(s”1 + 1 = ${1 + 1}”)

will print the string 1 + 1 = 2. Any arbitrary expression can be embedded in ${}.

The f Interpolator

Prepending f to any string literal allows the creation of simple formatted strings, similar to printfin other languages. When using the f interpolator, all variable references should be followed by aprintf-style format string, like %d. Let’s look at an example:

 

      1. val height = 1.9d
      2. val name = “James”
      3. println(f”$name%s is $height%2.2f meters tall”)  // James is 1.90 meters tall

The f interpolator is typesafe. If you try to pass a format string that only works for integers but pass a double, the compiler will issue an error. For example:

 

      1. val height: Double = 1.9d
      2. scala> f”$height%4d”
      1. <console>:9: error: type mismatch;
      1. found   : Double
      2. required: Int
      3. f”$height%4d”
      1. ^

The f interpolator makes use of the string format utilities available from Java. The formats allowed after the % character are outlined in the Formatter javadoc. If there is no % character after a variable definition a formatter of %s (String) is assumed.

The raw Interpolator

The raw interpolator is similar to the s interpolator except that it performs no escaping of literals within the string. Here’s an example processed string:

 

      1. scala> s”a\nb”
      2. res0: String =
      3. a
      4. b

Here the s string interpolator replaced the characters \n with a return character. The rawinterpolator will not do that.

 

      1. scala> raw”a\nb”
      2. res1: String = a\nb

The raw interpolator is useful when you want to avoid having expressions like \n turn into a return character.

In addition to the three default string interpolators, users can define their own.

Advanced Usage

In Scala, all processed string literals are simple code transformations. Anytime the compiler encounters a string literal of the form:

 

      1. id”string content”

it transforms it into a method call (id) on an instance of StringContext. This method can also be available on implicit scope. To define our own string interpolation, we simply need to create an implicit class that adds a new method to StringContext. Here’s an example:

 

      1. // Note: We extends AnyVal to prevent runtime instantiation.  See
      2. // value class guide for more info.
      1. implicit class JsonHelper(val sc: StringContext) extends AnyVal {
      2. def json(args: Any*): JSONObject = sys.error(“TODO – IMPLEMENT”)
      1. }
      1. def giveMeSomeJson(x: JSONObject): Unit = …
      1. giveMeSomeJson(json”{ name: $name, id: $id }”)

In this example, we’re attempting to create a JSON literal syntax using string interpolation. The JsonHelper implicit class must be in scope to use this syntax, and the json method would need a complete implementation. However, the result of such a formatted string literal would not be a string, but a JSONObject.

When the compiler encounters the literal json”{ name: $name, id: $id }” it rewrites it to the following expression:

 

      1. new StringContext(“{ name:”, “,id: “, “}”).json(name, id)

The implicit class is then used to rewrite it to the following:

 

      1. new JsonHelper(new StringContext(“{ name:”, “,id: “, “}”)).json(name, id)

So, the json method has access to the raw pieces of strings and each expression as a value. A simple (buggy) implementation of this method could be:

 

      1. implicit class JsonHelper(val sc: StringContext) extends AnyVal {
      2. def json(args: Any*): JSONObject = {
      1. val strings = sc.parts.iterator
      2. val expressions = args.iterator
      1. var buf = new StringBuffer(strings.next)
      2. while(strings.hasNext) {
      1. buf append expressions.next
      2. buf append strings.next
      1. }
      1. parseJson(buf)
      1. }
      2. }

Each of the string portions of the processed string are exposed in the StringContext’s partsmember. Each of the expression values is passed into the json method’s args parameter. Thejson method takes this and generates a big string which it then parses into JSON. A more sophisticated implementation could avoid having to generate this string and simply construct the JSON directly from the raw strings and expression values.

 

Pasted from <http://docs.scala-lang.org/overviews/core/string-interpolation>

Package objects

Normally you would put your package object in a separate file called package.scala in the package that it corresponds to. You can also use the nested package syntax but that is quite unusual.

The main use case for package objects is when you need definitions in various places inside your package as well as outside the package when you use the API defined by the package. Here is an example:

// file: foo/bar/package.scala

package foo

package object bar {

// package wide constants:
def BarVersionString = “1.0”

// or type aliases
type StringMap[+T] = Map[String,T]

// can be used to emulate a package wide import
// especially useful when wrapping a Java API
type DateTime = org.joda.time.DateTime

type JList[T] = java.util.List[T]

// Define implicits needed to effectively use your API:
implicit def a2b(a: A): B = // …

}

Now the definitions inside that package object are available inside the whole package foo.bar. Furthermore the definitions get imported when someone outside of that package imports foo.bar._.

This way you can prevent to require the API client to issue additional imports to use your library effectively – e.g. in scala-swing you need to write

import swing._
import Swing._

 

Pasted from <http://stackoverflow.com/questions/3400734/package-objects>

 

 

_ (underscore)

Existential types

def foo(l: List[Option[_]]) = …

Higher kinded type parameters

case class A[K[_],T](a: K[T])

Ignored variables

val _ = 5

Ignored parameters

List(1, 2, 3) foreach { _ => println(“Hi”) }

Wildcard patterns

Some(5) match { case Some(_) => println(“Yes”) }

Wildcard imports

import java.util._

Hiding imports

import java.util.{ArrayList => _, _}

Joining letters to punctuation

def bang_!(x: Int) = 5

Assignment operators

def foo_=(x: Int) { … }

Placeholder syntax

List(1, 2, 3) map (_ + 2)

Partially applied functions

List(1, 2, 3) foreach println _

There may be others I have forgotten!

 

Example showing why foo(_) and foo _ are different:

This example comes from 0__:

trait PlaceholderExample {
def process[A](f: A => Unit)

val set: Set[_ => Unit]

set.foreach(process _) // Error
set.foreach(process(_)) // No Error
}

 

 

 

import scala._    // Wild card — all of Scala is imported
import scala.{ Predef => _, _ } // Exception, everything except Predef
def f[M[_]]       // Higher kinded type parameter
def f(m: M[_])    // Existential type
_ + _             // Anonymous function placeholder parameter
m _               // Eta expansion of method into method value
m(_)              // Partial function application
_ => 5            // Discarded parameter
case _ =>         // Wild card pattern — matches anything
val (a, _) = (1, 2) // same thing
for (_ <- 1 to 10)  // same thing
f(xs: _*)         // Sequence xs is passed as multiple parameters to f(ys: T*)
case Seq(xs @ _*) // Identifier xs is bound to the whole matched sequence
var i: Int = _    // Initialization to the default value
def abc_<>!       // An underscore must separate alphanumerics from symbols on identifiers
t._2              // Part of a method name, such as tuple getters

 

 

Examples:

def matchTest(x: Int): String = x match {
case 1 => “one”
case 2 => “two”
case _ => “anything other than one and two”
}

expr match {
case List(1,_,_) => ” a list with three element and the first element is 1″
case List(_*)  => ” a list with zero or more elements ”
case Map[_,_] => ” matches a map with any key type and any value type ”
case _ =>
}

 

 

List(1,2,3,4,5).foreach(print(_))
Do the same with underscore
List(1,2,3,4,5).foreach( a => print(a))

In Scala, _ acts similar to * in Java while importing packages.

// Imports all the classes in the package matching
import scala.util.matching._

// Imports all the members of the object Fun (static import in Java).
import com.test.Fun._

// Imports all the members of the object Fun but renames Foo to Bar
import com.test.Fun.{ Foo => Bar , _ }

// Imports all the members except Foo. To exclude a member rename it to _
import com.test.Fun.{ Foo => _ , _ }

 

Pasted from <http://stackoverflow.com/questions/8000903/what-are-all-the-uses-of-an-underscore-in-scala>

 

 

Scala Tuples

Scala tuple combines a fixed number of items together so that they can be passed around as a whole. Unlike an array or list, a tuple can hold objects with different types but they are also immutable.

 

val t = (1, “hello”, Console)

 

=

val t = new Tuple3(1, “hello”, Console)

 

 

Tuples are of type Tuple1, Tuple2, Tuple3 and so on. There currently is an upper limit of 22 in the Scala if you need more, then you can use a collection, not a tuple. For each TupleN type, where 1 <= N <= 22,

 

 

val t = (4,3,2,1)

To access elements of a tuple t, you can use method t._1 to access the first element, t._2 to access the second, and so on. For example, the following expression computes the sum of all elements of t:

val sum = t._1 + t._2 + t._3 + t._4

 

 

Collections

http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html

 

Scala collections systematically distinguish between mutable and immutable collections. A mutable collection can be updated or extended in place. This means you can change, add, or remove elements of a collection as a side effect. Immutable collections, by contrast, never change. You have still operations that simulate additions, removals, or updates, but those operations will in each case return a new collection and leave the old collection unchanged.

 

 

http://docs.scala-lang.org/overviews/collections/overview

all collections in package scala.collection.immutable.

 

 

 

 

all collections in package scala.collection.mutable.

 

 

 

 

 

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s