[scala] Why are Scala's actors untyped?

View: New views
11 Messages — Rating Filter:   Alert me  

[scala] Why are Scala's actors untyped?

by Ricky Clarkson :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi all,

I came across a use case for actors in my Java-only job, so I started thinking about how to go about implementing them for Java (or possibly using Scala's actors as a library, though $bang isn't a great method name).  I learned enough of Erlang to be dangerous, then looked at Scala's implementation, to see how it would typically be implemented on the JVM.  I was quite surprised to see that Scala's actors' messages are dispatched on through pattern matching - not the usual pattern matching that you can use to take a List, Option or Either to bits, but the kind equivalent to instanceof and casts from Javaland - i.e., BreaksWhenYouChangeStuff(tm).

So I had a quick go and had typed actors working well in Java in a couple of hours, enough to get my job done.  Of course, programming for a Javaland project means that certain features seem too leftfield, e.g., using Either, tuples or Option, so in my own time I decided to port my typed actors to less than a screenful of Scala.

Then I had a look at Phillip Haller's tutorial on Scala Actors ( http://lamp.epfl.ch/~phaller/doc/ActorsTutorial.html ), and ported his PingPong example to my library.  (Library sounds grandiose for less than a screenful of code, but nevermind).  I link here to my version of that example - http://cime.net/~ricky/tmp/PingPong.scala .  I tried to keep close to the original, but I found it hard to keep track of using Ping and Pong twice (as a class extending Actor and as a case object representing a message), so I renamed the case objects to PingMessage and PongMessage (and changed them to case classes).

But for the second example, I really have no idea why you would ever use actors to implement synchronous iteration over a tree, so I deleted my half-written port of that until I have fresher eyes.  If anyone can explain why that example is useful, please do!

So far though, I'm really unsure why the original library is untyped - if it turns out when I do more interesting things with my version that typing is impossible or too awkward sometimes, it would make sense to route around it, but to have untyping as the default in Scala seems.. odd.

So, please enlighten me - why is it better to have untyped actors than typed actors?  If you quote the test case above in your explanation, please don't count Either against it - that can easily be removed.

Here's my working version of the 'library' for typed actors - names copied from scala.actors, laughably small - http://cime.net/~ricky/tmp/Actor.scala .  I'm not really sure right now whether Actor should have a result type too (it does in that version) or just a message type.

Cheers,
Ricky.

Re: [scala] Why are Scala's actors untyped?

by Erik Engbrecht :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Some parts of this message have been removed. Learn more about Nabble's security policy.
Good question.  I've often wondered the same thing.

On 8/4/08, Ricky Clarkson <ricky.clarkson@...> wrote:
Hi all,

I came across a use case for actors in my Java-only job, so I started thinking about how to go about implementing them for Java (or possibly using Scala's actors as a library, though $bang isn't a great method name).  I learned enough of Erlang to be dangerous, then looked at Scala's implementation, to see how it would typically be implemented on the JVM.  I was quite surprised to see that Scala's actors' messages are dispatched on through pattern matching - not the usual pattern matching that you can use to take a List, Option or Either to bits, but the kind equivalent to instanceof and casts from Javaland - i.e., BreaksWhenYouChangeStuff(tm).

So I had a quick go and had typed actors working well in Java in a couple of hours, enough to get my job done.  Of course, programming for a Javaland project means that certain features seem too leftfield, e.g., using Either, tuples or Option, so in my own time I decided to port my typed actors to less than a screenful of Scala.

Then I had a look at Phillip Haller's tutorial on Scala Actors ( http://lamp.epfl.ch/~phaller/doc/ActorsTutorial.html ), and ported his PingPong example to my library.  (Library sounds grandiose for less than a screenful of code, but nevermind).  I link here to my version of that example - http://cime.net/~ricky/tmp/PingPong.scala .  I tried to keep close to the original, but I found it hard to keep track of using Ping and Pong twice (as a class extending Actor and as a case object representing a message), so I renamed the case objects to PingMessage and PongMessage (and changed them to case classes).

But for the second example, I really have no idea why you would ever use actors to implement synchronous iteration over a tree, so I deleted my half-written port of that until I have fresher eyes.  If anyone can explain why that example is useful, please do!

So far though, I'm really unsure why the original library is untyped - if it turns out when I do more interesting things with my version that typing is impossible or too awkward sometimes, it would make sense to route around it, but to have untyping as the default in Scala seems.. odd.

So, please enlighten me - why is it better to have untyped actors than typed actors?  If you quote the test case above in your explanation, please don't count Either against it - that can easily be removed.

Here's my working version of the 'library' for typed actors - names copied from scala.actors, laughably small - http://cime.net/~ricky/tmp/Actor.scala .  I'm not really sure right now whether Actor should have a result type too (it does in that version) or just a message type.

Cheers,
Ricky.
 



--
http://erikengbrecht.blogspot.com/

Re: [scala] Why are Scala's actors untyped?

by David Pollak :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Some parts of this message have been removed. Learn more about Nabble's security policy.


Erik Engbrecht wrote:
Good question.  I've often wondered the same thing.
FWIW: Sometimes, I want strongly typed Actors.  Sometimes I use Actors in the best Unityped way... much like the things I like about Ruby and Python and Smalltalk.

I'd like to have the option of well typed Actors (with different in and out typed), but in general, I have been cool with the existing Actors.

On 8/4/08, Ricky Clarkson <ricky.clarkson@...> wrote:
Hi all,

I came across a use case for actors in my Java-only job, so I started thinking about how to go about implementing them for Java (or possibly using Scala's actors as a library, though $bang isn't a great method name).  I learned enough of Erlang to be dangerous, then looked at Scala's implementation, to see how it would typically be implemented on the JVM.  I was quite surprised to see that Scala's actors' messages are dispatched on through pattern matching - not the usual pattern matching that you can use to take a List, Option or Either to bits, but the kind equivalent to instanceof and casts from Javaland - i.e., BreaksWhenYouChangeStuff(tm).

So I had a quick go and had typed actors working well in Java in a couple of hours, enough to get my job done.  Of course, programming for a Javaland project means that certain features seem too leftfield, e.g., using Either, tuples or Option, so in my own time I decided to port my typed actors to less than a screenful of Scala.

Then I had a look at Phillip Haller's tutorial on Scala Actors ( http://lamp.epfl.ch/~phaller/doc/ActorsTutorial.html ), and ported his PingPong example to my library.  (Library sounds grandiose for less than a screenful of code, but nevermind).  I link here to my version of that example - http://cime.net/~ricky/tmp/PingPong.scala .  I tried to keep close to the original, but I found it hard to keep track of using Ping and Pong twice (as a class extending Actor and as a case object representing a message), so I renamed the case objects to PingMessage and PongMessage (and changed them to case classes).

But for the second example, I really have no idea why you would ever use actors to implement synchronous iteration over a tree, so I deleted my half-written port of that until I have fresher eyes.  If anyone can explain why that example is useful, please do!

So far though, I'm really unsure why the original library is untyped - if it turns out when I do more interesting things with my version that typing is impossible or too awkward sometimes, it would make sense to route around it, but to have untyping as the default in Scala seems.. odd.

So, please enlighten me - why is it better to have untyped actors than typed actors?  If you quote the test case above in your explanation, please don't count Either against it - that can easily be removed.

Here's my working version of the 'library' for typed actors - names copied from scala.actors, laughably small - http://cime.net/~ricky/tmp/Actor.scala .  I'm not really sure right now whether Actor should have a result type too (it does in that version) or just a message type.

Cheers,
Ricky.
 



--
http://erikengbrecht.blogspot.com/

Re: [scala] Why are Scala's actors untyped?

by Ricky Clarkson :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I'd rather escape from a typesystem than into one.. in other words, I'd rather the default was typed.  That's kind of.. why I use Scala.

2008/8/4 David Pollak <dpp@...>


Erik Engbrecht wrote:
Good question.  I've often wondered the same thing.
FWIW: Sometimes, I want strongly typed Actors.  Sometimes I use Actors in the best Unityped way... much like the things I like about Ruby and Python and Smalltalk.

I'd like to have the option of well typed Actors (with different in and out typed), but in general, I have been cool with the existing Actors.


On 8/4/08, Ricky Clarkson <ricky.clarkson@...> wrote:
Hi all,

I came across a use case for actors in my Java-only job, so I started thinking about how to go about implementing them for Java (or possibly using Scala's actors as a library, though $bang isn't a great method name).  I learned enough of Erlang to be dangerous, then looked at Scala's implementation, to see how it would typically be implemented on the JVM.  I was quite surprised to see that Scala's actors' messages are dispatched on through pattern matching - not the usual pattern matching that you can use to take a List, Option or Either to bits, but the kind equivalent to instanceof and casts from Javaland - i.e., BreaksWhenYouChangeStuff(tm).

So I had a quick go and had typed actors working well in Java in a couple of hours, enough to get my job done.  Of course, programming for a Javaland project means that certain features seem too leftfield, e.g., using Either, tuples or Option, so in my own time I decided to port my typed actors to less than a screenful of Scala.

Then I had a look at Phillip Haller's tutorial on Scala Actors ( http://lamp.epfl.ch/~phaller/doc/ActorsTutorial.html ), and ported his PingPong example to my library.  (Library sounds grandiose for less than a screenful of code, but nevermind).  I link here to my version of that example - http://cime.net/~ricky/tmp/PingPong.scala .  I tried to keep close to the original, but I found it hard to keep track of using Ping and Pong twice (as a class extending Actor and as a case object representing a message), so I renamed the case objects to PingMessage and PongMessage (and changed them to case classes).

But for the second example, I really have no idea why you would ever use actors to implement synchronous iteration over a tree, so I deleted my half-written port of that until I have fresher eyes.  If anyone can explain why that example is useful, please do!

So far though, I'm really unsure why the original library is untyped - if it turns out when I do more interesting things with my version that typing is impossible or too awkward sometimes, it would make sense to route around it, but to have untyping as the default in Scala seems.. odd.

So, please enlighten me - why is it better to have untyped actors than typed actors?  If you quote the test case above in your explanation, please don't count Either against it - that can easily be removed.

Here's my working version of the 'library' for typed actors - names copied from scala.actors, laughably small - http://cime.net/~ricky/tmp/Actor.scala .  I'm not really sure right now whether Actor should have a result type too (it does in that version) or just a message type.

Cheers,
Ricky.
 



--
http://erikengbrecht.blogspot.com/


Re: [scala] Why are Scala's actors untyped?

by Philipp Haller-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi, Ricky,

First, why are actors currently untyped?
Originally, the actors library emerged from an experiment to implement
Erlang in Scala. In that model, it is common to have nested receives, i.e.

  receive {
    case first =>
      ...
      receive {
        case second => ...
      }
  }

Now, if the types of `first` and `second` are unrelated, then certainly
the actor must be able to accept messages of type `Any`. Otherwise, at
least one of the receives would block indefinitely which is undesirable.
If the outer receive could enforce that inner receives operate on a
related message type, then we could give the actor a more precise
(input) type.

Why does this "untyped" scheme work surprisingly well in Scala? Pattern
matching helps you recover types, e.g.:

  case class DoThis(x: List[(Int, String)])
  receive {
    case DoThis(args) => // know that args: List[(Int, String)]
  }

Since you alluded to the simplicity of your library:
Much of the complexity of the actors library stems from the fact that an
actor can suspend in a nested event-based receive (called `react`). This
is explained in the first actors paper [1]. There is a set of
combinators, such as `loop`, that makes actors written in that style
composable. To some extent this is explained in the second actors paper [2].

There are more reasons why `scala.actors` doesn't fit on a screenful of
code. An important one is that it is guaranteed that only a single
thread is executing "inside" an actor at a time (which your
implementation does not guarantee since it submits `Callable`s right
away). For this you need an additional message queue. Other reason are
interoperability with Java threads (see [2]), monitoring through links etc.

Now, if you would disallow nested receives, then you could certainly
give those restricted actors a more precise type.
Basically, given a function `fun: M => R` the typed actors would fit the
pattern

  loop {
    react { case any => reply(fun(any)) }
  }

where `fun` would not contain any calls to potentially suspending
methods, such as `react`.

In fact, this is how you can do input-typed actors using the existing
library:

  def typedActor[A](fun: A => Unit): OutputChannel[A] = {
    val sink = new SyncVar[Channel[A]]
    actor {
      val in = new Channel[A](self)
      sink set in
      loop {
        in react { case any => reply(fun(any)) }
      }
    }
    sink.get
  }

Output types are also useful, e.g., to type synchronous and future-type
message sends, such as `!?` and `!!`. However, this probably requires a
little more effort.
But, I agree with you and others that it would good to have more support
for this in the library.

Cheers,
Philipp

[1] Haller, Odersky: Event-based Programming without Inversion of
Control, Proc. JMLC 2006

[2] Haller, Odersky: Actors that Unify Threads and Events, Proc.
COORDINATION 2007


Ricky Clarkson wrote:

> Hi all,
>
> I came across a use case for actors in my Java-only job, so I started
> thinking about how to go about implementing them for Java (or possibly
> using Scala's actors as a library, though $bang isn't a great method
> name).  I learned enough of Erlang to be dangerous, then looked at
> Scala's implementation, to see how it would typically be implemented on
> the JVM.  I was quite surprised to see that Scala's actors' messages are
> dispatched on through pattern matching - not the usual pattern matching
> that you can use to take a List, Option or Either to bits, but the kind
> equivalent to instanceof and casts from Javaland - i.e.,
> BreaksWhenYouChangeStuff(tm).
>
> So I had a quick go and had typed actors working well in Java in a
> couple of hours, enough to get my job done.  Of course, programming for
> a Javaland project means that certain features seem too leftfield, e.g.,
> using Either, tuples or Option, so in my own time I decided to port my
> typed actors to less than a screenful of Scala.
>
> Then I had a look at Phillip Haller's tutorial on Scala Actors (
> http://lamp.epfl.ch/~phaller/doc/ActorsTutorial.html ), and ported his
> PingPong example to my library.  (Library sounds grandiose for less than
> a screenful of code, but nevermind).  I link here to my version of that
> example - http://cime.net/~ricky/tmp/PingPong.scala .  I tried to keep
> close to the original, but I found it hard to keep track of using Ping
> and Pong twice (as a class extending Actor and as a case object
> representing a message), so I renamed the case objects to PingMessage
> and PongMessage (and changed them to case classes).
>
> But for the second example, I really have no idea why you would ever use
> actors to implement synchronous iteration over a tree, so I deleted my
> half-written port of that until I have fresher eyes.  If anyone can
> explain why that example is useful, please do!
>
> So far though, I'm really unsure why the original library is untyped -
> if it turns out when I do more interesting things with my version that
> typing is impossible or too awkward sometimes, it would make sense to
> route around it, but to have untyping as the default in Scala seems.. odd.
>
> So, please enlighten me - why is it better to have untyped actors than
> typed actors?  If you quote the test case above in your explanation,
> please don't count Either against it - that can easily be removed.
>
> Here's my working version of the 'library' for typed actors - names
> copied from scala.actors, laughably small -
> http://cime.net/~ricky/tmp/Actor.scala .  I'm not really sure right now
> whether Actor should have a result type too (it does in that version) or
> just a message type.
>
> Cheers,
> Ricky.


Re: [scala] Why are Scala's actors untyped?

by Josh Suereth :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I just wanted to say that I think the scala actor library is great and really easy to learn/start using.  My complaints come from how I think when I start developing software.  I want my actor to have a type-safe interface (compile-time) where you can just look at a trait and see what messages/methods may be called sent to an actor.  Therefore, this is the approach I've taken when adding actors into my existing code:

http://suereth.blogspot.com/2008/08/adding-scala-actors-to-your-spring.html (Note:  Shameless plug)

Anyway, it's a little bit more work that some people will say is "unnecessary", however it's great if you have an existing spring application or desire any of the flexibility mentioned in the blog.

My theory is that we'll need a layer on top of actors if we want to have type-safe interfaces, and delayed wiring of the app.  Perhaps if we figure out a good, standard way to do it, we can make use of annotations to write the boiler-plate code.


-Josh

On Mon, Aug 4, 2008 at 2:08 PM, Philipp Haller <philipp.haller@...> wrote:
Hi, Ricky,

First, why are actors currently untyped?
Originally, the actors library emerged from an experiment to implement
Erlang in Scala. In that model, it is common to have nested receives, i.e.

 receive {
   case first =>
     ...
     receive {
       case second => ...
     }
 }

Now, if the types of `first` and `second` are unrelated, then certainly
the actor must be able to accept messages of type `Any`. Otherwise, at
least one of the receives would block indefinitely which is undesirable.
If the outer receive could enforce that inner receives operate on a
related message type, then we could give the actor a more precise
(input) type.

Why does this "untyped" scheme work surprisingly well in Scala? Pattern
matching helps you recover types, e.g.:

 case class DoThis(x: List[(Int, String)])
 receive {
   case DoThis(args) => // know that args: List[(Int, String)]
 }

Since you alluded to the simplicity of your library:
Much of the complexity of the actors library stems from the fact that an
actor can suspend in a nested event-based receive (called `react`). This
is explained in the first actors paper [1]. There is a set of
combinators, such as `loop`, that makes actors written in that style
composable. To some extent this is explained in the second actors paper [2].

There are more reasons why `scala.actors` doesn't fit on a screenful of
code. An important one is that it is guaranteed that only a single
thread is executing "inside" an actor at a time (which your
implementation does not guarantee since it submits `Callable`s right
away). For this you need an additional message queue. Other reason are
interoperability with Java threads (see [2]), monitoring through links etc.

Now, if you would disallow nested receives, then you could certainly
give those restricted actors a more precise type.
Basically, given a function `fun: M => R` the typed actors would fit the
pattern

 loop {
   react { case any => reply(fun(any)) }
 }

where `fun` would not contain any calls to potentially suspending
methods, such as `react`.

In fact, this is how you can do input-typed actors using the existing
library:

 def typedActor[A](fun: A => Unit): OutputChannel[A] = {
   val sink = new SyncVar[Channel[A]]
   actor {
     val in = new Channel[A](self)
     sink set in
     loop {
       in react { case any => reply(fun(any)) }
     }
   }
   sink.get
 }

Output types are also useful, e.g., to type synchronous and future-type
message sends, such as `!?` and `!!`. However, this probably requires a
little more effort.
But, I agree with you and others that it would good to have more support
for this in the library.

Cheers,
Philipp

[1] Haller, Odersky: Event-based Programming without Inversion of
Control, Proc. JMLC 2006

[2] Haller, Odersky: Actors that Unify Threads and Events, Proc.
COORDINATION 2007


Ricky Clarkson wrote:
> Hi all,
>
> I came across a use case for actors in my Java-only job, so I started
> thinking about how to go about implementing them for Java (or possibly
> using Scala's actors as a library, though $bang isn't a great method
> name).  I learned enough of Erlang to be dangerous, then looked at
> Scala's implementation, to see how it would typically be implemented on
> the JVM.  I was quite surprised to see that Scala's actors' messages are
> dispatched on through pattern matching - not the usual pattern matching
> that you can use to take a List, Option or Either to bits, but the kind
> equivalent to instanceof and casts from Javaland - i.e.,
> BreaksWhenYouChangeStuff(tm).
>
> So I had a quick go and had typed actors working well in Java in a
> couple of hours, enough to get my job done.  Of course, programming for
> a Javaland project means that certain features seem too leftfield, e.g.,
> using Either, tuples or Option, so in my own time I decided to port my
> typed actors to less than a screenful of Scala.
>
> Then I had a look at Phillip Haller's tutorial on Scala Actors (
> http://lamp.epfl.ch/~phaller/doc/ActorsTutorial.html ), and ported his
> PingPong example to my library.  (Library sounds grandiose for less than
> a screenful of code, but nevermind).  I link here to my version of that
> example - http://cime.net/~ricky/tmp/PingPong.scala .  I tried to keep
> close to the original, but I found it hard to keep track of using Ping
> and Pong twice (as a class extending Actor and as a case object
> representing a message), so I renamed the case objects to PingMessage
> and PongMessage (and changed them to case classes).
>
> But for the second example, I really have no idea why you would ever use
> actors to implement synchronous iteration over a tree, so I deleted my
> half-written port of that until I have fresher eyes.  If anyone can
> explain why that example is useful, please do!
>
> So far though, I'm really unsure why the original library is untyped -
> if it turns out when I do more interesting things with my version that
> typing is impossible or too awkward sometimes, it would make sense to
> route around it, but to have untyping as the default in Scala seems.. odd.
>
> So, please enlighten me - why is it better to have untyped actors than
> typed actors?  If you quote the test case above in your explanation,
> please don't count Either against it - that can easily be removed.
>
> Here's my working version of the 'library' for typed actors - names
> copied from scala.actors, laughably small -
> http://cime.net/~ricky/tmp/Actor.scala .  I'm not really sure right now
> whether Actor should have a result type too (it does in that version) or
> just a message type.
>
> Cheers,
> Ricky.



[scala] Re: Why are Scala's actors untyped?

by Jesper Nordenberg :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Philipp Haller wrote:

> First, why are actors currently untyped?
> Originally, the actors library emerged from an experiment to implement
> Erlang in Scala. In that model, it is common to have nested receives, i.e.
>
>   receive {
>     case first =>
>       ...
>       receive {
>         case second => ...
>       }
>   }
>
> Now, if the types of `first` and `second` are unrelated, then certainly
> the actor must be able to accept messages of type `Any`. Otherwise, at
> least one of the receives would block indefinitely which is undesirable.

So, in this case you create an Actor[Any] (or a more advanced type with
Either or the message sequence encoded in the type). I can't think of
any reason why the Actor class shouldn't have a type parameter.

> Why does this "untyped" scheme work surprisingly well in Scala? Pattern
> matching helps you recover types, e.g.:
>
>   case class DoThis(x: List[(Int, String)])
>   receive {
>     case DoThis(args) => // know that args: List[(Int, String)]
>   }

The usefulness of message type check is not primarily on the receiver
side, it's on the caller side. You don't want to send a message of
incorrect type to an actor and get a runtime error.

In essence, you can view an actor as a function of type "A =>
Future[B]". Types A and B are clearly related, if you send an actor a
certain message type you would expect a reply of a certain type. How can
we encode this in Scala? The straightforward way would be to encode the
return type in the message type, for example:

trait Message { type ReturnType }

case class MyMess(x : Int, y : Int) extends Message {
   type ReturnType = Int
}

trait Actor[Msg] {
   def !![T <: Msg with Message](msg : T) : Future[T#ReturnType]
}

(alternatively "trait Actor[Msg <: Message]")

However, implementing the receive method in a type safe way is AFAIK not
possible to do in Scala, you would have to resort to casting.

/Jesper Nordenberg


Re: [scala] Re: Why are Scala's actors untyped?

by Martin Odersky :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Note that Actor inherits from OutputChannel, which is typed. So you can write:

scala> val x: OutputChannel[Int] = actor { ... }
x: scala.actors.OutputChannel[Int] = scala.actors.Actor$$anon$1@114382d

scala> x ! 2

scala> x ! "abc"
<console>:10: error: type mismatch;
 found   : java.lang.String("abc")
 required: Int
       x ! "abc"
           ^

Cheers

 -- Martin

[scala] Re: Why are Scala's actors untyped?

by Jesper Nordenberg :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

martin odersky wrote:
> Note that Actor inherits from OutputChannel, which is typed. So you can write:

True, but this leads to the following questions:

- Why does Actor "hide" the type parameter of supertrait OutputChannel?

- The "OutputChannel.receiver" method seems a bit misplaced, hard
linking an OutputChannel to an Actor. What's its purpose?

- If you want to send typed messages with a reply, are you meant to use
the Channel class?

- Why does "Channel.?" have return type Msg, while "Channel.!?" has
return type Any?

- Why does Channel use the same type parameter for both the InputChannel
and the OutputChannel? It would often be useful to have separate types
for sent and received messages.

/Jesper Nordenberg


Re: [scala] Re: Why are Scala's actors untyped?

by Philipp Haller-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi, Jesper,

Of course, one can choose a type that somehow subsumes all the types
that an actor receives. (As a minor point, note that when using `Either`
or other types, one has to re-organize the code accordingly.)

However, after giving it more thought I realized that the problem comes
from the dynamic scoping of `self` which refers to the currently
executing actor:

  actor {
    actor {
      ... self ...
    }
    ... self ...
  }

In the above example the two occurrences of `self` refer to two
different actors. Note that `self` has dynamic scope, therefore we can
use `self` inside a function, e.g.

  def f(x: Int): Unit = {
    ... self ...
  }

and it will continue to refer to the currently executing actor even if
the concrete actor instance is not known at compile time:

  actor {
    actor {
      if (b1) f(0)
    }
    if (b2) f(1)
  }

Assuming that using `actor` one could create typed actors `Actor[+Msg]`,
and types `S` and `T` are unrelated, then in

  actor[S] {
    actor[T] {
      ... self ...
    }
    ... self ...
  }

the type of `self` would have to be `Actor[Nothing]` and therefore
useless for typed message sends.

Currently, I see two approaches to allow typed actors:

1. Remove the dynamically-scoped `self` altogether. Replace the untyped
   `actor` function with

     def actor[T](Actor[T] => Unit): Actor[T]

   Example use:

     actor[Int] { self => ... }

   The downside to this is that there is no common way to refer to
   the currently executing actor (regardless of how it is created). As a
   consequence, some patterns used in, e.g., Erlang, are ruled out.

2. Allow some dynamic scoping w.r.t. `self`:
   Keep the untyped `actor` function as a way to create `Actor[Any]`s.
   These actors can use `self` with dynamic scope.

   Typed actors are created by sub-classing `Actor[+Msg]`. Inside typed
   actors, use of the dynamically-scoped `self` results in a runtime
   error.


Cheers,
Philipp


Jesper Nordenberg wrote:

> Philipp Haller wrote:
>> First, why are actors currently untyped?
>> Originally, the actors library emerged from an experiment to implement
>> Erlang in Scala. In that model, it is common to have nested receives, i.e.
>>
>>   receive {
>>     case first =>
>>       ...
>>       receive {
>>         case second => ...
>>       }
>>   }
>>
>> Now, if the types of `first` and `second` are unrelated, then certainly
>> the actor must be able to accept messages of type `Any`. Otherwise, at
>> least one of the receives would block indefinitely which is undesirable.
>
> So, in this case you create an Actor[Any] (or a more advanced type with
> Either or the message sequence encoded in the type). I can't think of
> any reason why the Actor class shouldn't have a type parameter.
>
>> Why does this "untyped" scheme work surprisingly well in Scala? Pattern
>> matching helps you recover types, e.g.:
>>
>>   case class DoThis(x: List[(Int, String)])
>>   receive {
>>     case DoThis(args) => // know that args: List[(Int, String)]
>>   }
>
> The usefulness of message type check is not primarily on the receiver
> side, it's on the caller side. You don't want to send a message of
> incorrect type to an actor and get a runtime error.
>
> In essence, you can view an actor as a function of type "A =>
> Future[B]". Types A and B are clearly related, if you send an actor a
> certain message type you would expect a reply of a certain type. How can
> we encode this in Scala? The straightforward way would be to encode the
> return type in the message type, for example:
>
> trait Message { type ReturnType }
>
> case class MyMess(x : Int, y : Int) extends Message {
>    type ReturnType = Int
> }
>
> trait Actor[Msg] {
>    def !![T <: Msg with Message](msg : T) : Future[T#ReturnType]
> }
>
> (alternatively "trait Actor[Msg <: Message]")
>
> However, implementing the receive method in a type safe way is AFAIK not
> possible to do in Scala, you would have to resort to casting.
>
> /Jesper Nordenberg
>


Re: [scala] Re: Why are Scala's actors untyped?

by Ricky Clarkson :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Philipp,

Apologies for misspelling your name.

By the by, not to 'hit and run' with this thread, I bought Programming
in Erlang by Joe Armstrong recently, not least to make sure that I
understand how actors are supposed to work.  I plan to revisit this
thread/topic when I know what I'm talking about.

When I mentioned the simplicity of my library, I didn't intend to
accuse scala.actors of complexity - I'm quite aware that my library is
very limited (in fact I have a few versions each with different
subsets implemented).  I'm looking at scala.actors for inspiration,
and trying to understand the decisions embodied in it, rather than
trying to outright criticise it.

Cheers,
Ricky.

2008/8/18 Philipp Haller <philipp.haller@...>:

> Hi, Jesper,
>
> Of course, one can choose a type that somehow subsumes all the types
> that an actor receives. (As a minor point, note that when using `Either`
> or other types, one has to re-organize the code accordingly.)
>
> However, after giving it more thought I realized that the problem comes
> from the dynamic scoping of `self` which refers to the currently
> executing actor:
>
>  actor {
>    actor {
>      ... self ...
>    }
>    ... self ...
>  }
>
> In the above example the two occurrences of `self` refer to two
> different actors. Note that `self` has dynamic scope, therefore we can
> use `self` inside a function, e.g.
>
>  def f(x: Int): Unit = {
>    ... self ...
>  }
>
> and it will continue to refer to the currently executing actor even if
> the concrete actor instance is not known at compile time:
>
>  actor {
>    actor {
>      if (b1) f(0)
>    }
>    if (b2) f(1)
>  }
>
> Assuming that using `actor` one could create typed actors `Actor[+Msg]`,
> and types `S` and `T` are unrelated, then in
>
>  actor[S] {
>    actor[T] {
>      ... self ...
>    }
>    ... self ...
>  }
>
> the type of `self` would have to be `Actor[Nothing]` and therefore
> useless for typed message sends.
>
> Currently, I see two approaches to allow typed actors:
>
> 1. Remove the dynamically-scoped `self` altogether. Replace the untyped
>   `actor` function with
>
>     def actor[T](Actor[T] => Unit): Actor[T]
>
>   Example use:
>
>     actor[Int] { self => ... }
>
>   The downside to this is that there is no common way to refer to
>   the currently executing actor (regardless of how it is created). As a
>   consequence, some patterns used in, e.g., Erlang, are ruled out.
>
> 2. Allow some dynamic scoping w.r.t. `self`:
>   Keep the untyped `actor` function as a way to create `Actor[Any]`s.
>   These actors can use `self` with dynamic scope.
>
>   Typed actors are created by sub-classing `Actor[+Msg]`. Inside typed
>   actors, use of the dynamically-scoped `self` results in a runtime
>   error.
>
>
> Cheers,
> Philipp
>
>
> Jesper Nordenberg wrote:
>> Philipp Haller wrote:
>>> First, why are actors currently untyped?
>>> Originally, the actors library emerged from an experiment to implement
>>> Erlang in Scala. In that model, it is common to have nested receives, i.e.
>>>
>>>   receive {
>>>     case first =>
>>>       ...
>>>       receive {
>>>         case second => ...
>>>       }
>>>   }
>>>
>>> Now, if the types of `first` and `second` are unrelated, then certainly
>>> the actor must be able to accept messages of type `Any`. Otherwise, at
>>> least one of the receives would block indefinitely which is undesirable.
>>
>> So, in this case you create an Actor[Any] (or a more advanced type with
>> Either or the message sequence encoded in the type). I can't think of
>> any reason why the Actor class shouldn't have a type parameter.
>>
>>> Why does this "untyped" scheme work surprisingly well in Scala? Pattern
>>> matching helps you recover types, e.g.:
>>>
>>>   case class DoThis(x: List[(Int, String)])
>>>   receive {
>>>     case DoThis(args) => // know that args: List[(Int, String)]
>>>   }
>>
>> The usefulness of message type check is not primarily on the receiver
>> side, it's on the caller side. You don't want to send a message of
>> incorrect type to an actor and get a runtime error.
>>
>> In essence, you can view an actor as a function of type "A =>
>> Future[B]". Types A and B are clearly related, if you send an actor a
>> certain message type you would expect a reply of a certain type. How can
>> we encode this in Scala? The straightforward way would be to encode the
>> return type in the message type, for example:
>>
>> trait Message { type ReturnType }
>>
>> case class MyMess(x : Int, y : Int) extends Message {
>>    type ReturnType = Int
>> }
>>
>> trait Actor[Msg] {
>>    def !![T <: Msg with Message](msg : T) : Future[T#ReturnType]
>> }
>>
>> (alternatively "trait Actor[Msg <: Message]")
>>
>> However, implementing the receive method in a type safe way is AFAIK not
>> possible to do in Scala, you would have to resort to casting.
>>
>> /Jesper Nordenberg
>>
>
>