comp.lang.ada
 help / color / mirror / Atom feed
From: Natasha Kerensikova <lithiumcat@gmail.com>
Subject: Re: Starter project: getopt_long in Ada
Date: Sat, 26 Nov 2011 18:13:22 +0000 (UTC)
Date: 2011-11-26T18:13:22+00:00	[thread overview]
Message-ID: <slrnjd2b1q.vl6.lithiumcat@sigil.instinctive.eu> (raw)
In-Reply-To: 4ecfc4c4$0$6579$9b4e6d93@newsspool3.arcor-online.net

Hello,

On 2011-11-25, Georg Bauhaus <rm.dash-bauhaus@futureapps.de> wrote:
> I'd prefer these handlers to be "linguistically" collected in
> one place (and a different sets of handlers collected in
> different places, respectively).

I completely agree that the error handler are indeed connected. I'm
still genuinely wondering whether they should be grouped with the
argument callback like you suggest or not.

> In order to achieve this,
> an abstract type can state the list of handling procedures,
> with null defaults for operations the programmer does not
> wish to do anything special.

You seem to be missing one important point about these handlers,
probably because it's not documented well enough: the error callbacks
are currently defaulting to null, but that null does not mean nothing is
performed when such an error is encountered (i.e. a null procedure), it
means that an Option_Error exception is raised.

In most use cases I can imagine, an application encountering an error in
argument parsing will just print a "usage" text and exit with an error
code, that can be done simply by catching Natools.Getopt_Long.Option_Error
exception.

However some tools not only print the generic "usage" text, they also
print what was wrong in the given arguments. Some tools even do so in a
runtime-selected language (e.g. locale facilities), which prevents using
blindly the exception message. That's how I came up with the callbacks,
which allows to communicate what went wrong (and then the ability to
recover from such errors was a happy side-effect I decided to keep; but
I have never encountered any command-line tool that does recover from
command-line argument errors).

That's why I'm wondering (and implicitly asking your opinion) whether
the "normal" callback should be bundled with the error handling
callbacks.

All applications will have to provide a useful callback for argument
processing, even when they don't do any error handling beyond printing
"usage" text and aborting. So maybe it would make sense to keep the
access-to-procedure Callback argument, and create an
Option_Error_Handler class, whose default value in Process would be
something that just raises Option_Error (which would by the way make
Process body cleaner by not having to check null access).

On the other hand, I could also go for an Option_Handler abstract class,
with abstract regular Callback and with overrideable implementations for
error handlers that raise Option_Error.

> Defining this type has the
> advantages that it makes programmers write software organized
> into typed structure, yielding
>
> 1) definite places to look for the handling procedures
> 2) handlers that can share common data for communicating
>    parsing state among them
> 3) human readers that know about 1 and 2 because they can
>    look for concrete types derived from the abstract type.

While I certainly agree with this in general, in this particular case
I'm skeptical about (2), since I can't think of any example where error
handlers are not fatal, which leaves only one handler that only has to
communicate with itself.

The error handlers are really only a workaround to have in effect
exceptions with structured arguments.

> I think the advantages outweigh a minor loss in flexibility,
> if you'd want to call flexibility the ability to pass a
> collection of subprograms each declared just anywhere.

Yes, I'm completely sold on the idea of using a dispatching call instead
of error handler accesses. And still unsure about the normal handler.

> Influencing the shape of this type, Process's parameters
> such as Posixly_Correct might mean that the handling
> procedures may want to determine whether or not Posixly_Correct
> is true.

I think it depends on who is supposed to set these parameters. For
example Long_Only should not be changed while Process is running, so I
don't like it being a record component or the result of a function.
Having it a type discriminant like you suggest feels like an abuse of
the type discriminant feature, but I cannot manage to tell why (and I
might be wrong, considering I'm still too new to have accurate
feelings).

Posixly_Correct could be changed on-the-fly (even though in the C code I
took inspiration from it was a compile-time option), even though I don't
see any reason to do so (a meta-flag?).

I will give it some deeper thought.

> So, then, my first idea will be along these lines:
>
> package Natools.Handlers is
>
>     type Id_And_Argument_Handler
>        (Posixly_Correct :  Boolean;
>         ...)
>     is abstract tagged private;
>
>     procedure Callback
>         (Handler : in out Id_And_Argument_Handler;
>          Id : Option_Id;
>          Argument : String) is abstract;
>
>     procedure Missing_Argument
>         (Handler : in out Id_And_Argument_Handler;
>          Id : Option_Id) is null;
>
>     etc.
>
> end Natools.Handlers;

I'm afraid it will not work, since Option_Id is a formal type from
generic package Natools.Getopt_Long.

However, is there anything wrong with having something like the
following?

generic
   type Option_Id is (<>);
package Natools.Getopt_Long is
   Option_Error : exception;
   package Handlers is
      type Argument_Handler is abstract tagged null record;
      procedure Missing_Argument
        (Handler : in out Argument_Handler;
         Id      : Option_Id);   --  implementation raises Option_Error;
      --  others handlers, maybe including regular argument callback
   end Handlers;
   procedure Process ( -- arguments to be written later
end Natools.Getopt_Long;

Or is the inner package looking for trouble?

> I did not look at the implementation.

I'm sure there are very useful lessons for me to draw from the
implementation. Still I'm very grateful for your comments on the
specification, I think that's the best way for me to make progress at
this point.


Thanks a lot for your help,
Natasha



  reply	other threads:[~2011-11-26 18:13 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-11-25 10:47 Starter project: getopt_long in Ada Natasha Kerensikova
2011-11-25 16:39 ` Georg Bauhaus
2011-11-26 18:13   ` Natasha Kerensikova [this message]
2011-11-26 20:47     ` Jeffrey Carter
2011-11-28 15:49     ` Georg Bauhaus
2011-11-28 17:18       ` Natasha Kerensikova
2011-11-27  8:21   ` Yannick Duchêne (Hibou57)
2011-11-27 12:30     ` Natasha Kerensikova
2011-11-27 15:11       ` Yannick Duchêne (Hibou57)
2011-11-28  8:21         ` Natasha Kerensikova
2011-11-28 13:02           ` Yannick Duchêne (Hibou57)
2011-11-27  8:05 ` Yannick Duchêne (Hibou57)
2011-11-27 12:39   ` Natasha Kerensikova
2011-11-27 14:52     ` Yannick Duchêne (Hibou57)
2011-11-27  8:09 ` Yannick Duchêne (Hibou57)
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox