[mercury-users] Functor(Arg) Terms Construction (Not Partially Instantitated?)
Fergus Henderson
fjh at cs.mu.OZ.AU
Mon May 19 12:58:58 AEST 2003
On 18-May-2003, Goncalo Jorge Coelho e Silva <l10454 at alunos.uevora.pt> wrote:
>
> But, would I be able to construct a functor(arguments) term
> using a one-fits-all predicate like this one?
>
> (using this example of non-compilable Mercury, just to show
> what I'd like)
>
> :- type address == int.
> :- type value == int.
> :- type my_things ---> set_value(address, value).
>
> main -->
> {
> X = 1,
> Y = 1,
> Z = "set_value",
> Term = Z(X, Y)
> },
> run_instr(Term).
>
> run_instr(set_value(Address, Value))-->
> ...
If you really want to do something like that, it is possible to do so using
the procedures in the `construct' module in the standard library. Instead
of writing `Term = Z(X, Y)', you can write `Term = make_term(Z, X, Y)',
where make_term is defined as follows:
:- import_module int, list, std_util, construct, require.
:- func make_term(string, T1, T2) = T.
make_term(Functor, Arg1, Arg2) =
make_term_with_arglist(Functor, [univ(Arg1), univ(Arg2)]).
:- func make_term_with_arglist(string, list(univ)) = T.
make_term_with_arglist(Functor, Args) = Term :-
Arity = list.length(Args),
Type = std_util.type_of(Term),
(if
Univ = construct.construct(Type,
lookup_constructor(Type, Functor, Arity),
Args),
std_util.univ_to_type(Univ, Term0)
then
Term = Term0
else
require.error("make_term_with_arglist failed")
).
:- func lookup_constructor(type_desc, string, int) = int.
lookup_constructor(Type, FunctorName, Arity) =
lookup_constructor_2(Type, FunctorName, Arity,
0, construct.num_functors(Type)).
:- func lookup_constructor_2(type_desc, string, int, int, int) = int.
lookup_constructor_2(Type, FunctorName, Arity, CtorNum0, Max)
= CtorNum :-
(if CtorNum0 >= Max then
require.error("lookup_constructor failed")
else if construct.get_functor(Type, CtorNum0, FunctorName,
Arity, _)
then
CtorNum = CtorNum0
else
CtorNum = lookup_constructor_2(Type,
FunctorName, Arity, CtorNum0 + 1, Max)
).
Possibly the predicates make_term, make_term_with_arglist, and
lookup_constructor may be good candidates for future additions
to the Mercury standard library.
I have attached a complete working example.
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
The University of Melbourne | of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.
-------------- next part --------------
:- module construct_example.
:- interface.
:- import_module io.
:- pred main(io::di, io::uo) is det.
:- implementation.
:- import_module int, list, std_util, construct, require.
:- type address == int.
:- type value == int.
:- type my_things ---> set_value(address, value).
main -->
{
X = 1,
Y = 1,
Z = "set_value",
Term = make_term(Z, X, Y)
},
run_instr(Term).
:- pred run_instr(my_things::in, io.state::di, io.state::uo)
is det.
run_instr(set_value(Address, Value)) -->
print("set_value "), print(Address), print(" "), print(Value),
nl.
:- func make_term(string, T1, T2) = T.
make_term(Functor, Arg1, Arg2) =
make_term_with_arglist(Functor, [univ(Arg1), univ(Arg2)]).
:- func make_term_with_arglist(string, list(univ)) = T.
make_term_with_arglist(Functor, Args) = Term :-
Arity = list.length(Args),
Type = std_util.type_of(Term),
(if
Univ = construct.construct(Type,
lookup_constructor(Type, Functor, Arity),
Args),
std_util.univ_to_type(Univ, Term0)
then
Term = Term0
else
require.error("make_term_with_arglist failed")
).
:- func lookup_constructor(type_desc, string, int) = int.
lookup_constructor(Type, FunctorName, Arity) =
lookup_constructor_2(Type, FunctorName, Arity,
0, construct.num_functors(Type)).
:- func lookup_constructor_2(type_desc, string, int, int, int) = int.
lookup_constructor_2(Type, FunctorName, Arity, CtorNum0, Max)
= CtorNum :-
(if CtorNum0 >= Max then
require.error("lookup_constructor failed")
else if construct.get_functor(Type, CtorNum0, FunctorName,
Arity, _)
then
CtorNum = CtorNum0
else
CtorNum = lookup_constructor_2(Type,
FunctorName, Arity, CtorNum0 + 1, Max)
).
More information about the users
mailing list