Ben Biddington

Whatever it is, it's not about "coding"

Posts Tagged ‘scala

Scala — Futures

leave a comment »

A future is a placeholder for the return value of an asynchronous operation, it’s left to clients to decide when to block and wait for reply value.

It is an alternative to blocking on receive.

For example, the double-bang on Actor causes operation to return a future:

   /**
   * Sends msg to this actor and immediately
   * returns a future representing the reply value.
   */
  def !!(msg: Any): Future[Any] = {
    val ftch = new Channel[Any](Actor.self)
    send(msg, ftch)
    new Future[Any](ftch) {
      def apply() =
        if (isSet) value.get
        else ch.receive {
          case any => value = Some(any); any
        }
      def isSet = value match {
        case None => ch.receiveWithin(0) {
          case TIMEOUT => false
          case any => value = Some(any); true
        }
        case Some(_) => true
      }
    }
  }

Which can then be used to obtain the reply.

The Future class takes an InputChannel as its ctor argument. This channel is monitored to determine the future’s completion status.

In this instance, the future by !! is configured with the reply channel as supplied to send. In short, the actor has sent itself a message and specified that the future’s channel should be notified when complete. The future then just monitors that channel for the reply.

Note: Actor.send invokes the act method using a Reaction, which spawns threads and runs actors.

Only the actor creating an instance of a Channel may receive from it. This means that the future here must be running on the same thread as the actor that created it.

The send call is instructing the reply to be returned to the channel being monitored by the future.

Why does future block until actor returns value?

This is because it blocks on the channel, waiting for reply:

...
def apply() =
    if (isSet) value.get
    else ch.receive {
        case any => value = Some(any); any
    }
...

and Channel.receive is a ultimately a blocking operation, since it invokes receive on the actor it belongs to:

...
def receive[R](f: PartialFunction[Msg, R]): R = {
    val C = this.asInstanceOf[Channel[Any]]
    recv.receive {
        case C ! msg if (f.isDefinedAt(msg.asInstanceOf[Msg])) => f(msg.asInstanceOf[Msg])
    }
}
...

Note that recv here is the Actor supplied in Channel ctor.

Consider this example:

val aFuture = future[String] {
    currentThreadId
};

Internally, a new actor is created and has its double bang invoked:

def future[T](body: => T): Future[T] = {
    case object Eval
    val a = Actor.actor {
        Actor.react {
            case Eval => Actor.reply(body)
        }
    }
    a !! (Eval, { case any => any.asInstanceOf[T] })
}

And by examining the apply method above, we know this blocks until a message is received from channel.

Written by benbiddington

24 April, 2010 at 13:37

Posted in development

Tagged with , , ,

Scala introduction — writing an OAuth library

leave a comment »

I started out intending to write some scala examples against the twitter API, however I soon discovered I needed OAuth first. Given that I use OAuth all the time at work I figured I could probably do with learning about it first-hand, while learning scala.

org.junit.rules._

I chose to test drive it with JUnit 4.7 and NetBeans.

NetBeans works almost immediately with scala, and has support for project templates etc — even scala JUnit fixtures.

UPDATE (2010-04-27) I have since discovered IntelliJ to be much better, and there is now a free community edition. IntelliJ supports scala without any fiddling around.

JUnit mostly works, though rules don’t and neither do some matchers. Even though rules don’t work, I have included it anyway because I have the t-shirt.

You can find the project on github.

Important abstractions

  1. SignatureBaseString.
    1. Characterized by three ampersand-separated segments: verb, uri, parameters.
    2. URL Encoding must conform to RFC 3986, and the following characters should are consider unreserved so should not be encoded:
      ALPHA, DIGIT, ‘-‘, ‘.’, ‘_’, ‘~’
  2. Signature.
    1. Signature is a keyed-Hash Message Authentication Code (HMAC).
    2. Consumer secret required part of HMAC secret key.
    3. Token secret is optionally included in HMAC secret key:
      (consumer_secret, token_secret) => uri_encoded_consumer_secret&[uri_encoded_token_secret]
  3. OAuthCredential. Represents the secret key(s) used to create the HMAC signature. OAuth requires a consumer credential, and optionally a token credential, representing the end user.

Now that these core concepts are complete, I am working on high-level policy, like classes for generating signed URLs and authorization headers.

Notes

JUnit — expecting exceptions in scala

Assuming JUnit 4.x, a test can expect an exception using the test annotation:

Java:

@Test(expected=IllegalArgumentException.class)
    public void ExampleThrowsException(){
        throw new IllegalArgumentException();
    }

This needs to be modified for scala:

Scala:

@Test { val expected=classOf[IllegalArgumentException] }
    def ExampleThrowsException {
        throw new IllegalArgumentException
    }

The reason for it is outlined here in the Java annotations section on named parameters.

Here is the documentation for scala annotations. Seealso: the documentation for scala 2.7.3 (includes dbc).

Closures and return

The return statement immediately returns from the current method, even if you’re within a closure. Omit return in this case — return is optional anyway.

When to use semicolon line terminator

Never — apart from:

  • When a method returns Unit (equivalent to void) and you aren’t using return keyword. [TBD: Add example].

How to use blocks

var count = 1
times(2) { println("Printed " + count + " times")}
protected def times(count : Int)(block : => Unit) = {
    1.to(count).foreach((_) => block)
}

Seealso: some executable examples on github

References

ALPHA, DIGIT, '-', '.', '_', '~'

Written by benbiddington

18 September, 2009 at 13:37

Posted in development

Tagged with , , , , , , , ,