From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-0.9 required=5.0 tests=BAYES_00,FORGED_GMAIL_RCVD, FREEMAIL_FROM autolearn=no autolearn_force=no version=3.4.4 X-Google-Thread: 103376,cfb2002511b830ab X-Google-NewGroupId: yes X-Google-Attributes: gida07f3367d7,domainid0,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Received: by 10.68.59.229 with SMTP id c5mr16397129pbr.6.1322331203205; Sat, 26 Nov 2011 10:13:23 -0800 (PST) Path: lh20ni21025pbb.0!nntp.google.com!news1.google.com!goblin3!goblin.stu.neva.ru!news-transit.tcx.org.uk!eternal-september.org!feeder.eternal-september.org!.POSTED!not-for-mail From: Natasha Kerensikova Newsgroups: comp.lang.ada Subject: Re: Starter project: getopt_long in Ada Date: Sat, 26 Nov 2011 18:13:22 +0000 (UTC) Organization: A noiseless patient Spider Message-ID: References: <4ecfc4c4$0$6579$9b4e6d93@newsspool3.arcor-online.net> Mime-Version: 1.0 Injection-Date: Sat, 26 Nov 2011 18:13:22 +0000 (UTC) Injection-Info: mx04.eternal-september.org; posting-host="Mda950WjNwNLAFOE7yJXQw"; logging-data="13542"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19ldeMApj1pJoY6jvh9Md0F" User-Agent: slrn/0.9.9p1 (FreeBSD) Cancel-Lock: sha1:0P+MLrQr0sMbnGj6zwmVv3tnnWk= Xref: news1.google.com comp.lang.ada:19178 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Date: 2011-11-26T18:13:22+00:00 List-Id: Hello, On 2011-11-25, Georg Bauhaus 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