不带参数的scala方法中的模式匹配

时间:2016-11-25 07:52:06

标签: scala

我最近查看了scala多线程教程,偶然发现了一个在Actor中实现的方法:

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

虽然我认为我知道该方法的作用,但我无法弄清楚如何使用这样的方法(在它没有任何参数的情况下)。

Althouh的例子是关于Akka,我认为这与Akka无关

2 个答案:

答案 0 :(得分: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)

当然,此调用取决于许多参数,例如您使用的拓扑,邮箱等。

答案 1 :(得分:1)

正如@Fatih Donmez所说,它是 Parital Funciton ,这定义了某些类型的某些值,用法:

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

orElse 示例:

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)

然后示例:

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