• Algol 68 / Genie - event routine for reading from strings with'gets'?

    From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.misc on Tue Sep 2 06:20:34 2025
    From Newsgroup: comp.lang.misc

    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.
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Carlos H@pragus@centrum.cz to comp.lang.misc on Thu Sep 4 18:16:08 2025
    From Newsgroup: comp.lang.misc

    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
    Carlos.


    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.misc on Fri Sep 5 05:16:20 2025
    From Newsgroup: comp.lang.misc

    On 04.09.2025 18:16, Carlos H wrote:
    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 :)

    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: (
    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<---

    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.

    Janis

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Carlos H@pragus@centrum.cz to comp.lang.misc on Sat Sep 6 03:19:51 2025
    From Newsgroup: comp.lang.misc

    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'm using Algol 68 with the Genie specific extension 'gets', here
    to read real numbers from strings.
    [...]>> 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 :)

    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.

    The good thing is that all that transput implementation is available for strings as well (via 'associate').

    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.)

    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...



    HTH

    Thanks. It's good to have discussion partners to exchange experiences
    and opinions.

    Agree.

    C.

    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Janis Papanagnou@janis_papanagnou+ng@hotmail.com to comp.lang.misc on Sat Sep 6 07:00:32 2025
    From Newsgroup: comp.lang.misc

    On 06.09.2025 03:19, Carlos H wrote:
    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?

    It's just a simple way to allow - and skip - whitespace delimiters
    between the payload substrings; without polluting the result array's
    data or overload the function call interface making it unreadable.

    TRUE allows between the patterns whitespace that will be discarded.
    FALSE means a strict sequence of the matching patterns as provided.
    (Details here: http://algol68.gridbug.de/match.a68)


    ...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.

    Yes, that's true. But it would alleviate me from the re-definition
    of the clumsy UNION; there's so many types (and you would also gain
    from the the implicit coercion). Non-existing (unused) types in the
    CASE would run into a runtime-error, and (if it's no actual error)
    could then be extended or added only on demand.

    That's why I asked myself whether there's a hindrance or drawback
    if that general implicit UNION mode would have been made available
    for explicit use.


    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 ...

    Ah, right. I've seen it before but forgot about it. Thanks for the
    reminder.


    ...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...]

    Personally I have some dislike. But also the 'ANDTH' is not to my
    liking, to be honest. I'd have preferred 'AND THEN' or 'AND_THEN'
    and 'OR ELSE' or 'OR_ELSE' (as defined e.g. in the Eiffel language),
    and preferable as syntactical part of the control construct not as
    "pseudo operator" (or how it's been called). - But I think there's
    reasons why this Genie extension of Algol 68 had been defined the
    way it is.


    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.

    Yes.

    Although I seem to recall that there were Pascal dialects (or later
    standard extensions) where its _enumeration type literals_ could be
    literally written out and read in. (It was not supported in the
    original Pascal standard or the versions I used long ago, though.)
    So one could use directly the enumeration literals internally and
    externally (and don't need switching between numbers and strings).


    In comparison, reading strings and applying the transput routines (via 'associate') to [parts of] them, it's as simple as it gets.

    Right. (I was actually surprised how simple it was achievable in
    this language.)

    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...

    Thanks.

    Janis

    --- Synchronet 3.21a-Linux NewsLink 1.2