2016-11-25 22 views
1

最近,我看着階​​多線程教程和無意中發現這是在演員實現的方法在Scala的方法匹配:模式不帶參數

class MyActor extends Actor 
    def receive = { 
    case "test" => println("received test") 
    case _ =>  println("received unknown message") 
    } 
} 

雖然我認爲我知道什麼方法呢,我可以」弄清楚如何使用這種方法(在它不需要任何參數的情況下)。

Althouh的例子是關於阿卡,我認爲這是不相關的阿卡

+0

你能放下文檔鏈接呢?看起來它會對收到的消息進行模式匹配。 – Pavel

回答

6

其實receive收益部分功能。當你檢查Actor的源代碼時,你會看到;

type Receive = PartialFunction[Any, Unit] 

因此,它意味着覆蓋接收你提供了一個部分功能,它採用任何參數和返回單位。在稍後的某個時刻,如果你的演員得到了一條消息,Akka本身將使用這個局部函數對傳入的消息進行模式匹配。

- 編輯 -

更具體的例子,假設你創建了一個類似的對象;

object Obj { 
    def receive: PartialFunction[Any, Unit] = { 
    case "test" => println("test case") 
    case 1 => println("int 1 case") 
    case d: Double => println("double case $d") 
    case _ => println("rest") 
    } 
} 

然後你可以像普通的方法調用一樣調用這個部分函數;

scala> Obj.receive(1) 
int 1 case 
scala> Obj.receive("test") 
test case 

演員案例是特定的,它只是你不直接調用接收,你提供它,如果消息到達,Akka自己調用它;

protected[akka] def aroundReceive(receive: Actor.Receive, msg: Any): Unit = receive.applyOrElse(msg, unhandled) 

當然這個調用取決於許多像您使用的拓撲結構,郵箱等參數

+0

我仍然沒有看到如何讓這種方法做一些事情(獨立於Akka)。你能提供一些關於如何調用'receive'的代碼,我的意思是它實際上打印了一些東西? –

+0

@RaphaelRoth看到編輯 –

+0

好吧,現在我明白了,你明確定義了返回類型'def receive:PartialFunction [Any,Unit]',否則它不能用普通的標準scala工作。在我上面的例子中,返回類型是在'trait Actor'中定義的,因此在實現方法時不需要再指定它。 –

1

正如@Fatih麥茲說,這是一個Parital功能可按,這個定義的某些類型的某些值,用法:

List("hello", "test").foreach { 
    case "test" => println("received test") 
    case _ =>  println("received unknown message") 
} 

(0 to 20) collect { 
    case i if i % 2 == 0 => i 
} 

(0 to 20) map { 
    case i if i % 2 == 0 => i * i 
    case j => j 
} 

你也可以直接使用它,比如:

val f1: PartialFunction[Int, Unit] = { 
    case 1 => println("I am 1") 
    case t => println(s"I am $t") 
} 

f1(1) 

> I am 1 

f1(2) 

> I am 2 

否則容易實施例:

val f1: PartialFunction[Int, Int] = { 
    case i if i % 2 == 0 => i * i 
} 

val f2: PartialFunction[Int, Int] = { 
    case i if i % 2 != 0 => i+1 
} 

val f = f1 orElse f2 

f(1) 
> 2 

(0 to 10) map f 
> scala.collection.immutable.IndexedSeq[Int] = Vector(0, 2, 4, 4, 16, 6, 36, 8, 64, 10, 100) 

andThen實施例:

val f1: PartialFunction[Int, Int] = { 
    case i if i % 2 == 0 => i * i 
    case j => j 
} 

val f2: PartialFunction[Int, Int] = { 
    case i if i % 2 != 0 => i * i 
    case j => j + 1 
} 

val f = f1 andThen f2 
f(2) 
res20: Int = 5 

(0 to 10) map f 
> scala.collection.immutable.IndexedSeq[Int] = Vector(1, 1, 5, 9, 17, 25, 37, 49, 65, 81, 101) 

構成實施例:

val f1: PartialFunction[Int, Int] = { 
    case i if i % 2 == 0 => i * i 
    case j => j 
} 

val f2: PartialFunction[Int, Int] = { 
    case i if i % 2 != 0 => i * i 
    case j => j + 1 
} 


val f = f1 compose f2 

f(2) 
res18: Int = 3 

(0 to 10) map f 
res17: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 1, 3, 9, 5, 25, 7, 49, 9, 81, 11) 

文檔:

  1. https://twitter.github.io/scala_school/pattern-matching-and-functional-composition.html
  2. https://twitter.github.io/scala_school/pattern-matching-and-functional-composition.html