[dmd-concurrency] Pattern matching on message receives, error handling

Fawzi Mohamed fawzi at gmx.ch
Wed Jan 13 08:16:48 PST 2010


On 13-gen-10, at 16:44, Mark Kegel wrote:

> The reason I'm scared is fairly simple, I've seen this exact design
> (well maybe not exact, but the similarities are too great to ignore)
> used before. I worked for a couple of years on a large Telco system.
> Message handling was its bread and butter. We had lots of independent
> process with probably thousands of different messages flying through
> the system.
>
> One thing that got beat into my head was that you really, really want
> to be able to easily trace the sequence of messages in a system. What
> pattern matching gives you is a more concise notation for telling
> outside users what is handled and what is not. That is the protocols
> that actors use to communicate are made explicit, not left implicit
> and thus recalcuated everytime you want to know how it works. In
> essence you can segment your code more cleanly along logical
> communication lines rather than function signature, since one function
> signature might be the entry point for fifteen different completely
> orthogonal messages.
>
> It really all comes down to how easily the syntax of the language
> scales to large designs. Sure, taking anonymous functions and then
> testing for all messages that matching that signature is exactly as
> powerful as pattern matching, but I would contend that its a lot less
> readable.
>
> So lets assume that you let receive() take some kind of pattern
> object, what might this look like? To write it out in the worst
> possible way, here's one idea:
>
> receive( pattern("foo", _1) + (string a, string b) { ...},
>            pattern("bar", _1) + (string a, string b) { ...},
>            pattern(_1, _2) + (string a, string b) { ...},
>            ...
>          );
>
> I've used _* placeholders similar to the way boost lambda does.
>
> While I've intentionally made this as ugly (and self documenting) as
> possible, I really have no idea how'd you'd clean this syntax up,
> since I'm just not that familiar with D's introspection capabilites.
> Does any one more familiar with D have a better way to implement
> pattern matching?

maybe the place where you want to go looks like exposing an object  
that has several methods, and thus a fixed interface, and have  
execution on that object be sequential by default on the server (what  
I do in blip.parallel.rpc).
Also to send a message in general you use a proxy tat has exactly the  
same exposed interface and does the remote call.

Fawzi
>
> Mark
>
>
> On Tue, Jan 12, 2010 at 11:38 PM, Sean Kelly  
> <sean at invisibleduck.org> wrote:
>> On Jan 12, 2010, at 7:54 PM, Andrei Alexandrescu wrote:
>>
>>> Mark Kegel wrote:
>>>> Call me silly, but how many of you have seen 1000 line switch
>>>> statements when polymorphism was called for? And what is
>>>> polymorphism but dispatch / pattern matching over argument type?
>>>> So when I see code like this:
>>>>       auto msg = receiveOnly!(Tid, int)();
>>>>       if (!msg[0]) return;
>>>>       writeln("Secondary thread: ", msg[1]);
>>>>       msg[0].send(thisTid);
>>>> ...where you the first thing you tell new readers about how to
>>>> test what message you just got is with an 'if' statement, I get
>>>> scared. Please give users a more elegant mechanism, and if you
>>>> need ideas about what it could look like I would suggest that
>>>> Scala offers a passable (and maybe even compatible) syntax.
>>>
>>> You have a point, but quite a weak one. First, the example above  
>>> is not illustrative on the pattern matching capabilities of D;  
>>> we'll get to those with the full-fledged receive() function. For  
>>> now I just considered fine to send a null Tid to signal loop  
>>> termination. With receive() you can dispatch to various functions  
>>> depending on the types of the arguments. With introspection it's  
>>> very easy to dispatch messages to an object depending on their  
>>> types.
>>>
>>> I don't agree with the comparison with switch() vs. virtuals at  
>>> all. The problem with switch() is that it breaks modularity by  
>>> requiring all cases to be present in the same place. On the  
>>> contrary, pattern matching _also_ requires all cases to be present  
>>> together (which makes me believe it's much less powerful than it's  
>>> cracked to be). So if I pattern match with
>>>
>>> patternmatch (receive()) {
>>>    case int x: ...
>>>    case (string a, int b): ...
>>> }
>>>
>>> versus
>>>
>>> receive(
>>>    (int x) { ... },
>>>    (string a, int b) { ... }
>>> );
>>>
>>> we're only talking about a difference in syntax, not power. So  
>>> essentially you shouldn't be scared just because there's no built- 
>>> in syntax for something that can be expressed within the existing  
>>> language with the same power.
>>
>> It's worth adding that Erlang does provide pattern matching  
>> capabilities that have to be a run time in D, but I'm not sure this  
>> same capability is available in Scala, for example.  In our case,  
>> this will probably be handled manually by the user, with possibly  
>> some fancier way to do it later (metaprogramming can do quite a lot  
>> in D).  For example:
>>
>>    receive(
>>        (int x) { ... },
>>        (string a, int b) { if (a == "blah") return false; ...;  
>> return true; }
>>    );
>>
>> Here, the second function checks string a to see if it matches a  
>> pattern, and returns true/false to indicate that there was a match.
>>
>> _______________________________________________
>> dmd-concurrency mailing list
>> dmd-concurrency at puremagic.com
>> http://lists.puremagic.com/mailman/listinfo/dmd-concurrency
>>
> _______________________________________________
> dmd-concurrency mailing list
> dmd-concurrency at puremagic.com
> http://lists.puremagic.com/mailman/listinfo/dmd-concurrency



More information about the dmd-concurrency mailing list