On 8 March 2014 13:31, Daniel Armak <danar...@gmail.com> wrote:

> Hi Derek.
>
> Yes, I'm aware of the tradeoffs and the reasons for them. It just seems to
> me there ought to be a middle road.
>
> Here's an idea off the top of my head. If remoting is going to be
> transparent, there won't be compile time type assurance. So let's give up
> on local type assurance too, and just use types for documentation and
> refactoring; that still seems a lot better than nothing.
>
> Suppose for each actor I wanted to implement, I declare a trait with a
> method for each message it might receive. Each method must receive exactly
> one parameter, which is the message, and return Unit:
>
> trait Printer {
>   def print(msg: String): Unit
> }
>
> The method name 'print' is just for documentation; only the parameter is
> sent as the message. This preserves transparency with the actor model; you
> don't rely on the trait implementation to build the actual message.
>
> The user of an ActorRef would use a wrapper (value type around the
> ActorRef) generated by a macro to implement this trait. The macro would
> also validate the trait: each method has one argument, returns Unit, and
> all argument types are distinct. Each method call would be implemented as a
> send().
>
> val actor : ActorRef = ???
> val typedActor: Printer = mymacro.wrap[Printer](actor) // Or is there a
> way to declare types with macros? I forget.
> typedActor.print("my message")
>
> The macro would add an (implicit sender: ActorRef) argument to each method.
>
> The actor itself would extend the Printer trait and implement its methods.
> Another macro would concatenate them to implement receive:
>
> class PrinterActor extends Actor with Printer with
> TypedActorMacro[Printer] {
>   def print(msg: String):
> }
>
> To use become/unbecome, we could introduce something more complicated. Or,
> even, use the Printer trait only on the sender side - it would still be
> useful. This is just a rough outline. Do you think it might be useful, or
> do you think I shouldn't go down this road and trying to marry akka actors
> and (actor) types is a futile endeavour?
>

Not futile, but highly suspect.  You've barely scratched the surface with
the above and much research is way ahead of you here.

The ??? you have above isn't exactly trivial to implement, for example.
What's more is that you've probably thrown away a ton more features in the
process.  e.g.:

class MyActor(printActor: PrinterActor) { ... }

// later...

val myActor =
  MyActor.props(loadBalancer(printerActor.props()))
// oops. Does the "loadBalancer" now have to
// implement Printer?  What if it's a load
// balancer in front of scatter gather routers
// that talk to forwarders that talk to various
// different versions of Printers?  Does everyone
// have to implement the same API?  If not, how
// are you not throwing away type safety?  And, if so
// how am I doing anything but writing annoying code
// that keeps me a slave to the API?  And how do I
// easily manage API changes, and so on, and so forth?

Maybe not theoretically futile, but practically?  Probably :)

To be perfectly honest, it seems as though you're trying to "fix" a problem
without having travelled a mile in its shoes yet.  There are subsets of the
problem that are much more important and more possible to cage, and you
will see them as you progress.  When you do, focusing on those (should you
still believe them to be worth it) might be the far better option.


>
> Thanks!
>
> On Sat, Mar 8, 2014 at 7:51 PM, Derek Wyatt <de...@derekwyatt.org> wrote:
>
>> What you're experiencing is a trade-off.  Actors provide a trade-off that
>> you don't seem to be taking into account; endpoints (Actors) are untyped
>> and the messages that they handle are strongly typed.
>>
>> You can't have an Actor be able to process "anything" with a
>> type-specific receive method.  With Actor programming, I should be able to
>> add as many intermediaries in the message flow as I like and not disturb
>> the two endpoints. The intermediaries should equally be ignorant of what's
>> happening (load balancers, routers, loggers, cachers, mediators,
>> scatter-gather, and so forth).  You should also be able to move them around
>> a cluster without disturbing the endpoints.  You can also set up dynamic
>> delegation in an Actor without it having to really understand what's going
>> on - for example, an Actor that speaks the "main dialect" but delegates to
>> something else when it doesn't understand what's being said.
>>
>> If you want to eliminate all of those features, then you will be able to
>> get the type-safe determinism you're looking for (so long as you stay in
>> the same JVM - crossing JVMs will incur a "what the hell am I *really* 
>> talking
>> to?" question that eliminates a compile time assurance). Roland also tried
>> bringing the best of both worlds together using Typed Channels but I think
>> it was lacking a high enough success level to survive, but it might be a
>> way to get closer to your ideal.
>>
>> In short, you're giving up type safety in order to open the door to a
>> whole new set of facilities.  Don't want to lose the type-safety?  Close
>> the door :)
>>
>> I had the exact same reservations as you have right now.  I tried to
>> reconcile them myself, using typed actors and my world turned into a pile
>> of crap... I got no real flexibility out of that system.  There was a
>> cognitive overhead to switching to actors and no benefit.
>>
>> In the end, I learned to embrace the patterns and philosophy and grew to
>> love it so much that I wrote a book about it (the first one, I think) and
>> now code in Scala and Akka every single day.  Your mileage may vary :)
>>
>>
>> On Friday, March 7, 2014 5:10:23 PM UTC-5, Daniel Armak wrote:
>>>
>>> Hello,
>>>
>>> I hope someone will take the time to read this message (sorry about its
>>> length) and help me.
>>>
>>> I'm writing a fairly large system from scratch in Scala. I love the rich
>>> typing and functional programming style, and I have experience with
>>> future-based programming, but not actors.
>>>
>>> When I try to use actors, I feel like I'm giving up static typing, even
>>> the basic feature of a type declaring its methods (=received messages). 
>>> Using
>>> partial functions feels like casting, because I really want to assert that
>>> the 'partial' function will always match.
>>>
>>> This can't be right. How do you reconcile the two worlds?
>>>
>>> Specific issues I'm struggling with:
>>>
>>> 1. Typed code is discoverable via methods and fields. An actor relies on
>>> documentation.
>>>
>>> One option is to define all messages an actor can receive in its
>>> companion object, and document each message; but many libraries (e.g.
>>> spray) define many different actors that all send and receive the same
>>> types (eg HttpRequest), which is convenient for forwarding messages between
>>> actors. But then the *only* way to figure out which messages are legal and
>>> the semantics of what they do is to read the docs.
>>>
>>> When an actor manages complex state and might receive ten or twenty
>>> different message types, this is hard to manage.
>>>
>>> Even if I document the actor, this documentation is still not
>>> discoverable because the client has an ActorRef, not an
>>> ActorRef[MyActorTrait]. So I have to figure out manually what behavior this
>>> actor is expected to implement and read the docs for that.
>>>
>>> 2. Refactoring actors is hard. To make a non-backward-compatible API
>>> change to an actor, I have to go over all references to the message types
>>> involved. No more 'find all usages of method' or 'rename method'.
>>>
>>> 3. Typed Actors lack important Actor features (become/unbecome, etc),
>>> have to declare exceptions, suffer a proxy performance penalty, and aren't
>>> recommended as a replacement for actors in general.
>>>
>>>
>>> I understand that features like become() and remoting make it difficult
>>> to type actors, and maybe this is just an unsolved difficult problem. So
>>> how do mature actor-based projects handle these issues? How can I have the
>>> benefits of both actors and static typing?
>>>
>>> TIA for any insight.
>>>
>>> Daniel Armak
>>>
>>  --
>> >>>>>>>>>> Read the docs: http://akka.io/docs/
>> >>>>>>>>>> Check the FAQ:
>> http://doc.akka.io/docs/akka/current/additional/faq.html
>> >>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
>> ---
>> You received this message because you are subscribed to the Google Groups
>> "Akka User List" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to akka-user+unsubscr...@googlegroups.com.
>> To post to this group, send email to akka-user@googlegroups.com.
>> Visit this group at http://groups.google.com/group/akka-user.
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>  --
> >>>>>>>>>> Read the docs: http://akka.io/docs/
> >>>>>>>>>> Check the FAQ:
> http://doc.akka.io/docs/akka/current/additional/faq.html
> >>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "Akka User List" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/akka-user/rLKk7-D_jHQ/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> akka-user+unsubscr...@googlegroups.com.
> To post to this group, send email to akka-user@googlegroups.com.
> Visit this group at http://groups.google.com/group/akka-user.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
>>>>>>>>>>      Read the docs: http://akka.io/docs/
>>>>>>>>>>      Check the FAQ: 
>>>>>>>>>> http://doc.akka.io/docs/akka/current/additional/faq.html
>>>>>>>>>>      Search the archives: https://groups.google.com/group/akka-user
--- 
You received this message because you are subscribed to the Google Groups "Akka 
User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to akka-user+unsubscr...@googlegroups.com.
To post to this group, send email to akka-user@googlegroups.com.
Visit this group at http://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.

Reply via email to