[mercury-users] partial instantiation?

Mark Brown mark at csse.unimelb.edu.au
Tue Apr 20 07:24:40 AEST 2010


On 19-Apr-2010, Tomas By <tomas at basun.net> wrote:
> On Mon, April 19, 2010 19:56, Mark Brown wrote:
> > On 19-Apr-2010, Tomas By <tomas at basun.net> wrote:
> >> What I get on the command line is ["command","foo","42"],
> >
> > So cmd is called with the (ground) value [str("foo"), int(42)] as the
> > second argument, and dosomething(42, "foo") is returned.
> 
> Are you telling me what I should be doing instead of what I want myself?
> 
> Good luck with that eh!

I thought I was telling you what you wanted...

> 
> Here is the code that calls cmd/3 (in an earlier version that never
> worked, but anyway):
> 
> |:- pred command(list(string),maybe(cmdproc),errors,errors).
> |:- mode command(in,out,in,out) is det.
> |
> |command(As,MC,!Es) :-
> |  ( As = [],                              MC = yes(none)
> |  ; As = [CS|Ss],
> |    solutions((pred(P::out) is nondet :-
> |      cmd(CS,AA,PR), P = AA-PR ),Ps),
> |    ( Ps = [] ->
> |      add_error(unknown_command(CS),!Es), MC = no
> |    ; solutions((pred(X::out) is nondet :-
> |        member(Zs-X,Ps), cmdargs(Zs,Ss)),Xs),
> |      ( Xs = [Proc] ->                    MC = yes(Proc)
> |      ; add_error(funny_cmdline(As),!Es), MC = no ) ) ).

Ah, I think I see what you are getting at.  Aside from picking the right
cmdproc for the given arguments, you also want to be able to check whether
there exists any implementation of the command at all (so you know whether
the error is "unknown command" or "funny command line").  It wasn't clear
that's what you wanted.

> 
> `As' is what comes out of getopt.process_options, and the `cmdproc' takes
> some additional arguments including the io.state.
> 
> I'd be interested in ideas about how to do this in Mercury. My only
> absolute requirement is that the list of commands (e.g. cmd/3) must be
> short and simple.

I usually do something along the following lines:

    % Enum type of all accepted commands.
    :- type cmd
        --->    cmd1
        ;       cmd2
        ...

    % Command names.
    :- pred cmd_name(cmd, string).
    :- mode cmd_name(in, out) is det.       % For printing the command.
    :- mode cmd_name(out, in) is semidet.   % For parsing the command.
    :- mode cmd_name(out, out) is multi.    % For generating help messages.

    cmd_name(cmd1, "cmd1").
    cmd_name(cmd2, "cmd2").
    ...

    % Command handlers.
    :- pred cmd_handler(cmd::in, list(string)::in, cmd_proc::out(cmd_proc))
        is semidet.

    cmd_handler(cmd1, [Arg],        handler1(Arg)).
    cmd_handler(cmd1, [Arg1, Arg2], handler1a(Arg1, Arg2)).
    cmd_handler(cmd2, [],           handler2).
    ...

    % Help messages.
    :- pred cmd_help(cmd::in, string::out) is det.

This perhaps isn't as short as you might like, but is very maintainable --
the detism ensures that help messages will always be added whenever a new
command is added, for example.  But maybe I'm telling you what you should
be doing instead of what you want, again.  ;-)

Hope this helps.

Cheers,
Mark.

--------------------------------------------------------------------------
mercury-users mailing list
Post messages to:       mercury-users at csse.unimelb.edu.au
Administrative Queries: owner-mercury-users at csse.unimelb.edu.au
Subscriptions:          mercury-users-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the users mailing list