Discussion:
Accessing The Command Line
(too old to reply)
Lawrence D'Oliveiro
2024-07-04 00:08:56 UTC
Permalink
with Ada.Command_Line;
with Ada.Text_IO;

procedure Echo is

package cli renames Ada.Command_Line;
package tio renames Ada.Text_IO;
package int_io is new tio.Integer_IO(Num => Integer);

begin
tio.put("my name: ");
tio.put(cli.Command_name);
tio.Put_Line("");
tio.Put("nr args: ");
int_io.Put(cli.Argument_Count, width => 1);
tio.Put_Line("");
for i in 1 .. cli.Argument_Count loop
tio.put("[");
int_io.put(i, width => 1);
tio.put("]: ");
tio.put(cli.argument(i));
tio.put_line("");
end loop;
end Echo;

----

Comments:

Ada, like Python, offers the convenience of being able to specify
local “nicknames” for imported packages, to save some typing.

Having become used to the convenience of printf-style formatting in C
and other languages that have adopted it (including Lisp and Python),
I don’t miss the tedium of having to format and output one item at a
time. Though I recognize that there is no way to do printf style in a
type-safe fashion, short of going to a fully-dynamic language.

Being able to access the POSIX command line via some globally-defined
entity instead of arguments to a “mainline” procedure is something
that just about every decent language offers. C is notably absent from
this list.
Paul Rubin
2024-07-04 01:16:01 UTC
Permalink
Post by Lawrence D'Oliveiro
Though I recognize that there is no way to do printf style in a
type-safe fashion, short of going to a fully-dynamic language.
C++ does that polymorphism stuff in iostream so you'd write
std::cout << "my name: " << command_line << ...

Haskell does something sort of similar with additional machinery.

printf for some people is one of the motivations for dependent types.
Lawrence D'Oliveiro
2024-07-04 01:50:59 UTC
Permalink
Post by Paul Rubin
C++ does that polymorphism stuff in iostream so you'd write
std::cout << "my name: " << command_line << ...
I know. The disadvantage of the C++ scheme is you cannot easily reorder
items as necessary to fit the grammar of localized messages. That, I
think, is why lots of other languages (including Python and Lisp) have
copied the printf scheme, yet none have seen fit to copy the C++ scheme.
Post by Paul Rubin
printf for some people is one of the motivations for dependent types.
I wonder how you would express such a thing in an Ada-friendly fashion?
Rod Kay
2024-07-04 15:13:36 UTC
Permalink
Post by Lawrence D'Oliveiro
I wonder how you would express such a thing in an Ada-friendly fashion?
There is the 'GNAT.Formatted_String' package, which provides
'printf' functionality.

Unfortunately, it's formatting is somewhat buggy and has been so for
many years. Usage is quite simple and reasonably elegant but the
occasional incorrect formatting is a major problem, essentially
rendering the package useless.

There is also the new 2022 f"X = {An_X_Variable}" notation for
embedding Variable'Image into strings, which is very nice. However, it
does not allow for formatting, so not useful for your needs. Just
thought I'd mention it, as it is now available in GCC 14.



Regards.
Dmitry A. Kazakov
2024-07-04 16:15:54 UTC
Permalink
Post by Lawrence D'Oliveiro
Post by Paul Rubin
printf for some people is one of the motivations for dependent types.
I wonder how you would express such a thing in an Ada-friendly fashion?
For example:

http://www.dmitry-kazakov.de/ada/strings_edit.htm
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Jeffrey R.Carter
2024-07-04 11:27:05 UTC
Permalink
Post by Lawrence D'Oliveiro
tio.put("my name: ");
tio.put(cli.Command_name);
tio.Put_Line("");
Tio.Put_Line (Item => "my name: " & Cli.Command_Name);

Image functions thus allow similar simplifications. 'Image is one such function,
Post by Lawrence D'Oliveiro
tio.Put("nr args: ");
int_io.Put(cli.Argument_Count, width => 1);
tio.Put_Line("");
Tio.Put_Line (Item => "nr args:" & Cli.Argument_Count'Image);

For simple cases you can roll your own:

function Image (Value : in Integer) return String is
Raw : constant String := Value'Image;
begin -- Image
return Raw ( (if Value < 0 then 1 else 2) .. Raw'Last);
end Image;
Post by Lawrence D'Oliveiro
tio.put("[");
int_io.put(i, width => 1);
tio.put("]: ");
tio.put(cli.argument(i));
tio.put_line("");
Tio.Put_Line (Item => '[' & Image (I) & "]: " & Image (Cli.Argument (I) ) );

For more complex uses, you can use something like PragmARC.Images[.Image]
(https://github.com/jrcarter/PragmARC).

You probably should review the definition of Ada.Text_IO
(http://www.ada-auth.org/standards/aarm12_w_tc1/html/AA-A-10.html), especially
for procedure New_Line.

--
Jeff Carter
"Write clearly--don't sacrifice clarity for 'efficiency.'"
Elements of Programming Style
186
Lawrence D'Oliveiro
2024-07-04 23:54:49 UTC
Permalink
Post by Jeffrey R.Carter
Post by Lawrence D'Oliveiro
tio.put("my name: ");
tio.put(cli.Command_name);
tio.Put_Line("");
Tio.Put_Line (Item => "my name: " & Cli.Command_Name);
I’m sure I can, but I’m not sure what the point is. Let Ada collect the
pieces in its own buffers. That saves copying steps.
Post by Jeffrey R.Carter
For more complex uses, you can use something like
PragmARC.Images[.Image] (https://github.com/jrcarter/PragmARC).
I don’t really feel the need to resort to third-party libraries just to do
simple I/O.
J-P. Rosen
2024-07-05 08:58:00 UTC
Permalink
Post by Lawrence D'Oliveiro
Post by Jeffrey R.Carter
Post by Lawrence D'Oliveiro
tio.put("my name: ");
tio.put(cli.Command_name);
tio.Put_Line("");
Tio.Put_Line (Item => "my name: " & Cli.Command_Name);
I’m sure I can, but I’m not sure what the point is. Let Ada collect the
pieces in its own buffers. That saves copying steps.
Agreed. I don't understand why people dislike printing piece by piece.
In the old FORTRAN, you could write only line by line, but this time is
long gone...
With the various Put procedures, you have individual formatting options
that you don't have otherwise. Moreover, there is a nice property that
few people noticed: if you have an algorithm writing data to a file,
with loops and so on, you can keep the exact same structure replacing
every Put with the matching Get, and you will read your data correctly.
This feature goes away as soon as you have a 'Image.
--
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
https://www.adalog.fr https://www.adacontrol.fr
Dmitry A. Kazakov
2024-07-04 13:01:05 UTC
Permalink
Post by Lawrence D'Oliveiro
with Ada.Command_Line;
with Ada.Text_IO;
[...]

A general advice processing strings, any strings: messages, commands,
payload etc.

Always read a complete string into a fixed size buffer (safety). Never
use streams. Process the whole string consequently. Never tokenize.
Never copy anything. Ada has slices.

The same is true for the output. Build a complete substring in a buffer.
Consequently. Flush the complete substring to the output.

Do not use Unbounded_String.
--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
Ben Bacarisse
2024-07-04 19:42:00 UTC
Permalink
... Though I recognize that there is no way to do printf style in a
type-safe fashion, short of going to a fully-dynamic language.
No so. Haskell has Text.Printf.
--
Ben.
Paul Rubin
2024-07-04 22:06:00 UTC
Permalink
Post by Ben Bacarisse
... Though I recognize that there is no way to do printf style in a
type-safe fashion, short of going to a fully-dynamic language.
No so. Haskell has Text.Printf.
Text.Printf is not fully type safe. printf "%d\n" "foo"
throws an "bad formatting character" exception, really amounting to
a runtime type exception.
Loading...