Richard Searle's Blog

Thoughts about software

Archive for March, 2012

Resolved the ()=>Unit surprise

Posted by eggsearle on March 28, 2012

f{() => println("2")} calls f with a value that is a function.

Scala has a special case where expressions with a return type of Unit discard any value that might otherwise be returned.
In this case, the expression is() => println("2"). The resultant Unit matches the signature of f, which explains why the compiler does not complain.

Advertisements

Posted in Scala | Leave a Comment »

Surprises with call-by-name and unary functions

Posted by eggsearle on March 27, 2012

I recently created a subtle defect while using the Play2 enumerators

Both  pushee and fromCallback are passed an onComplete that is executed when the target Iteratee can no longer accept any input. The signatures are slightly different

pushee:onComplete: ⇒ Unit
fromCallback:onComplete: () ⇒ Unit

I did not notice the difference and used {() => println("completed")} in each case. That prints the expected output for fromCallback but is not executed for pushee. The compiler does not generate any errors, making this a completely silent failure. Thanks to sadek for pointing out my error.

The next step was to gain a better understanding of this corner of the Scala language

def f(a: => Unit){a}
def g(a:() => Unit){a()}
def h(a: => String)={a}
def i(a:() => String)={a()}

f{println("1")}
f{() => println("2")}
g{() => println("3")}
println(h{"5"})
println(h{()=>"6"})
println(i{() => "7"})

The result is
1
3
5
<console>:9: error: type mismatch;
found : () => java.lang.String
required: String
println(h{()=>”6″})
^
7

So there is something special about () => Unit

Posted in play, Scala | Leave a Comment »

Akka system IO client

Posted by eggsearle on March 10, 2012


Network clients can also be implemented using Akka System IO.

The following provides a simple client that contents to the LengthCountedServer,  simplistically modified to echo back the received text to all attached clients

Note that all the operations are asynchronous, including the connection creation on line 24. The API returns a SocketHandle, even if the connection cannot be made. The clarity of system state we wait for the Connected operation before registering a handle.


case Read(socket, bytes) =>
 state(socket)(Chunk(bytes))
 state.foreach{p => p._1.asWritable.write(bytes)}

import akka.actor._
import akka.util.{ ByteString, ByteStringBuilder }
import java.net.InetSocketAddress

class LengthBoundedClient(port: Int) extends Actor {
  import IO._

  var handle: Option[SocketHandle] = None
  var respondTo: Option[ActorRef] = None

  def receive = {
    case Read(socket, bytes) =>
      respondTo.foreach { _ ! bytes }

    case Closed(socket, cause) =>
      handle = None

    case Connected(h, _) => handle = Some(h)

    case s: String => handle.foreach { _ write ByteString("%04d%s".format(s.length, s)) }

    case Attach(r) =>
      respondTo = Some(r);
      IOManager(context.system).connect(new InetSocketAddress(port))

    case Detach => handle.foreach { _.close }; handle = None
  }

}

case class Attach(respondTo: ActorRef)
case object Detach

case class RespondTo extends Actor {
  def receive = {
    case bytes: ByteString => println(bytes.decodeString("US-ASCII"))
  }
}

object Client extends App {
  val port = Option(System.getenv("PORT")) map (_.toInt) getOrElse 9999
  val system = ActorSystem()
  val client = system.actorOf(Props(new LengthBoundedClient(port)))
  val respondTo = system.actorOf(Props[RespondTo])

  while (true) {
    Console.readLine() match {
      case "A" => client ! Attach(respondTo)
      case "D" => client ! Detach
      case _@ s => client ! s
    }
  }

}



				

Posted in Akka, Scala | 3 Comments »