|
As much as I love APL for its notation, Erlang does provides equivalent highlevel operators for processing sequences of elements. It's not fair to compare your highlevel implementation in APL to your lowlevel optimized (and quite unreadable) solution in Erlang. Here's the equivalent algorithm: is_descendant(A, B) ->
lists:all(fun ({Actor, Event}) ->
Event =< proplists:get_value(Actor, B, -1)
end, A).
compare(A, B) ->
A_in_B = is_descendant(A, B),
B_in_A = is_descendant(B, A),
{A_in_B,
B_in_A,
A_in_B and B_in_A,
not (A_in_B or B_in_A}}.
The function `is_descendant` is nearly a translation of your APL code. I'm not convinced that we need APL on the Beam, for the quality of this VM certainly isn't in its array processing capabality... but I was expecting the argument "such an array-oriented language would motivate improvements in this direction", which is definitively true!APL-enthousiasts often forget that APL forces you to use its builtin operators, while modern languages provide means to implement them (and aren't restricted to arrays). lists:all isn't a builtin in Erlang, but does it really matters that you can write it as `^/` in APL? Note for functional programmers: `^` is the boolean AND operator, `/` is `fold`, and somehow there's an APL builtin hack so that `fold` knows that 1 (true) is the monoid identity of `AND`... but really `^/` is a compact notation for `fold (&&) True` For completness: all(_, []) -> true.
all(Pred, [X | Xs]) -> Pred(X) andalso all(Pred, Xs).
get_value(_, [], Default) -> Default;
get_value(K, [{K, V} | _], _) -> V;
get_value(K, [_ | Rest], Default) -> get_value(K, Rest, Default).
|
There are a squad of specific set related problems in Riak that the Basho engineers skirted round or were afraid of - and they were all about Set operations - so APL's focus on tiny notational programmes that are graspable in the mind is appealing for that basis.
Is this the most considered blog post? No, hell no ;-) but APL struck me as fascinating...