diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0b100cf9c851cc4c4c2ee6391bb04eace0e78a19..edda250c5c68f5f44d428d71eefffd174e4b7532 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -21,4 +21,4 @@ test: tags: - cs320 script: - - sbt "runMain lecture1.javaThreads; runMain lecture1.scalaThreadWrapper; runMain lecture1.ExampleThread; runMain lecture3.intersectionWrong; runMain lecture3.intersectionCorrect; runMain lecture3.intersectionNoSideEffect; runMain lecture3.parallelGraphContraction; runMain lecture3.parallelGraphContractionCorrect; runMain midterm22.mock1; runMain midterm22.part3; runMain ed.patternMatching; runMain lecture13.askPatternDemo; test; scalafmtCheck; Test / scalafmtCheck" + - sbt "runMain lecture1.javaThreads; runMain lecture1.scalaThreadWrapper; runMain lecture1.ExampleThread; runMain lecture3.intersectionWrong; runMain lecture3.intersectionCorrect; runMain lecture3.intersectionNoSideEffect; runMain lecture3.parallelGraphContraction; runMain lecture3.parallelGraphContractionCorrect; runMain midterm22.mock1; runMain midterm22.part3; runMain ed.patternMatching; runMain lecture13.askPatternDemo; test; runMain lecture13.becomeDemo; scalafmtCheck; Test / scalafmtCheck" diff --git a/src/main/scala/lecture13/Become.scala b/src/main/scala/lecture13/Become.scala new file mode 100644 index 0000000000000000000000000000000000000000..c3702c4a4b35160b812a29c67b08581f27a03d65 --- /dev/null +++ b/src/main/scala/lecture13/Become.scala @@ -0,0 +1,49 @@ +package lecture13 + +import akka.actor.{Actor, ActorContext, ActorRef, ActorSystem, Props} +import akka.event.LoggingReceive +import akka.testkit.{ImplicitSender, TestKit} + +class CounterRight extends Actor: + def counter(n: Int): Receive = { + case "increment" => context.become(counter(n + 1), discardOld = false) + // ^^^^^^^^^^^^^^^^^^ + // This is needed. + case "get" => sender() ! n + case "decrement" => if n != 0 then context.unbecome() + } + def receive = counter(0) + +class CounterWrong extends Actor: + def counter(n: Int): Receive = { + case "increment" => context.become(counter(n + 1)) + case "get" => sender() ! n + case "decrement" => if n != 0 then context.unbecome() + } + def receive = counter(0) + +@main def becomeDemo() = + new TestKit(ActorSystem("DebugSystem")) with ImplicitSender: + try + val counter = system.actorOf(Props(CounterRight()), "counter") + + counter ! "increment" + counter ! "get" + expectMsg(1) + + counter ! "increment" + counter ! "get" + expectMsg(2) + + counter ! "decrement" + counter ! "get" + expectMsg(1) + // This is wrong if we use CounterWrong because it doesn't set the + // discardOld parameter to false. Therefore, it will not remember the + // previous state and reset the behavior to the initial one, which is + // `counter(0)`. + + counter ! "decrement" + counter ! "get" + expectMsg(0) + finally shutdown(system)