riccardotommasini / ppl

This repository contains the material related to the practical classes of the course Principles of Programming Languages
Apache License 2.0
29 stars 12 forks source link

[LAST ERLANG CLASS] Easier brancy? #10

Open DavideSampietro opened 6 years ago

DavideSampietro commented 6 years ago

What if we simply impose an order in the reception of the messages from the subtrees? They'll just stack in the mailbox, no deadlock should arise:

brancy(L, R, Fun) ->
    receive
        {ask, P} ->
            % they ask their sons for the values
            L ! {ask, self()},
            R ! {ask, self()},
            % at this point you expect an answer...
            receive
                {L, V1} -> Op1 = V1
            end,
            receive
                {R, V2} -> Op2 = V2
            end,
            % now you evaluate your function for the father
            P ! {self(), Fun(Op1, Op2)}
    end.

This sounds easier to me...

leonardoarcari commented 6 years ago

I thought the same while re-doing the exercise on my own. The only thing I didn't like was having a hanging receive on a branch while the other one may have already finished. The solution I came up with is a little more verbose, but exploiting pattern matching it becomes easier to read and reason about, while keeping the branchy interface the same.

waitBranches(Left, Right, nil, nil) ->
    receive
        {Left, V} -> waitBranches(Left, Right, V, nil);
        {Right, V} -> waitBranches(Left, Right, nil, V)
    end;

waitBranches(Left, Right, LVal, RVal) ->
    receive
        {Left, V} -> {V, RVal};
        {Right, V} -> {LVal, V}
    end.

branchy(F, Left, Right) ->
    receive
        {ask, P} ->
            Left ! {ask, self()},
            Right ! {ask, self()},
            {LVal, RVal} = waitBranches(Left, Right, nil, nil),
            P ! {self(), F(LVal, RVal)}
    end.

Edit: Changed code according to https://github.com/riccardotommasini/ppl/issues/10#issuecomment-356995756

riccardotommasini commented 6 years ago

I like it a lot more, can I include this code in the repository?

DavideSampietro commented 6 years ago

@leonardoarcari you need to swap :) (if I'm getting that right...)

waitBranches(Left, Right, LVal, RVal) ->
    receive
        {Left, V} -> {V, RVal};
        {Right, V} -> {LVal, V}    <-------
    end.
DavideSampietro commented 6 years ago

As for me, no problem with using my code :)

leonardoarcari commented 6 years ago

@DavideSampietro Sure thing! Thanks!