I'm using Algol 68 with the Genie specific extension 'gets', here
to read real numbers from strings.
I wanted to polish the data input interface to become more robust.
My program is reading in real values, either from the command line,
or from the keyboard, or both. Entering a non-real data string the
program aborted with an error message (i.e. in my initial version).
So I defined the event handler 'on value error' to catch that
on value error (stand in,
(REF FILE file) BOOL : ( fix_input (0.0); TRUE ) );
which works as advertised for the interactive keyboard input in the else-branch of this code fragment
REAL k;
IF argind <= argc THEN # input from command line #
STRING optarg := argv (argind);
argind PLUSAB 1;
gets (optarg, k);
printf (($ g(6) l $, k))
ELSE # interactive input #
read ((k, newline))
FI;
Is such an event handler solution possible for the _string input_ with
'gets' (in the then-branch), as well?
Currently the 'gets' function throws an error if non-real command line parameters are provided. (Note: for command line argument that's in my
case acceptable, but generally if would be nice to have a handler for
that input form as well.)[*]
Janis
BTW; I had mentioned in another thread that I find the event handler
handling peculiar and not smoothly integrating in the control flow.
Initially I wanted a "redo"-functionality but couldn't get a working solution. So I restricted it (as shown above) to just interpret wrong
input as "0.0" to at least prevent that annoying error message. :-/
[*] I think, implicitly the 'gets' relies on 'associate', but I'm not
sure whether that's actually a hindrance, or whether it opens some
possible solution; and, if at all, without undesired side-effects.
BTW; one of the changes I'd liked to have seen in Genie with 'gets'
is that it's not defined to require a REF STRING but instead accept
STRING items, to avoid the "unnecessary" hack with a LOC temporary.
On 02/09/2025 06:20, Janis Papanagnou wrote:
I'm using Algol 68 with the Genie specific extension 'gets', here
to read real numbers from strings.
I wanted to polish the data input interface to become more robust.
My program is reading in real values, either from the command line,
or from the keyboard, or both. Entering a non-real data string the
program aborted with an error message (i.e. in my initial version).
So I defined the event handler 'on value error' to catch that
on value error (stand in,
(REF FILE file) BOOL : ( fix_input (0.0); TRUE ) );
which works as advertised for the interactive keyboard input in the
else-branch of this code fragment
REAL k;
IF argind <= argc THEN # input from command line #
STRING optarg := argv (argind);
argind PLUSAB 1;
gets (optarg, k);
printf (($ g(6) l $, k))
ELSE # interactive input #
read ((k, newline))
FI;
Is such an event handler solution possible for the _string input_ with
'gets' (in the then-branch), as well?
Currently the 'gets' function throws an error if non-real command line
parameters are provided. (Note: for command line argument that's in my
case acceptable, but generally if would be nice to have a handler for
that input form as well.)[*]
Janis
BTW; I had mentioned in another thread that I find the event handler
handling peculiar and not smoothly integrating in the control flow.
Initially I wanted a "redo"-functionality but couldn't get a working
solution. So I restricted it (as shown above) to just interpret wrong
input as "0.0" to at least prevent that annoying error message. :-/
[*] I think, implicitly the 'gets' relies on 'associate', but I'm not
sure whether that's actually a hindrance, or whether it opens some
possible solution; and, if at all, without undesired side-effects.
BTW; one of the changes I'd liked to have seen in Genie with 'gets'
is that it's not defined to require a REF STRING but instead accept
STRING items, to avoid the "unnecessary" hack with a LOC temporary.
I'd write my own parsing function. If I'm going to use non-standard
routines, they'd better be mine and adapted to my needs :)
It could be something like
--8<---
PROC parse real = (STRING s, REF REAL r) BOOL: (
FILE f; associate(f, LOC STRING := s);
on value error (f, (REF FILE x) BOOL: (close(x); GOTO error));
get(f, r);
close(f);
TRUE EXIT
error: FALSE);
# test #
[]STRING numbers = ("1.0", "4.5e10", ".9", "what?", "-0", " +123.455");
FOR i TO UPB numbers DO
print(("""", numbers[i], """"));
IF REAL r; parse real(numbers[i], r) THEN
print((" -> ", r))
ELSE
print((" isn't a real number"))
FI;
print((new line))
OD
--8<---
...or multipurpose, using a UNION for the second argument.
Also, I'd
recommend to just read strings from the keyboard and then parse them,
instead of trying to read reals.
Input handling in Algol 68 is a pain in the ass.
HTH
On 04.09.2025 18:16, Carlos H wrote:[...]>> I'd write my own parsing function. If I'm going to use non-standard
On 02/09/2025 06:20, Janis Papanagnou wrote:
I'm using Algol 68 with the Genie specific extension 'gets', here
to read real numbers from strings.
routines, they'd better be mine and adapted to my needs :)
Well, yes, and I also thought about that. - I even thought about circumventing the whole I/O to build my own I/O parsing framework.
But, to be honest, it appeared to me to not be the "Right Thing"
to do to implement such functionality in context of a language
that provides a huge transput implementation. - My hope was that
I had just overlooked something existing. So thanks also for the
(implicit) confirmation in that respect.
[...]>It could be something like
--8<---
PROC parse real = (STRING s, REF REAL r) BOOL: (
And also thanks for the illustration with code samples.
I've also implemented (originally for another context) a 'match'
function that could also support me with parsing the components.
(With my code sample below it would support more flexibility;
match (line, ("[A-Z]", "[=~]", "[0-9]+(.[0-9]*)?"), TRUE)
for example, but then I'll need yet more supporting code to parse
the returned array of string values.)
...or multipurpose, using a UNION for the second argument.
This actually touches another "small question" I had asked myself;
in similar structural programming contexts I sometimes thought it
might be useful to have access to the two implicit UNION types of
the basic types that Algol 68 uses for example for read and write.
And I wondered why these (implicit) types are not usable in user's
programs.
Also, I'd
recommend to just read strings from the keyboard and then parse them,
instead of trying to read reals.
This is what I've actually also done in another context; but still
using the "standard" (or rather Genie-) methods in the inner parse
STRING line;
get (rc_in, (line, newline));
IF UPB line > 0 THEN
# nested IF to avoid annoying warning with Genie's ANDTH #
IF line[1] NE "#" THEN
CHAR var; BOOL op_blur; REAL val;
getsf (line, ($ a, b("~","="), g(0) $, var, op_blur, val));
...
But that's all not perfect, and to make it a sophisticated foolproof
code you need a lot more (and different) things to do! You understand
why I'm reluctant to (re-)implement such "parsing A68-inherent types" functions myself.
Input handling in Algol 68 is a pain in the ass.
Well, what shall I say. I certainly think that input is (for various
reasons) significantly more demanding [than output] - also in other languages.
HTH
Thanks. It's good to have discussion partners to exchange experiences
and opinions.
On 05/09/2025 05:16, Janis Papanagnou wrote:
On 04.09.2025 18:16, Carlos H wrote:
On 02/09/2025 06:20, Janis Papanagnou wrote:
I've also implemented (originally for another context) a 'match'
function that could also support me with parsing the components.
(With my code sample below it would support more flexibility;
match (line, ("[A-Z]", "[=~]", "[0-9]+(.[0-9]*)?"), TRUE)
for example, but then I'll need yet more supporting code to parse
the returned array of string values.)
That looks useful. What's the last argument (TRUE) for?
...or multipurpose, using a UNION for the second argument.
This actually touches another "small question" I had asked myself;
in similar structural programming contexts I sometimes thought it
might be useful to have access to the two implicit UNION types of
the basic types that Algol 68 uses for example for read and write.
And I wondered why these (implicit) types are not usable in user's
programs.
I don't know how useful they'd be. You'd still have to write the CASE statement to process the possible types those unions can hold. And since
they can hold any type, you'd only catch unimplemented cases at run
time. While if you write your union mode in tandem with your CASE, you'd catch unintended assignments at compile time.
Also, I'd
recommend to just read strings from the keyboard and then parse them,
instead of trying to read reals.
This is what I've actually also done in another context; but still
using the "standard" (or rather Genie-) methods in the inner parse
STRING line;
get (rc_in, (line, newline));
IF UPB line > 0 THEN
# nested IF to avoid annoying warning with Genie's ANDTH #
IF line[1] NE "#" THEN
[digression: I'm currently using this idiom for short-circuit AND:
IF (condition a | condition b | FALSE) THEN ...
...and this for short-circuit OR:
IF (condition a | TRUE | condition b) THEN ...
I'm still not sure if I like them or will get used to them...]
CHAR var; BOOL op_blur; REAL val;
getsf (line, ($ a, b("~","="), g(0) $, var, op_blur, val));
...
But that's all not perfect, and to make it a sophisticated foolproof
code you need a lot more (and different) things to do! You understand
why I'm reluctant to (re-)implement such "parsing A68-inherent types"
functions myself.
But you don't have to. Read on.
Input handling in Algol 68 is a pain in the ass.
Well, what shall I say. I certainly think that input is (for various
reasons) significantly more demanding [than output] - also in other
languages.
Yes. And it's frustrating, because it's so tantalizing (like, in what language can you read spelled-out numbers just like this:
INT n;
readf(($ c("one", "two", "three", "four", "five", "six", "seven",
"eight", "nine", "ten") l $, n));
), but the moment the input isn't what you expect you can only recover through convoluted and unmaintainable spaghetti code.
In comparison, reading strings and applying the transput routines (via 'associate') to [parts of] them, it's as simple as it gets.
Did the getf
fail? Just try the next format on the same string. While if you were
working directly on the file you'd have to reset the position, etc...
Sysop: | DaiTengu |
---|---|
Location: | Appleton, WI |
Users: | 1,070 |
Nodes: | 10 (0 / 10) |
Uptime: | 158:42:20 |
Calls: | 13,734 |
Calls today: | 2 |
Files: | 186,966 |
D/L today: |
808 files (292M bytes) |
Messages: | 2,418,677 |