caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: "Daniel Bünzli" <daniel.buenzli@erratique.ch>
To: Gabriel Scherer <gabriel.scherer@gmail.com>
Cc: caml-list@inria.fr
Subject: Re: [Caml-list] [ANN] Cmdliner 0.9.0
Date: Sat, 28 May 2011 18:02:16 +0200	[thread overview]
Message-ID: <BANLkTi=d0W-ZN+ZP3GbNSYFO=MaKZEs3HQ@mail.gmail.com> (raw)
In-Reply-To: <BANLkTim_o0N6rcowCz50D9cxn6Pfj5N3-Q@mail.gmail.com>

Thanks for the long email.

> - I'm not sure the presentation "oh it's just an applicative functor" is the
> most accessible to the wider OCaml community. That said, your examples do a
> rather good job at explaining how it's used, so maybe the scary words
> upfront are not so much of a problem.

As you saw, no knowledge of this is needed. Maybe you are right that
this info doesn't belong here but OTOH I may help programmers who know
what it means. It was also an opportunity to link to an interesting
paper.

> - I wasn't able to understand why you specifically chose an applicative
> functor.

Me neither. I realized after thought that this was an applicative
functor. Although I can now hint why I turned that way (see below).

> Intuitively I would see this rather as a Reader (or Env) monad over
> the (parsed, typed) "parameter state" of the program.

I didn't want to see this interaction as reading from an environment.
I wanted to see that as follows.

When I invoke a command on the command line I invoke a function and
the command line arguments are the arguments to the function. In my
function I don't want to work with special types representing command
line arguments, if my function needs an int then it should be a
regular int, not something from which I can extract an int.

So the idea was that to turn the problem inside-out. Instead of
working with special types representing command line arguments, lift
your bare function in an applicative functor that handles and hides
the extraction of OCaml values from the command line arguments.

> Given that monads are
> more popular and widely used, and that the monadic interface is richer than
> the applicative functor one, I'm wondering why you made that choice. It
> would be ok if this is not a monad (I think only structures that are
> explicitely *not* monads should be presented as applicative functors), but I
> don't see why your type isn't. Maybe this should be documented.

First I always try to work with the weakest assumptions and
applicative was enough. Second monad is just applicative + bind and I
don't see for what you would like bind here. In cmdliner terms are
just a way to hide the command line parsing machinery to our function
that need regular OCaml values. It turns out that this is exactly
Applicative's domain, embed pure computations in an effectful world
(the parsing machinery).

> - Term.eval_choice use a (info * 'a) associative list, while varg_* use ('a
> * info) lists. I'm not sure why you made different choices.

Not sure either. Can't remember. Maybe because of the order of
arguments in Term.eval.

> Actually I don't understand what "vflag" is.

It's a single value that can be defined by different flags. Maybe have
a look at the rm example.

http://erratique.ch/software/cmdliner/doc/Cmdliner.html#examples

It uses vflag_all which is like vflag except that the flags are
allowed to repeat.

> - I think the "predefined converters" are mostly orthogonal to the rest of
> the interface, and would possibly benefit of being factored out as a
> separate module, or even an external "extra" library; they should certainly
> be in any reasonable "extra standard library" (Extlib, Core, Batteries,
> whichever you like) and you could/should propose them upstream to those
> libraries if they are not.

I think it would defeat the "quick and easy" way intended by the
library. Besides having them in the Arg module allows more concise
definitions if you program in OCaml 3.12, e.g. :

let count = Arg.(value & opt int 10 & info ["c"; "count"] ~docv:"COUNT" ~doc)

> - The converter interface seems a bit simplistic and unsatisfying. In
> particular, parsers being (string -> 'a) functions,

The converter interface is certainly simplistic but I didn't find it
unsatisfying in practice. Take that as a stance to keep your command
line interfaces simple and reasonable.

> compose different parsers. I just had a look at the implementation and, for
> pairs for example, if I understand correctly you split the input string on
> "," beforehand, then call the parser on both parts.

Yes. Note that you don't have to look at the implementation. You can
just read the documentation :

http://erratique.ch/software/cmdliner/doc/Cmdliner.Arg.html#VALpair

> This seems wrong:
>   - there seems to be an associativity issue, if I build (pair (pair int
> int) int) and pass "1,2,3", it will try to parse "1" with (pair int int); so
> we would need delimiters here
>   - what if I pass a quoted string that contains a comma?

Implement a better parser... Given the generality of the parser
interface you are allowed to invoke whatever parsing technology suits
you.

> - Your build system (handcoded make-like script) is a bit unusual. Maybe it
> be better for the principle-of-least-surprise if you had a Makefile just
> redirecting the obvious actions to your funny build script. I first tried
> (yes, I should read the README first) to run "oasis", but this failed as the
> _oasis file is syntactically invalid due to the %%FOO%% configuration
> variables. I'm unsure what is the benefit of having those configuration
> variables in your build script rather than in the _oasis, but I understand
> this is a highly subjective thing.

I do proper software releases (yes I'm old fashioned I don't just push
a repo on github). If you see the %%FOO%% variables it means that you
are trying to use the repository version and you shouldn't; use the
tarballs. These variables are here so that I don't have to repeat
myself.

That said the _oasis file in the distribution 0.9.0 has a syntax
error. If you download from oasis-db you will get one without the
syntax error (I know that you should not publish two tar balls
pretending to be the same thing that differ in content, I permitted
myself this misstep because the current ocaml-db is "experimental" and
will be destroyed).

Regarding the "funny" build script, it may eventually disappear if I
finally get serious about using oasis.

> On a more open-ended side, I wanted to report that I have done a related
> thing for a prototype, with a slightly different twist: I needed a
> description of configuration options that would support both a command-line
> interface (for which I reused the Arg module), and configuration directives
> in an interactive toplevel: "#set +debug;;". I don't suppose you would or
> should be interested in extending your interface to support such a thing,
> but this is food for thought anyway.

Without thinking too much about it I don't think it would *need* to be extended.

> Finally, I had a different approach wrt. option/commands spelling. If I
> understand correctly, you accept an input if and only if it is a valid
> prefix of only one valid option/command.

Yes.

> It may still be useful to suggest the correct option when rejecting the spelling, à la git "Did you mean this ?".

That could be nice. But I have to admit, I spent far too much time on
solving (for me) the mundane problem of command line argument parsing
so don't expect that anytime soon. Well written patches are, however,
welcome.

Best,

Daniel


      reply	other threads:[~2011-05-28 16:02 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-05-27 14:54 Daniel Bünzli
2011-05-27 16:35 ` Gabriel Scherer
2011-05-28 16:02   ` Daniel Bünzli [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='BANLkTi=d0W-ZN+ZP3GbNSYFO=MaKZEs3HQ@mail.gmail.com' \
    --to=daniel.buenzli@erratique.ch \
    --cc=caml-list@inria.fr \
    --cc=gabriel.scherer@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).