Lisp-Python vs. Erlang (was MLvtA, was Meta)
Ulf Wiger (TN/EAB)
ulf.wiger@REDACTED
Fri Aug 25 14:22:49 CEST 2006
Not having though it through much, wouldn't
ordsets be a better starting point than
unordered lists?
Ordsets are defined as being ordered lists, so it
should be perfectly ok to use the odd lists library
function on them.
BR,
Ulf W
> -----Original Message-----
> From: owner-erlang-questions@REDACTED
> [mailto:owner-erlang-questions@REDACTED] On Behalf Of Sean Hinde
> Sent: den 25 augusti 2006 12:28
> To: Jay Nelson
> Cc: erlang-questions@REDACTED
> Subject: Re: Lisp-Python vs. Erlang (was MLvtA, was Meta)
>
> This is fun!
>
> Here is my Erlang translation of the GPS from Norvig,
> following the lisp code as closely as possible.
>
> I found it quite kludgy to write in erlang. I ended up using
> a deprecated function from lists.erl, and there were some
> features of lisp like named parameters and extension
> parameters that seemed quite nice - although perhaps not so
> much until Luke forcefully pointed out the benefits :-)
>
> Heavy higher order function programming certainly seems less
> elegant in Erlang than lisp or any of the modern statically
> typed functional languages.
>
> Sean
>
> -module(gps).
>
> -export([gps/3]).
>
> -record(op,
> {
> action,
> preconds = [],
> add_list = [],
> del_list = []
> }).
>
> gps(State, Goals, Ops) ->
> put(state, State),
> put(ops, Ops),
> lists:all(fun achieve/1, Goals).
>
> achieve(Goal) ->
> State = get(state),
> Ops = get(ops),
> lists:member(Goal, State) orelse
> lists:any(fun apply_op/1, find_all(Goal, Ops, fun
> appropriate_p/2)).
>
> appropriate_p(Op, Goal) ->
> lists:member(Goal, Op#op.add_list).
>
> apply_op(Op) ->
> case lists:all(fun achieve/1, Op#op.preconds) of
> true ->
> io:format("Executing ~p~n",[Op#op.action]),
> put(state, get(state) -- Op#op.del_list),
> put(state, merge(get(state), Op#op.add_list)),
> true;
> false ->
> false
> end.
>
> merge(L1, L2) ->
> lists:merge(lists:sort(L1), lists:sort(L2)).
>
> find_all(Goal, Ops, Pred) ->
> lists:filter(Pred, [Goal], Ops).
>
>
>
> On 25 Aug 2006, at 03:05, Jay Nelson wrote:
>
> > James Hague wrote:
> >
> > > But C# and Java aren't worth worrying about, IMO. The interesting
> > > stuff is happening in the scripting language world,
> especially with
> > > Python and Ruby. Those languages are a lot closer to Lisp (see
> > > http://www.norvig.com/python-lisp.html).
> >
> >
> > Here's my conversion of the Lisp / Python example Norvig gave:
> >
> > -------------------------------------------------
> >
> > -module(norvig).
> >
> > -export([generate/1, generate_tree/1]).
> >
> > % Constructions...
> > grammar(s) -> [np, vp];
> > grammar(np) -> [art, n];
> > grammar(vp) -> [v, np];
> >
> > % Elements...
> > grammar(art) -> {"the", "a"};
> > grammar(n) -> {"man", "ball", "woman", "table"};
> > grammar(v) -> {"hit", "took", "saw", "liked"};
> >
> > % Unknown.
> > grammar(_) -> none.
> >
> >
> >
> > generate(Phrase) when is_atom(Phrase) ->
> > case grammar(Phrase) of
> > none ->
> > [Phrase];
> > Words when is_tuple(Words) ->
> > ChoiceNum = random:uniform(size(Words)),
> > element(ChoiceNum, Words);
> > Construct ->
> > generate(Construct)
> > end;
> >
> > generate(Phrase) ->
> > [generate(Word) || Word <- Phrase].
> >
> >
> >
> > generate_tree(Phrase) when is_atom(Phrase) ->
> > case grammar(Phrase) of
> > none ->
> > [Phrase];
> > Words when is_tuple(Words) ->
> > ChoiceNum = random:uniform(size(Words)),
> > {Phrase, element(ChoiceNum, Words)};
> > Construct ->
> > [Phrase, generate_tree(Construct)]
> > end;
> >
> > generate_tree(Phrase) ->
> > [generate_tree(Word) || Word <- Phrase].
> >
> > ---------------------------------------------------
> >
> >
> > I deliberately left it similar to his so that people
> unfamiliar with
> > lisp can see the correspondence, but I don't like the repetition of
> > the generate functions. I would prefer to use a vlad-macro or an
> > annotate function to collapse the 2nd and 3rd branches of the case
> > statement so that there is a single generate function in
> source code
> > with two variants.
> >
> > [This is an example of when a real macro is more readable than a
> > support function, because the two branches are different in
> different
> > ways, so the annotate function would have to have two branches or
> > there would have to be two annotate functions, whereas a
> single macro
> > could handle both cases. As an exercise to the reader, try writing
> > the annotate approach and you'll see the slight awkwardness.]
> >
> >
> > I think it reads clearer than lisp or python for the following
> > reasons:
> >
> > 1) Prolog-like patterns map to the problem domain as a grammar
> > function
> > rather than the artificial list/hash map structure. Also the
> > compiler
> > can optimize it more easily so clarity plus speed.
> >
> > 2) The list comprehension is just a succinct joy.
> >
> > 3) The use of tuples and lists differentiates intent better.
> >
> > 4) I prefer the case ... of ... end style over (cond ( ) ...) now.
> > Syntactically there is not much difference but erlang
> > suggests using similar (and more readable) patterns
> > in each branch of the case.
> >
> >
> > If I had a month or two to burn I would go through the exercise of
> > porting Norvig's AI code to erlang. There's no reason why
> it wouldn't
> > all work -- and possibly discover some new parallel
> approaches in the
> > process. I think erlang is a perfectly suited to many
> problems that
> > lisp was.
> >
> >
> > jay
>
>
More information about the erlang-questions
mailing list