Home > Archive > Prolog > January 2006 > Generic term search in a list
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Generic term search in a list
|
|
| Steffen Schwigon 2006-01-10, 7:57 am |
| Hi!
My sub-average prolog skills need a lesson. I use swi-prolog.
I have an application in which I want to give kind of
option arguments into my predicates, e.g this way:
get_d(Options, depends_on(B,C), D) :-
options:get_range(Options, range(Min,Max)),
calendar:fruehestens_danach(Options, C,D),
calendar:fruehestens_x_tage_danach(Optio
ns, B,10,D),
calendar:ist_guter_tag(D),
between(Min,Max,D).
When "get_d" is called, "Options" is a term containing a list of
option terms, e.g.:
options([range(100,300), foo(12), bar(1,2,3)])
I specify the "Options" at toplevel and hand it over to each predicate
that might also use them. Each predicate then extracts the options it
needs; some might need "range(Min,Max)", another one needs "foo(X)" or
"bar(X,Y,Z)". If an option is not contained, default values are
returned.
What I want is a clever way to extract a specific option.
My current option handling looks too explicit and non-gerneric. I have
a recursive search for each option, because of different arities of
the option terms and the different default values for each option.
%% Option: range(Min,Max) - default: range(0, inf).
get_range(options([]), Range) :- Range = range(0,inf), !.
get_range(options([range(Min, Max)|_]), range(Min, Max)).
get_range(options([Head|Tail]), Range) :-
Head \= range(_,_),
get_range(options(Tail), Range).
%% Option: foo(F) - default: foo(1).
get_foo(options([]), Foo) :- Foo = foo(1), !.
get_foo(options([foo(Min)|_]), foo(Min)).
get_foo(options([Head|Tail]), Foo) :-
Head \= foo(_),
get_foo(options(Tail), Foo).
It would be better to have a generic recursive search for a matching
term name and a way to specify which term to search and which default
value it should have. Something that could easily be extend for more
options.
E.g., a general option searcher:
get_option(Options, Termname, Default, Result) :- ... ???.
and specifications of different options, arities and default values:
get_range(Options, R) :- get_option(Options, 'range', range(0, inf), R).
get_foo(Options, F) :- get_option(Options, 'foo', foo(1), F).
The option terms are unambiguous in name and arity, e.g. there is only
one "range" option with its specific arity, and not another one with
different arity.
==> I don't really know how to do it. Different experiments
stumbled. I had most problems in mapping strings to terms,
respectively understanding the right usage of things like
atom_to_term/3. I don't even know whether that's the right
direction.
Could someone please give me some help?
Thanks in advance.
Steffen
--
Steffen Schwigon <schwigon@webit.de>
Dresden Perl Mongers <http://dresden-pm.org/>
| |
| Jan Wielemaker 2006-01-10, 7:57 am |
| On 2006-01-10, Steffen Schwigon <schwigon@webit.de> wrote:
> Hi!
>
> My sub-average prolog skills need a lesson. I use swi-prolog.
>
> I have an application in which I want to give kind of
> option arguments into my predicates, e.g this way:
>
> get_d(Options, depends_on(B,C), D) :-
> options:get_range(Options, range(Min,Max)),
> calendar:fruehestens_danach(Options, C,D),
> calendar:fruehestens_x_tage_danach(Optio
ns, B,10,D),
> calendar:ist_guter_tag(D),
> between(Min,Max,D).
>
> When "get_d" is called, "Options" is a term containing a list of
> option terms, e.g.:
>
> options([range(100,300), foo(12), bar(1,2,3)])
>
> I specify the "Options" at toplevel and hand it over to each predicate
> that might also use them. Each predicate then extracts the options it
> needs; some might need "range(Min,Max)", another one needs "foo(X)" or
> "bar(X,Y,Z)". If an option is not contained, default values are
> returned.
>
> What I want is a clever way to extract a specific option.
>
> My current option handling looks too explicit and non-gerneric. I have
> a recursive search for each option, because of different arities of
> the option terms and the different default values for each option.
>
> %% Option: range(Min,Max) - default: range(0, inf).
> get_range(options([]), Range) :- Range = range(0,inf), !.
> get_range(options([range(Min, Max)|_]), range(Min, Max)).
> get_range(options([Head|Tail]), Range) :-
> Head \= range(_,_),
> get_range(options(Tail), Range).
What about
get_range(options(Options), Range) :-
Range = range(_, ),
( memberchk(Range, Options)
-> true
; Range = range(0,inf)
).
I see little purpose in the options/1 representation and would use
a plain list. The code above also gives a good idea how to make
it generic.
>==> I don't really know how to do it. Different experiments
> stumbled. I had most problems in mapping strings to terms,
> respectively understanding the right usage of things like
> atom_to_term/3. I don't even know whether that's the right
> direction.
Unless you have to deal exchange Prolog terms with systems that
are unaware of them, atom_to_term/3 is rarely a good idea.
Hope this helps
--- Jan
| |
| Steffen Schwigon 2006-01-10, 7:57 am |
| Jan Wielemaker <jan@nospam.ct.xs4all.nl> writes:
> What about
>
> get_range(options(Options), Range) :-
> Range = range(_, ),
> ( memberchk(Range, Options)
> -> true
> ; Range = range(0,inf)
> ).
Aha, memberchk. Looks good. Thanks.
> I see little purpose in the options/1 representation and would use a
> plain list.
I do such things often for readability. Less for the definition
of the predicates but mostly when they are called. I prefer
get_d(options([range(1,2), foo(12), bar(65)]), depends(B,C), D)
over
get_d([range(1,2), foo(12), bar(65)], depends(B,C), D)
I'm still learning typical patterns and are experimenting to find my
personal style. Would you consider the above as unusual style in
Prolog?
Thanks.
Steffen
--
Steffen Schwigon <schwigon@webit.de>
Dresden Perl Mongers <http://dresden-pm.org/>
| |
| Jan Wielemaker 2006-01-10, 9:58 pm |
| On 2006-01-10, Steffen Schwigon <schwigon@webit.de> wrote:
> Jan Wielemaker <jan@nospam.ct.xs4all.nl> writes:
>
> Aha, memberchk. Looks good. Thanks.
>
>
>
> I do such things often for readability. Less for the definition
> of the predicates but mostly when they are called. I prefer
>
> get_d(options([range(1,2), foo(12), bar(65)]), depends(B,C), D)
>
> over
>
> get_d([range(1,2), foo(12), bar(65)], depends(B,C), D)
>
>
> I'm still learning typical patterns and are experimenting to find my
> personal style. Would you consider the above as unusual style in
> Prolog?
If you look at most of the ISO predicates that use option lists, they
carry them as last argument without option() around them. Carrying
them as last argument makes sense, as you normally want the first
argument for things you switch on to exploit clause-indexing. You do
not switch on the option list in a way that is exploitable by
clause-indexing. By carrying option lists always at the end there is
not that much need for an extra option(). I'm not saying it is bad
style to use option(). There is some point in trying to addopt to
current practice and only develop your own style for things you `can't
live with' though. There is a good document on style issues by
Michael A. Covington at http://www.ai.uga.edu/mc/plcoding.pdf. I also
keep recommending reading Richard O'Keefe's "The Craft of Prolog" for
anyone who plans to take Prolog programming seriously (considering
your questions you appear to be in this group).
Enjoy --- Jan
| |
| Steffen Schwigon 2006-01-10, 9:58 pm |
| Jan Wielemaker <jan@nospam.ct.xs4all.nl> writes:
> There is a good document on style issues by Michael A. Covington at
> http://www.ai.uga.edu/mc/plcoding.pdf.
This guide is great. It will become my new bible. Thanks.
Steffen
--
Steffen Schwigon <schwigon@webit.de>
Dresden Perl Mongers <http://dresden-pm.org/>
|
|
|
|
|