• BASIC (and Horizon)

    From Simon Clubley@21:1/5 to Dave Froble on Mon Jan 29 18:27:36 2024
    On 2024-01-29, Dave Froble <davef@tsoft-inc.com> wrote:
    On 1/29/2024 8:24 AM, Simon Clubley wrote:

    $ set response/mode=good_natured

    Don't be too hard on David, Dan. He still likes to use line numbers
    in his BASIC code... :-)


    That is a filthy slander ...

    Line numbers can be used in place of labels for GoTo statements, which you'll also probably also slander. But they can be useful. Other than that, line numbers can be useful for appending boiler plate code to a program. Line numbers are used in handling error exceptions and handling.

    Your implication that I use numbers on every line is just false.


    $ set response/mode=good_natured

    Er, David, where do I say _every_ line ? Or is that a guilty conscience
    that's reading something above which isn't there ? :-)

    It was a reference to the last time you posted a bit of BASIC code and
    it was pointed out it could be written much more cleanly using structured control loops.

    Someone (Arne IIRC) posted some BASIC code using structured control
    loops and I don't remember you being too impressed by the different
    coding style, even though to me, Arne's version looked a lot cleaner.

    If I'm going to have:

    On Error GoTo 32000

    Ahhh, what's the use, you're probably just laughing ...


    $ set response/mode=angry

    On the plus side, and to take the opportunity to vent my anger at something that I get more angry about whenever more details are revealed, at least
    you know how to reverse the sign of a variable without having to write a function to do it. :-( :-(

    See:

    https://news.ycombinator.com/item?id=38926582

    Original reference:

    https://www.postofficehorizoninquiry.org.uk/evidence/fuj00080690-report-eposs-pinicl-task-force

    See page 17 onwards of the PDF. :-(

    Innocent people went to jail because of the system this code is
    a part of, and because of the coverup around it, and it took
    a TV drama to really get things moving. :-(

    So, yes, I may make fun of your line numbers, but at least you most
    certainly know what you are doing, unlike the above people.

    Simon.

    --
    Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
    Walking destinations on a map are further away than they appear.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Simon Clubley on Mon Jan 29 19:06:18 2024
    On 1/29/2024 1:27 PM, Simon Clubley wrote:
    On the plus side, and to take the opportunity to vent my anger at something that I get more angry about whenever more details are revealed, at least
    you know how to reverse the sign of a variable without having to write a function to do it. :-( :-(

    See:

    https://news.ycombinator.com/item?id=38926582

    Original reference:

    https://www.postofficehorizoninquiry.org.uk/evidence/fuj00080690-report-eposs-pinicl-task-force

    See page 17 onwards of the PDF. :-(

    Innocent people went to jail because of the system this code is
    a part of, and because of the coverup around it, and it took
    a TV drama to really get things moving. :-(

    So, yes, I may make fun of your line numbers, but at least you most
    certainly know what you are doing, unlike the above people.

    The code is VB6.

    But none of the problems are Basic specific. It is possible
    to write the same bad code in C or Fortran or whatever.

    So it just shows that there are some really really bad programmers out
    there.

    Arne

    PS: Good compilers may have detected the unreachable code. But it
    is still good vs bad compiler not good vs bad language.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to kludge@panix.com on Mon Jan 29 20:02:35 2024
    On 1/29/2024 7:50 PM, kludge@panix.com wrote:
    =?UTF-8?Q?Arne_Vajh=C3=B8j?= <arne@vajhoej.dk> wrote:
    The code is VB6.

    But none of the problems are Basic specific. It is possible
    to write the same bad code in C or Fortran or whatever.

    So it just shows that there are some really really bad programmers out
    there.

    I have worked with people who could write spaghetti Fortran in any programming language available.

    "A real Fortran programmer can write Fortran in any language"

    Every time this comes up I post this Fortran/Pascal code:

    PROGRAM GOTOFUN(INPUT,OUTPUT);
    LABEL L731,L113,L247,L588,L761,L922,L399,L601;
    VAR LBL:INTEGER;
    VAR I:INTEGER;
    BEGIN
    L731: GOTO L113;
    LBL:=399;
    L113: I:=0;
    WRITELN(I);
    L247: LBL:=601;
    IF(I<0)THEN GOTO L588 ELSE IF(I=0)THEN GOTO L922 ELSE GOTO L399;
    L588: I:=I+1;
    WRITELN(I);
    GOTO L399;
    L761: CASE(LBL)OF 399: GOTO L399; 601: GOTO L601; END;
    L922: I:=I+1;
    WRITELN(I);
    CASE(I)OF 1: GOTO L588; 2: GOTO L399; 3: GOTO L922; END;
    L399: GOTO L761;
    L601: END.

    :-)

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From kludge@panix.com@21:1/5 to arne@vajhoej.dk on Tue Jan 30 00:50:47 2024
    =?UTF-8?Q?Arne_Vajh=C3=B8j?= <arne@vajhoej.dk> wrote:
    The code is VB6.

    But none of the problems are Basic specific. It is possible
    to write the same bad code in C or Fortran or whatever.

    So it just shows that there are some really really bad programmers out
    there.

    I have worked with people who could write spaghetti Fortran in any
    programming language available. Did you know that LISP has a goto?
    It does.

    PS: Good compilers may have detected the unreachable code. But it
    is still good vs bad compiler not good vs bad language.

    The exciting part is when they tell you not to remove the unreachable code, because the program crashes at runtime when you do that.
    --scott

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to kludge on Tue Jan 30 00:55:00 2024
    On 30 Jan 2024 00:50:47 -0000, kludge wrote:

    Did you know that LISP has a goto?

    Scheme doesn’t. It has continuations, which are a cool thing that can be
    used to implement control structures, exceptions and coroutines, yet make
    it quite difficult to express arbitrary gotos. Win-win, really.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to All on Tue Jan 30 02:06:06 2024
    On 1/29/2024 8:02 PM, Arne Vajhøj wrote:
    On 1/29/2024 7:50 PM, kludge@panix.com wrote:
    =?UTF-8?Q?Arne_Vajh=C3=B8j?= <arne@vajhoej.dk> wrote:
    The code is VB6.

    But none of the problems are Basic specific. It is possible
    to write the same bad code in C or Fortran or whatever.

    So it just shows that there are some really really bad programmers out
    there.

    I have worked with people who could write spaghetti Fortran in any
    programming language available.

    "A real Fortran programmer can write Fortran in any language"

    Every time this comes up I post this Fortran/Pascal code:

    PROGRAM GOTOFUN(INPUT,OUTPUT);
    LABEL L731,L113,L247,L588,L761,L922,L399,L601;
    VAR LBL:INTEGER;
    VAR I:INTEGER;
    BEGIN
    L731: GOTO L113;
    LBL:=399;
    L113: I:=0;
    WRITELN(I);
    L247: LBL:=601;
    IF(I<0)THEN GOTO L588 ELSE IF(I=0)THEN GOTO L922 ELSE GOTO L399;
    L588: I:=I+1;
    WRITELN(I);
    GOTO L399;
    L761: CASE(LBL)OF 399: GOTO L399; 601: GOTO L601; END;
    L922: I:=I+1;
    WRITELN(I);
    CASE(I)OF 1: GOTO L588; 2: GOTO L399; 3: GOTO L922; END;
    L399: GOTO L761;
    L601: END.

    :-)

    Arne


    I'm amused every time the GoTo bashing begins.

    Not only is there nothing wrong when using a branch operation, when appropriate,
    just look at the assembler listings after compilation. Branching is just about all assembler does, as required.

    Now, I won't defend what I and most consider improper use of the poor misunderstood GoTo statement.


    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Townley@21:1/5 to Dave Froble on Tue Jan 30 14:40:34 2024
    On 30/01/2024 07:06, Dave Froble wrote:
    On 1/29/2024 8:02 PM, Arne Vajhøj wrote:
    On 1/29/2024 7:50 PM, kludge@panix.com wrote:
    =?UTF-8?Q?Arne_Vajh=C3=B8j?=  <arne@vajhoej.dk> wrote:
    The code is VB6.

    But none of the problems are Basic specific. It is possible
    to write the same bad code in C or Fortran or whatever.

    So it just shows that there are some really really bad programmers out >>>> there.

    I have worked with people who could write spaghetti Fortran in any
    programming language available.

    "A real Fortran programmer can write Fortran in any language"

    Every time this comes up I post this Fortran/Pascal code:

          PROGRAM GOTOFUN(INPUT,OUTPUT);
          LABEL L731,L113,L247,L588,L761,L922,L399,L601;
          VAR LBL:INTEGER;
          VAR I:INTEGER;
          BEGIN
    L731: GOTO L113;
          LBL:=399;
    L113: I:=0;
          WRITELN(I);
    L247: LBL:=601;
          IF(I<0)THEN GOTO L588 ELSE IF(I=0)THEN GOTO L922 ELSE GOTO L399; >> L588: I:=I+1;
          WRITELN(I);
          GOTO L399;
    L761: CASE(LBL)OF 399: GOTO L399; 601: GOTO L601; END;
    L922: I:=I+1;
          WRITELN(I);
          CASE(I)OF 1: GOTO L588; 2: GOTO L399; 3: GOTO L922; END;
    L399: GOTO L761;
    L601: END.

    :-)

    Arne


    I'm amused every time the GoTo bashing begins.

    Not only is there nothing wrong when using a branch operation, when appropriate, just look at the assembler listings after compilation.
    Branching is just about all assembler does, as required.

    Now, I won't defend what I and most consider improper use of the poor misunderstood GoTo statement.


    But unless used very carefully, it can create horrible spaghetti like
    code, and is also easy to screw up.

    Using proper structured constructs is much better - easier to read as
    well, hence better maintainability.


    --
    Chris

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Townley@21:1/5 to bill on Tue Jan 30 17:14:21 2024
    On 30/01/2024 16:45, bill wrote:
    On 1/29/2024 7:50 PM, kludge@panix.com wrote:
    =?UTF-8?Q?Arne_Vajh=C3=B8j?=  <arne@vajhoej.dk> wrote:
    The code is VB6.

    But none of the problems are Basic specific. It is possible
    to write the same bad code in C or Fortran or whatever.

    So it just shows that there are some really really bad programmers out
    there.

    I have worked with people who could write spaghetti Fortran in any
    programming language available.  Did you know that LISP has a goto?
    It does.

    PS: Good compilers may have detected the unreachable code. But it
         is still good vs bad compiler not good vs bad language.

    The exciting part is when they tell you not to remove the unreachable
    code,
    because the program crashes at runtime when you do that.

    Many moons ago I had to try to fix a number of programs that
    crashed whenever run.  Back in those days a common method was
    to add statements to display variables during execution.  I
    had many cases where adding those statements made the program
    work.

    bill

    Could it have been the variables were being incorrectly being optimised
    out, but adding a print statement would avoid that. I have seen that a
    few times

    --
    Chris

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dave Froble on Tue Jan 30 18:54:17 2024
    On 1/30/2024 2:06 AM, Dave Froble wrote:
    On 1/29/2024 8:02 PM, Arne Vajhøj wrote:
    On 1/29/2024 7:50 PM, kludge@panix.com wrote:
    I have worked with people who could write spaghetti Fortran in any
    programming language available.

    "A real Fortran programmer can write Fortran in any language"

    Every time this comes up I post this Fortran/Pascal code:

          PROGRAM GOTOFUN(INPUT,OUTPUT);

    I'm amused every time the GoTo bashing begins.

    Not only is there nothing wrong when using a branch operation, when appropriate, just look at the assembler listings after compilation.
    Branching is just about all assembler does, as required.

    Now, I won't defend what I and most consider improper use of the poor misunderstood GoTo statement.

    The IT world 50-60 years ago had a GoTo problem.

    The lack of structured constructs in assembler, Fortran 66,
    original Dartmouth Basic etc. had resulted in a lot of
    spaghetti code.

    And as a result GoTo got a very bad reputation.

    The IT world today does not have a GoTo problem.

    Many languages does not support GoTo, but even in the languages
    that do support GoTo it is typical not a common construct.

    There are actual cases where GoTo (goto in case sensitive languages)
    can result in more readable code than the structured approach.

    In languages without exception support then a goto down to
    cleanup code can be very readable.

    In languages without labeled break then a goto out of an
    inner loop can be very readable.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Dorsey@21:1/5 to bill.gunshannon@gmail.com on Wed Jan 31 00:16:09 2024
    bill <bill.gunshannon@gmail.com> wrote:
    Many moons ago I had to try to fix a number of programs that
    crashed whenever run. Back in those days a common method was
    to add statements to display variables during execution. I
    had many cases where adding those statements made the program
    work.

    Yes, this is a sign of a fandango on core. In Fortran it is
    likely exceeding array bounds or bad parameter passing, but in
    C the possibilities to screw up with pointers are endless.
    --scott
    --
    "C'est un Nagra. C'est suisse, et tres, tres precis."

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to Chris Townley on Tue Jan 30 23:28:53 2024
    On 1/30/2024 9:40 AM, Chris Townley wrote:
    On 30/01/2024 07:06, Dave Froble wrote:
    On 1/29/2024 8:02 PM, Arne Vajhøj wrote:
    On 1/29/2024 7:50 PM, kludge@panix.com wrote:
    =?UTF-8?Q?Arne_Vajh=C3=B8j?= <arne@vajhoej.dk> wrote:
    The code is VB6.

    But none of the problems are Basic specific. It is possible
    to write the same bad code in C or Fortran or whatever.

    So it just shows that there are some really really bad programmers out >>>>> there.

    I have worked with people who could write spaghetti Fortran in any
    programming language available.

    "A real Fortran programmer can write Fortran in any language"

    Every time this comes up I post this Fortran/Pascal code:

    PROGRAM GOTOFUN(INPUT,OUTPUT);
    LABEL L731,L113,L247,L588,L761,L922,L399,L601;
    VAR LBL:INTEGER;
    VAR I:INTEGER;
    BEGIN
    L731: GOTO L113;
    LBL:=399;
    L113: I:=0;
    WRITELN(I);
    L247: LBL:=601;
    IF(I<0)THEN GOTO L588 ELSE IF(I=0)THEN GOTO L922 ELSE GOTO L399;
    L588: I:=I+1;
    WRITELN(I);
    GOTO L399;
    L761: CASE(LBL)OF 399: GOTO L399; 601: GOTO L601; END;
    L922: I:=I+1;
    WRITELN(I);
    CASE(I)OF 1: GOTO L588; 2: GOTO L399; 3: GOTO L922; END;
    L399: GOTO L761;
    L601: END.

    :-)

    Arne


    I'm amused every time the GoTo bashing begins.

    Not only is there nothing wrong when using a branch operation, when
    appropriate, just look at the assembler listings after compilation. Branching
    is just about all assembler does, as required.

    Now, I won't defend what I and most consider improper use of the poor
    misunderstood GoTo statement.


    But unless used very carefully, it can create horrible spaghetti like code, and
    is also easy to screw up.

    Using proper structured constructs is much better - easier to read as well, hence better maintainability.



    Prey tell, what structured construct will perform cleanup and exit? I always expected a return from routines and such.

    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bob Eager@21:1/5 to bill on Wed Jan 31 09:54:15 2024
    On Tue, 30 Jan 2024 20:21:43 -0500, bill wrote:

    On 1/30/2024 7:16 PM, Scott Dorsey wrote:
    bill <bill.gunshannon@gmail.com> wrote:
    Many moons ago I had to try to fix a number of programs that crashed
    whenever run. Back in those days a common method was to add
    statements to display variables during execution. I had many cases
    where adding those statements made the program work.

    Yes, this is a sign of a fandango on core. In Fortran it is likely
    exceeding array bounds or bad parameter passing, but in C the
    possibilities to screw up with pointers are endless.

    Bingo!!!

    It was mostly Fortran but every once in a while some idiot would do it
    in COBOL, too.

    We had a machine that ran FORTRAN for the physics department. One guy had
    a program that crashed the machine. As in, the microcode halted. That was
    an array bounds error.

    Full story:

    http://www.bobeager.uk/anecdotes.html#hwhack

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Townley@21:1/5 to Dave Froble on Wed Jan 31 12:03:51 2024
    On 31/01/2024 04:28, Dave Froble wrote:
    On 1/30/2024 9:40 AM, Chris Townley wrote:
    On 30/01/2024 07:06, Dave Froble wrote:
    On 1/29/2024 8:02 PM, Arne Vajhøj wrote:
    On 1/29/2024 7:50 PM, kludge@panix.com wrote:
    =?UTF-8?Q?Arne_Vajh=C3=B8j?=  <arne@vajhoej.dk> wrote:
    The code is VB6.

    But none of the problems are Basic specific. It is possible
    to write the same bad code in C or Fortran or whatever.

    So it just shows that there are some really really bad programmers >>>>>> out
    there.

    I have worked with people who could write spaghetti Fortran in any
    programming language available.

    "A real Fortran programmer can write Fortran in any language"

    Every time this comes up I post this Fortran/Pascal code:

          PROGRAM GOTOFUN(INPUT,OUTPUT);
          LABEL L731,L113,L247,L588,L761,L922,L399,L601;
          VAR LBL:INTEGER;
          VAR I:INTEGER;
          BEGIN
    L731: GOTO L113;
          LBL:=399;
    L113: I:=0;
          WRITELN(I);
    L247: LBL:=601;
          IF(I<0)THEN GOTO L588 ELSE IF(I=0)THEN GOTO L922 ELSE GOTO L399;
    L588: I:=I+1;
          WRITELN(I);
          GOTO L399;
    L761: CASE(LBL)OF 399: GOTO L399; 601: GOTO L601; END;
    L922: I:=I+1;
          WRITELN(I);
          CASE(I)OF 1: GOTO L588; 2: GOTO L399; 3: GOTO L922; END;
    L399: GOTO L761;
    L601: END.

    :-)

    Arne


    I'm amused every time the GoTo bashing begins.

    Not only is there nothing wrong when using a branch operation, when
    appropriate, just look at the assembler listings after compilation.
    Branching
    is just about all assembler does, as required.

    Now, I won't defend what I and most consider improper use of the poor
    misunderstood GoTo statement.


    But unless used very carefully, it can create horrible spaghetti like
    code, and
    is also easy to screw up.

    Using proper structured constructs is much better - easier to read as
    well,
    hence better maintainability.



    Prey tell, what structured construct will perform cleanup and exit?  I always expected a return from routines and such.


    It would depend on what is needing to be done

    --
    Chris

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Dave Froble on Wed Jan 31 15:52:30 2024
    On Tue, 30 Jan 2024 23:28:53 -0500
    Dave Froble <davef@tsoft-inc.com> wrote:


    Prey tell, what structured construct will perform cleanup and exit?
    I always expected a return from routines and such.


    One option is named construct and named break.
    Example below is from Go (golang) tutorial. Ada has something very
    similar.

    Loop:
    for n := 0; n < len(src); n += size {
    switch {
    case src[n] < sizeOne:
    if validateOnly {
    break
    }
    size = 1
    update(src[n])

    case src[n] < sizeTwo:
    if n+1 >= len(src) {
    err = errShortInput
    break Loop
    }
    if validateOnly {
    break
    }
    size = 2
    update(src[n] + src[n+1]<<shift)
    }
    }


    Another option is defer clause.
    From the same tutorial:

    // Contents returns the file's contents as a string.
    func Contents(filename string) (string, error) {
    f, err := os.Open(filename)
    if err != nil {
    return "", err
    }
    defer f.Close() // f.Close will run when we're finished.

    var result []byte
    buf := make([]byte, 100)
    for {
    n, err := f.Read(buf[0:])
    result = append(result, buf[0:n]...) // append is discussed
    later. if err != nil {
    if err == io.EOF {
    break
    }
    return "", err // f will be closed if we return here.
    }
    }
    return string(result), nil // f will be closed if we return here.
    }

    The third option, the one I like least (an understatement) is use of exceptions. Despite my personal preferences, it's quite popular.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stephen Hoffman@21:1/5 to Dave Froble on Wed Jan 31 11:05:22 2024
    On 2024-01-31 04:28:53 +0000, Dave Froble said:

    On 1/30/2024 9:40 AM, Chris Townley wrote:
    On 30/01/2024 07:06, Dave Froble wrote:
    On 1/29/2024 8:02 PM, Arne Vajhj wrote:
    On 1/29/2024 7:50 PM, kludge@panix.com wrote:
    =?UTF-8?Q?Arne_Vajh=C3=B8j?= <arne@vajhoej.dk> wrote:
    The code is VB6.

    But none of the problems are Basic specific. It is possible
    to write the same bad code in C or Fortran or whatever.

    So it just shows that there are some really really bad programmers out >>>>>> there.

    I have worked with people who could write spaghetti Fortran in any
    programming language available.

    "A real Fortran programmer can write Fortran in any language"

    Every time this comes up I post this Fortran/Pascal code:

    PROGRAM GOTOFUN(INPUT,OUTPUT);
    LABEL L731,L113,L247,L588,L761,L922,L399,L601;
    VAR LBL:INTEGER;
    VAR I:INTEGER;
    BEGIN
    L731: GOTO L113;
    LBL:=399;
    L113: I:=0;
    WRITELN(I);
    L247: LBL:=601;
    IF(I<0)THEN GOTO L588 ELSE IF(I=0)THEN GOTO L922 ELSE GOTO L399;
    L588: I:=I+1;
    WRITELN(I);
    GOTO L399;
    L761: CASE(LBL)OF 399: GOTO L399; 601: GOTO L601; END;
    L922: I:=I+1;
    WRITELN(I);
    CASE(I)OF 1: GOTO L588; 2: GOTO L399; 3: GOTO L922; END;
    L399: GOTO L761;
    L601: END.

    :-)

    Arne


    I'm amused every time the GoTo bashing begins.

    Not only is there nothing wrong when using a branch operation, when
    appropriate, just look at the assembler listings after compilation. Branching
    is just about all assembler does, as required.

    Now, I won't defend what I and most consider improper use of the poor
    misunderstood GoTo statement.


    But unless used very carefully, it can create horrible spaghetti like code, and
    is also easy to screw up.

    Using proper structured constructs is much better - easier to read as well, >> hence better maintainability.


    Prey tell, what structured construct will perform cleanup and exit? I
    always expected a return from routines and such.


    BASIC has its own variation on the classic TRY / THROW / CATCH /
    FINALLY syntax:
    WHEN ERROR IN
    protected-statement [protected-statement,...]
    USE
    handler-statement [handler-statement,...]
    END WHEN

    But I'm mildly surprised it's lacking an ATEXIT or ilk. (I thought it
    had that now, but I'm clearly mis-remembering.) I've used $dclexh and
    ilk in various apps, or coded the app to release at rundown. (Not that
    I prefer to have to implement manual cleanup, much as I'd like to avoid explicitly deallocating memory in C. Garbage collection is so much
    nicer, outside of kernel mode or other special app or context
    requirements.)
    Classic BASIC, Fortran, and C tend to be pretty bad at this
    error-handling stuff (it's kinda been grafted on) without a fair amount
    of work by the developer, and quite possibly with platform-specific
    calls ($dclexh, etc) added. (Yes, I know about setjmp, atexit(), etc.
    in C, and some other error-related syntax.) And yes, in BASIC, that
    GOTO is one of the common ways to deal with errors, but I'd usually go
    WHEN ERROR IN where I can. Or whatever other TRY / THROW / CATCH /
    FINALLY / ATEXIT exists in the particular implementation.

    And as for that earlier BASIC line number gibe, I'm sure most folks
    working with BASIC on OpenVMS nowadays are using labels, as the labels
    are just vastly more descriptive.

    I've long thought this: "If the ERR function is used before an error
    occurs or after an error is handled, the results are undefined" was
    silly. UB? Seriously? Return some analog to SS$_NORMAL. Poof. No UB.


    --
    Pure Personal Opinion | HoffmanLabs LLC

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dave Froble on Wed Jan 31 10:20:35 2024
    On 1/30/2024 11:28 PM, Dave Froble wrote:
    On 1/30/2024 9:40 AM, Chris Townley wrote:
    On 30/01/2024 07:06, Dave Froble wrote:
    I'm amused every time the GoTo bashing begins.

    Not only is there nothing wrong when using a branch operation, when
    appropriate, just look at the assembler listings after compilation.
    Branching
    is just about all assembler does, as required.

    Now, I won't defend what I and most consider improper use of the poor
    misunderstood GoTo statement.


    But unless used very carefully, it can create horrible spaghetti like
    code, and
    is also easy to screw up.

    Using proper structured constructs is much better - easier to read as
    well,
    hence better maintainability.

    Prey tell, what structured construct will perform cleanup and exit?  I always expected a return from routines and such.

    Let me try and show some examples.

    In VB.NET.

    Te first two examples could be done in VMS Basic (obviously
    procedural not object oriented) but the last can not.

    First with goto:

    Imports System

    Namespace GoToDemo
    Public NotInheritable Class Luck
    Private Shared rng As New Random()
    Public Shared Function InLuck() As Boolean
    Return rng.NextDouble() > 0.2
    End Function
    End Class
    Public Class X
    Private id As String
    Private Sub New(id As String)
    Me.id = id
    Console.WriteLine("X {0} created", id)
    End Sub
    Public Shared Function Create(id As String) As X
    If Luck.InLuck() Then
    Return New X(id)
    Else
    Return Nothing
    End If
    End Function
    Public Sub Close()
    Console.WriteLine("X {0} closed", id)
    End Sub
    End Class
    Public Class Program
    Public Shared Sub Main(args As String())
    Dim o1 As X = X.Create("A")
    If o1 Is Nothing Then
    Console.WriteLine("Error creating A")
    GoTo lbl_done
    End If
    Dim o2 As X = X.Create("B")
    If o2 Is Nothing Then
    Console.WriteLine("Error creating B")
    GoTo lbl_close1
    End If
    ' 20 lines
    Console.WriteLine("Part 1")
    If Not Luck.InLuck() Then
    Console.WriteLine("Error during execution")
    GoTo lbl_close2
    End If
    ' 20 lines
    Console.WriteLine("Part 2")
    lbl_close2:
    o2.Close()
    lbl_close1:
    o1.Close()
    lbl_done:
    Console.ReadKey(True)
    End Sub
    End Class
    End Namespace

    It is with goto, but I don't think it is a bad use of goto. It just
    jumps down to the cleanup code in case of an error.

    Next traditional blocks:

    Imports System

    Namespace BlocksDemo
    Public NotInheritable Class Luck
    Private Shared rng As New Random()
    Public Shared Function InLuck() As Boolean
    Return rng.NextDouble() > 0.2
    End Function
    End Class
    Public Class X
    Private id As String
    Private Sub New(id As String)
    Me.id = id
    Console.WriteLine("X {0} created", id)
    End Sub
    Public Shared Function Create(id As String) As X
    If Luck.InLuck() Then
    Return New X(id)
    Else
    Return Nothing
    End If
    End Function
    Public Sub Close()
    Console.WriteLine("X {0} closed", id)
    End Sub
    End Class
    Public Class Program
    Public Shared Sub Main(args As String())
    Dim o1 As X = X.Create("A")
    If o1 IsNot Nothing Then
    Dim o2 As X = X.Create("B")
    If o2 IsNot Nothing Then
    ' 20 lines
    Console.WriteLine("Part 1")
    If Luck.InLuck() Then
    ' 20 lines
    Console.WriteLine("Part 2")
    Else
    Console.WriteLine("Error during execution")
    End If
    o2.Close()
    Else
    Console.WriteLine("Error creating B")
    End If
    o1.Close()
    Else
    Console.WriteLine("Error creating A")
    End If
    Console.ReadKey(True)
    End Sub
    End Class
    End Namespace

    No goto's. But I do not consider the code more readable than the
    version with goto's. It sort of unnecessarily stretch out the
    core logic.

    And now the modern way with exceptions:

    Imports System

    Namespace ExceptionsDemo
    Public NotInheritable Class Luck
    Private Shared rng As New Random()
    Public Shared Function InLuck() As Boolean
    Return rng.NextDouble() > 0.2
    End Function
    End Class
    Public Class XException
    Inherits Exception
    Public Sub New(msg As String)
    MyBase.New(msg)
    End Sub
    End Class
    Public Class X
    Implements IDisposable
    Private id As String
    Public Sub New(id As String)
    If Luck.InLuck() Then
    Me.id = id
    Console.WriteLine("X {0} created", id)
    Else
    Throw New XException("Error creating " & id)
    End If
    End Sub
    Public Sub Dispose() Implements IDisposable.Dispose
    Console.WriteLine("X {0} closed", id)
    End Sub
    End Class
    Public Class Program
    Public Shared Sub Main(args As String())
    Try
    Using o1 As New X("A")
    Using o2 As New X("B")
    ' 20 lines
    Console.WriteLine("Part 1")
    If Not Luck.InLuck() Then
    Throw New XException("Error during execution")
    End If
    ' 20 lines
    Console.WriteLine("Part 2")
    End Using
    End Using
    Catch ex As XException
    Console.WriteLine(ex.Message)
    End Try
    Console.ReadKey(True)
    End Sub
    End Class
    End Namespace

    Which I think is pretty nice. No goto's but still a compact
    core logic.

    For the not VB.NET knowledgable:

    Using o1 As New X("A")
    ...
    End Using

    calls o1.Dispose() when the block is exited no matter how it
    is exited - normal or exception does not matter Dispose is
    always called.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Dorsey@21:1/5 to already5chosen@yahoo.com on Wed Jan 31 16:17:15 2024
    Michael S <already5chosen@yahoo.com> wrote:

    The third option, the one I like least (an understatement) is use of >exceptions. Despite my personal preferences, it's quite popular.

    Exceptions can be very elegant or very inelegant... and it is entirely
    possible to have an exception that doesn't clean anything up at all and
    just exits and lets the operating system deal with the memory. On many
    systems this is a great idea because being able to exit quickly on a failure
    is more important than people give it credit for. On some other systems
    that have memory management issues it can lead to leakage.
    --scott
    --
    "C'est un Nagra. C'est suisse, et tres, tres precis."

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Simon Clubley@21:1/5 to arne@vajhoej.dk on Wed Jan 31 18:22:37 2024
    On 2024-01-31, Arne Vajhj <arne@vajhoej.dk> wrote:

    For the not VB.NET knowledgable:

    Using o1 As New X("A")
    ...
    End Using

    calls o1.Dispose() when the block is exited no matter how it
    is exited - normal or exception does not matter Dispose is
    always called.


    Unless there is a power failure or a system crash.

    I wonder how many people think of that one when assuming that their
    state reset code will _always_ run after execution of the routine
    has started. :-)

    Simon.

    --
    Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
    Walking destinations on a map are further away than they appear.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Simon Clubley on Wed Jan 31 13:38:32 2024
    On 1/31/2024 1:22 PM, Simon Clubley wrote:
    On 2024-01-31, Arne Vajhøj <arne@vajhoej.dk> wrote:
    For the not VB.NET knowledgable:

    Using o1 As New X("A")
    ...
    End Using

    calls o1.Dispose() when the block is exited no matter how it
    is exited - normal or exception does not matter Dispose is
    always called.

    Unless there is a power failure or a system crash.

    I guess that is also a form of exit.

    :-)

    I wonder how many people think of that one when assuming that their
    state reset code will _always_ run after execution of the routine
    has started. :-)

    Probably none. But it probably does not matter either.

    The construct is used to free unmanaged resources in the
    process. Open files, open network connections like database
    connections, unmanaged memory etc.. All stuff that goes
    away if the process is gone.

    I have never seen the construct used to reset an out
    of process state (persisted state). And I have seen
    a lot of C#, VB.NET, Java, Python etc. code using the
    construct.

    If there is a need for a consistent out of process
    state (persisted state), then it has to be transactions.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to Chris Townley on Wed Jan 31 13:27:57 2024
    On 1/31/2024 7:03 AM, Chris Townley wrote:
    On 31/01/2024 04:28, Dave Froble wrote:
    On 1/30/2024 9:40 AM, Chris Townley wrote:
    On 30/01/2024 07:06, Dave Froble wrote:
    On 1/29/2024 8:02 PM, Arne Vajhøj wrote:
    On 1/29/2024 7:50 PM, kludge@panix.com wrote:
    =?UTF-8?Q?Arne_Vajh=C3=B8j?= <arne@vajhoej.dk> wrote:
    The code is VB6.

    But none of the problems are Basic specific. It is possible
    to write the same bad code in C or Fortran or whatever.

    So it just shows that there are some really really bad programmers out >>>>>>> there.

    I have worked with people who could write spaghetti Fortran in any >>>>>> programming language available.

    "A real Fortran programmer can write Fortran in any language"

    Every time this comes up I post this Fortran/Pascal code:

    PROGRAM GOTOFUN(INPUT,OUTPUT);
    LABEL L731,L113,L247,L588,L761,L922,L399,L601;
    VAR LBL:INTEGER;
    VAR I:INTEGER;
    BEGIN
    L731: GOTO L113;
    LBL:=399;
    L113: I:=0;
    WRITELN(I);
    L247: LBL:=601;
    IF(I<0)THEN GOTO L588 ELSE IF(I=0)THEN GOTO L922 ELSE GOTO L399; >>>>> L588: I:=I+1;
    WRITELN(I);
    GOTO L399;
    L761: CASE(LBL)OF 399: GOTO L399; 601: GOTO L601; END;
    L922: I:=I+1;
    WRITELN(I);
    CASE(I)OF 1: GOTO L588; 2: GOTO L399; 3: GOTO L922; END;
    L399: GOTO L761;
    L601: END.

    :-)

    Arne


    I'm amused every time the GoTo bashing begins.

    Not only is there nothing wrong when using a branch operation, when
    appropriate, just look at the assembler listings after compilation. Branching
    is just about all assembler does, as required.

    Now, I won't defend what I and most consider improper use of the poor
    misunderstood GoTo statement.


    But unless used very carefully, it can create horrible spaghetti like code, and
    is also easy to screw up.

    Using proper structured constructs is much better - easier to read as well, >>> hence better maintainability.



    Prey tell, what structured construct will perform cleanup and exit? I always
    expected a return from routines and such.


    It would depend on what is needing to be done


    Final cleanup, if required, and exit the program.

    Knew a guy that would us a gosub to go to the END statement. Drove me nuts.

    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Scott Dorsey on Wed Jan 31 13:29:30 2024
    On 1/31/2024 11:17 AM, Scott Dorsey wrote:
    Michael S <already5chosen@yahoo.com> wrote:

    The third option, the one I like least (an understatement) is use of
    exceptions. Despite my personal preferences, it's quite popular.

    Exceptions can be very elegant or very inelegant... and it is entirely possible to have an exception that doesn't clean anything up at all and
    just exits and lets the operating system deal with the memory. On many systems this is a great idea because being able to exit quickly on a failure is more important than people give it credit for. On some other systems
    that have memory management issues it can lead to leakage.

    It is probably a bit easier to implement exceptions in languages
    with garbage collection and a lot easier for developers to avoid
    memory leak bugs.

    $ type mem.cpp
    #include <iostream>
    #include <string>

    using namespace std;

    class X
    {
    private:
    string id;
    public:
    X(string id) { this->id = id; cout << "Allocate " << id << endl; }
    virtual ~X() { cout << "Deallocate " << id << endl; }
    };

    void f2()
    {
    throw "Houston we have a problem";
    }

    void f1()
    {
    X o2("o2");
    X *o3 = new X("o3");
    f2();
    delete o3;
    }

    int main()
    {
    try
    {
    X o1("o1");
    f1();
    }
    catch(char *ex)
    {
    cout << ex << endl;
    }
    return 0;
    }

    $ cxx mem.cpp
    $ cxxlink mem
    link mem
    $ run mem
    Allocate o1
    Allocate o2
    Allocate o3
    Deallocate o2
    Deallocate o1
    Houston we have a problem
    $

    We see that o2 did get deallocated, but o3 did not get deallocated.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Wed Jan 31 20:41:32 2024
    In article <upe3ib$1kker$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 1/31/2024 11:17 AM, Scott Dorsey wrote:
    Michael S <already5chosen@yahoo.com> wrote:

    The third option, the one I like least (an understatement) is use of
    exceptions. Despite my personal preferences, it's quite popular.

    Exceptions can be very elegant or very inelegant... and it is entirely
    possible to have an exception that doesn't clean anything up at all and
    just exits and lets the operating system deal with the memory. On many
    systems this is a great idea because being able to exit quickly on a failure >> is more important than people give it credit for. On some other systems
    that have memory management issues it can lead to leakage.

    It is probably a bit easier to implement exceptions in languages
    with garbage collection and a lot easier for developers to avoid
    memory leak bugs.

    $ type mem.cpp
    #include <iostream>
    #include <string>

    using namespace std;

    class X
    {
    private:
    string id;
    public:
    X(string id) { this->id = id; cout << "Allocate " << id << endl; }
    virtual ~X() { cout << "Deallocate " << id << endl; }
    };

    void f2()
    {
    throw "Houston we have a problem";
    }

    void f1()
    {
    X o2("o2");
    X *o3 = new X("o3");
    f2();
    delete o3;
    }

    int main()
    {
    try
    {
    X o1("o1");
    f1();
    }
    catch(char *ex)
    {
    cout << ex << endl;
    }
    return 0;
    }

    $ cxx mem.cpp
    $ cxxlink mem
    link mem
    $ run mem
    Allocate o1
    Allocate o2
    Allocate o3
    Deallocate o2
    Deallocate o1
    Houston we have a problem
    $

    We see that o2 did get deallocated, but o3 did not get deallocated.

    This is well-known in older C++ code; since C++11 one should be
    using `std::unique_ptr<T>` to avoid this sort of issue. Code
    using an older dialect could look at something like the
    venerable ScopeGuard as a defensive technique to guard against
    leaks. https://www.drdobbs.com/article/print?articleId=184403758&siteSectionName=cpp

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Bob Eager on Wed Jan 31 21:21:10 2024
    On 31 Jan 2024 09:54:15 GMT, Bob Eager wrote:

    We had a machine that ran FORTRAN for the physics department. One guy
    had a program that crashed the machine. As in, the microcode halted.
    That was an array bounds error.

    Full story:

    http://www.bobeager.uk/anecdotes.html#hwhack

    We contacted ICL, but we never seemed to reach anyone who either
    understood what the problem was, or had the power or inclination
    to get it fixed ...

    If this was not after the Fujitsu acquisition, I assume it wasn’t long
    before ...

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Wed Jan 31 21:24:14 2024
    On Wed, 31 Jan 2024 10:20:35 -0500, Arne Vajhøj wrote:

    For the not VB.NET knowledgable:

    Using o1 As New X("A")
    ...
    End Using

    calls o1.Dispose() when the block is exited no matter how it is exited - normal or exception does not matter Dispose is always called.

    Python has “context managers” which are a generalization of this. It also has “try/finally” blocks, which are good for one-off cases.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Michael S on Wed Jan 31 21:28:01 2024
    On Wed, 31 Jan 2024 15:52:30 +0200, Michael S wrote:

    One option is named construct and named break.

    I have never written a goto in C code (not production code, anyway). These days, you need to do so much dynamic allocation, there is nearly always
    some need for cleanup when exiting an inner block anyway, so you can’t
    just jump directly somewhere else first. The overall pattern looks like
    this:

    MyPtr obj = NULL;
    do /*once*/
    {
    ... possible other stuff ...
    «allocate memory for obj»;
    if («error occurred»)
    break;
    ... possible other stuff using obj ...
    }
    while (false);
    free(obj);

    You can confirm, just by inspection, that there is no path out of the
    block that does not pass through the free() call precisely once.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Lawrence D'Oliveiro on Wed Jan 31 23:43:40 2024
    On Wed, 31 Jan 2024 21:21:10 -0000 (UTC)
    Lawrence D'Oliveiro <ldo@nz.invalid> wrote:

    On 31 Jan 2024 09:54:15 GMT, Bob Eager wrote:

    We had a machine that ran FORTRAN for the physics department. One
    guy had a program that crashed the machine. As in, the microcode
    halted. That was an array bounds error.

    Full story:

    http://www.bobeager.uk/anecdotes.html#hwhack

    We contacted ICL, but we never seemed to reach anyone who either
    understood what the problem was, or had the power or inclination
    to get it fixed ...

    If this was not after the Fujitsu acquisition, I assume it wasn’t
    long before ...

    From the article it looks like 1980, probably H1.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Wed Jan 31 17:13:26 2024
    On 1/31/2024 4:24 PM, Lawrence D'Oliveiro wrote:
    On Wed, 31 Jan 2024 10:20:35 -0500, Arne Vajhøj wrote:
    For the not VB.NET knowledgable:

    Using o1 As New X("A")
    ...
    End Using

    calls o1.Dispose() when the block is exited no matter how it is exited -
    normal or exception does not matter Dispose is always called.

    Python has “context managers” which are a generalization of this. It also has “try/finally” blocks, which are good for one-off cases.

    C# was born with using (2002), Python got with in 2.5 (2006)
    and Java got try with resource in 1.7 (2011).

    MS got a good idea and the rest copied it.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Wed Jan 31 17:08:44 2024
    On 1/31/2024 4:28 PM, Lawrence D'Oliveiro wrote:
    I have never written a goto in C code (not production code, anyway). These days, you need to do so much dynamic allocation, there is nearly always
    some need for cleanup when exiting an inner block anyway, so you can’t
    just jump directly somewhere else first. The overall pattern looks like
    this:

    MyPtr obj = NULL;
    do /*once*/
    {
    ... possible other stuff ...
    «allocate memory for obj»;
    if («error occurred»)
    break;
    ... possible other stuff using obj ...
    }
    while (false);
    free(obj);

    You can confirm, just by inspection, that there is no path out of the
    block that does not pass through the free() call precisely once.

    And the difference compared to:

    MyPtr obj = NULL;
    ... possible other stuff ...
    «allocate memory for obj»;
    if («error occurred»)
    goto lbl_freeobj;
    ... possible other stuff using obj ...
    lbl_freeobj:
    free(obj);

    are?

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Stephen Hoffman on Wed Jan 31 21:22:33 2024
    On Wed, 31 Jan 2024 11:05:22 -0500, Stephen Hoffman wrote:

    (Not that I prefer to have to implement manual cleanup, much as I'd like
    to avoid explicitly deallocating memory in C.

    Note that free(3) is defined as idempotent; freeing a NULL pointer is a harmless no-op. That simplifies things a lot.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to All on Wed Jan 31 18:04:52 2024
    On 1/31/2024 5:08 PM, Arne Vajhøj wrote:
    On 1/31/2024 4:28 PM, Lawrence D'Oliveiro wrote:
    I have never written a goto in C code (not production code, anyway). These >> days, you need to do so much dynamic allocation, there is nearly always
    some need for cleanup when exiting an inner block anyway, so you can’t
    just jump directly somewhere else first. The overall pattern looks like
    this:

    MyPtr obj = NULL;
    do /*once*/
    {
    ... possible other stuff ...
    «allocate memory for obj»;
    if («error occurred»)
    break;
    ... possible other stuff using obj ...
    }
    while (false);
    free(obj);

    You can confirm, just by inspection, that there is no path out of the
    block that does not pass through the free() call precisely once.

    And the difference compared to:

    MyPtr obj = NULL;
    ... possible other stuff ...
    «allocate memory for obj»;
    if («error occurred»)
    goto lbl_freeobj;
    ... possible other stuff using obj ...
    lbl_freeobj:
    free(obj);

    are?

    Arne



    I've seen code that did all kinds of confusing things, just avoid a GoTo branch.
    My question is, why? If the need is a simple and rather easy to understand branch, why get complex, just to be "political correct", which ia also a rather stupid concept.

    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Wed Jan 31 23:21:34 2024
    On Wed, 31 Jan 2024 17:08:44 -0500, Arne Vajhøj wrote:

    On 1/31/2024 4:28 PM, Lawrence D'Oliveiro wrote:

    I have never written a goto in C code (not production code, anyway). These >> days, you need to do so much dynamic allocation, there is nearly always
    some need for cleanup when exiting an inner block anyway, so you can’t
    just jump directly somewhere else first. The overall pattern looks like
    this:

    MyPtr obj = NULL;
    do /*once*/
    {
    ... possible other stuff ...
    «allocate memory for obj»;
    if («error occurred»)
    break;
    ... possible other stuff using obj ...
    }
    while (false);
    free(obj);

    You can confirm, just by inspection, that there is no path out of the
    block that does not pass through the free() call precisely once.

    And the difference compared to:

    MyPtr obj = NULL;
    ... possible other stuff ...
    «allocate memory for obj»;
    if («error occurred»)
    goto lbl_freeobj;
    ... possible other stuff using obj ...
    lbl_freeobj:
    free(obj);

    are?

    Nesting. Try to scale up to something like

    static PyObject * discipline_makedict
    (
    PyObject * self,
    PyObject * args
    )
    {
    PyObject * result = NULL;
    PyObject * tempresult = NULL;
    br_PyObject * items;
    const br_char * msg = NULL;
    do /*once*/
    {
    const bool parsed_ok = PyArg_ParseTuple(args, "Os", &items, &msg);
    if (not parsed_ok)
    break;
    fprintf(stdout, "makedict says: “%s”\n", msg);
    if (not PyTuple_Check(items))
    {
    PyErr_SetString(PyExc_TypeError, "expecting a tuple");
    break;
    } /*if*/
    const ssize_t nr_items = PyTuple_Size(items);
    if (PyErr_Occurred())
    break;
    tempresult = PyDict_New();
    if (tempresult == NULL)
    break;
    for (ssize_t i = 0;;)
    {
    if (i == nr_items)
    break;
    br_PyObject * const item = PyTuple_GetItem(items, i);
    if (item == NULL)
    break;
    if (not PyTuple_Check(item) or PyTuple_Size(item) != 2)
    {
    PyErr_SetString(PyExc_TypeError, "expecting a 2-tuple");
    break;
    } /*if*/
    br_PyObject * const first = PyTuple_GetItem(item, 0);
    if (first == NULL)
    break;
    br_PyObject * const second = PyTuple_GetItem(item, 1);
    if (second == NULL)
    break;
    if (first == (PyObject *)&ExceptMe_type or second == (PyObject *)&ExceptMe_type)
    {
    PyErr_SetString(PyExc_ValueError, "ExceptMe object found");
    break;
    } /*if*/
    if (PyDict_SetItem(tempresult, first, second) < 0)
    break;
    ++i;
    } /*for*/
    if (PyErr_Occurred())
    break;
    /* all done */
    result = tempresult;
    tempresult = NULL; /* so I don’t dispose of it yet */
    }
    while (false);
    Py_XDECREF(tempresult);
    return
    result;
    } /*discipline_makedict*/

    More details here <https://gitlab.com/ldo/a_structured_discipline_of_programming/>.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Wed Jan 31 23:18:12 2024
    On Wed, 31 Jan 2024 17:13:26 -0500, Arne Vajhøj wrote:

    On 1/31/2024 4:24 PM, Lawrence D'Oliveiro wrote:

    On Wed, 31 Jan 2024 10:20:35 -0500, Arne Vajhøj wrote:

    For the not VB.NET knowledgable:

    Using o1 As New X("A")
    ...
    End Using

    calls o1.Dispose() when the block is exited no matter how it is exited - >>> normal or exception does not matter Dispose is always called.

    Python has “context managers” which are a generalization of this. It also
    has “try/finally” blocks, which are good for one-off cases.

    C# was born with using (2002), Python got with in 2.5 (2006)
    and Java got try with resource in 1.7 (2011).

    MS got a good idea and the rest copied it.

    That is also true of async/await. But note that Python is the only one
    of the three that tries to use reference-counting as an alternative to
    garbage collection.

    And now it looks like C# might be shuffling off into those retirement
    pastures <https://www.theregister.com/2024/01/31/microsoft_seeks_rust_developers/>.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Wed Jan 31 19:42:50 2024
    On 1/31/2024 6:18 PM, Lawrence D'Oliveiro wrote:
    On Wed, 31 Jan 2024 17:13:26 -0500, Arne Vajhøj wrote:

    On 1/31/2024 4:24 PM, Lawrence D'Oliveiro wrote:

    On Wed, 31 Jan 2024 10:20:35 -0500, Arne Vajhøj wrote:

    For the not VB.NET knowledgable:

    Using o1 As New X("A")
    ...
    End Using

    calls o1.Dispose() when the block is exited no matter how it is exited - >>>> normal or exception does not matter Dispose is always called.

    Python has “context managers” which are a generalization of this. It also
    has “try/finally” blocks, which are good for one-off cases.

    C# was born with using (2002), Python got with in 2.5 (2006)
    and Java got try with resource in 1.7 (2011).

    MS got a good idea and the rest copied it.

    That is also true of async/await. But note that Python is the only one
    of the three that tries to use reference-counting as an alternative to garbage collection.

    All of them use garbage collection.

    Java and C# use tracing garbage collection.

    Python use both tracing garbage collection and reference
    counting garbage collection. Or more precisely the common
    implementation CPython does - there are other Python
    implementations that use only tracing garbage collection.

    And now it looks like C# might be shuffling off into those retirement pastures <https://www.theregister.com/2024/01/31/microsoft_seeks_rust_developers/>.

    Very interesting for Rust, but not particular important for C#.

    C# is primarily for business applications.

    That Microsoft will rewrite some platform software supporting
    moving data within Office 365 in Azure from C# to Rust does
    not indicate the end of C#.

    I would consider it more negative for Go. Go is big in that
    type of cloud and/or container platform software, so MS not
    picking Go may indicate something.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Townley@21:1/5 to Dave Froble on Thu Feb 1 00:15:52 2024
    On 31/01/2024 18:27, Dave Froble wrote:
    On 1/31/2024 7:03 AM, Chris Townley wrote:
    On 31/01/2024 04:28, Dave Froble wrote:
    On 1/30/2024 9:40 AM, Chris Townley wrote:
    On 30/01/2024 07:06, Dave Froble wrote:
    On 1/29/2024 8:02 PM, Arne Vajhøj wrote:
    On 1/29/2024 7:50 PM, kludge@panix.com wrote:
    =?UTF-8?Q?Arne_Vajh=C3=B8j?=  <arne@vajhoej.dk> wrote:
    The code is VB6.

    But none of the problems are Basic specific. It is possible
    to write the same bad code in C or Fortran or whatever.

    So it just shows that there are some really really bad
    programmers out
    there.

    I have worked with people who could write spaghetti Fortran in any >>>>>>> programming language available.

    "A real Fortran programmer can write Fortran in any language"

    Every time this comes up I post this Fortran/Pascal code:

          PROGRAM GOTOFUN(INPUT,OUTPUT);
          LABEL L731,L113,L247,L588,L761,L922,L399,L601;
          VAR LBL:INTEGER;
          VAR I:INTEGER;
          BEGIN
    L731: GOTO L113;
          LBL:=399;
    L113: I:=0;
          WRITELN(I);
    L247: LBL:=601;
          IF(I<0)THEN GOTO L588 ELSE IF(I=0)THEN GOTO L922 ELSE GOTO >>>>>> L399;
    L588: I:=I+1;
          WRITELN(I);
          GOTO L399;
    L761: CASE(LBL)OF 399: GOTO L399; 601: GOTO L601; END;
    L922: I:=I+1;
          WRITELN(I);
          CASE(I)OF 1: GOTO L588; 2: GOTO L399; 3: GOTO L922; END; >>>>>> L399: GOTO L761;
    L601: END.

    :-)

    Arne


    I'm amused every time the GoTo bashing begins.

    Not only is there nothing wrong when using a branch operation, when
    appropriate, just look at the assembler listings after
    compilation.  Branching
    is just about all assembler does, as required.

    Now, I won't defend what I and most consider improper use of the poor >>>>> misunderstood GoTo statement.


    But unless used very carefully, it can create horrible spaghetti
    like code, and
    is also easy to screw up.

    Using proper structured constructs is much better - easier to read
    as well,
    hence better maintainability.



    Prey tell, what structured construct will perform cleanup and exit?
    I always
    expected a return from routines and such.


    It would depend on what is needing to be done


    Final cleanup, if required, and exit the program.

    Knew a guy that would us a gosub to go to the END statement.  Drove me
    nuts.


    We always used global error handling, as well as local when error...

    At least with DEC Basic, it always handled garbage collection

    --
    Chris

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Wed Jan 31 19:29:14 2024
    On 1/31/2024 6:21 PM, Lawrence D'Oliveiro wrote:
    On Wed, 31 Jan 2024 17:08:44 -0500, Arne Vajhøj wrote:

    On 1/31/2024 4:28 PM, Lawrence D'Oliveiro wrote:

    I have never written a goto in C code (not production code, anyway). These >>> days, you need to do so much dynamic allocation, there is nearly always
    some need for cleanup when exiting an inner block anyway, so you can’t >>> just jump directly somewhere else first. The overall pattern looks like
    this:

    MyPtr obj = NULL;
    do /*once*/
    {
    ... possible other stuff ...
    «allocate memory for obj»;
    if («error occurred»)
    break;
    ... possible other stuff using obj ...
    }
    while (false);
    free(obj);

    You can confirm, just by inspection, that there is no path out of the
    block that does not pass through the free() call precisely once.

    And the difference compared to:

    MyPtr obj = NULL;
    ... possible other stuff ...
    «allocate memory for obj»;
    if («error occurred»)
    goto lbl_freeobj;
    ... possible other stuff using obj ...
    lbl_freeobj:
    free(obj);

    are?

    Nesting.

    Goto work fine with nested loops. In fact it is one of the cases
    where it really makes sense.

    Try to scale up to something like

    static PyObject * discipline_makedict
    (
    PyObject * self,
    PyObject * args
    )
    {
    PyObject * result = NULL;
    PyObject * tempresult = NULL;
    br_PyObject * items;
    const br_char * msg = NULL;
    do /*once*/
    {
    const bool parsed_ok = PyArg_ParseTuple(args, "Os", &items, &msg);
    if (not parsed_ok)
    break;
    fprintf(stdout, "makedict says: “%s”\n", msg);
    if (not PyTuple_Check(items))
    {
    PyErr_SetString(PyExc_TypeError, "expecting a tuple");
    break;
    } /*if*/
    const ssize_t nr_items = PyTuple_Size(items);
    if (PyErr_Occurred())
    break;
    tempresult = PyDict_New();
    if (tempresult == NULL)
    break;
    for (ssize_t i = 0;;)
    {
    if (i == nr_items)
    break;
    br_PyObject * const item = PyTuple_GetItem(items, i);
    if (item == NULL)
    break;
    if (not PyTuple_Check(item) or PyTuple_Size(item) != 2)
    {
    PyErr_SetString(PyExc_TypeError, "expecting a 2-tuple");
    break;
    } /*if*/
    br_PyObject * const first = PyTuple_GetItem(item, 0);
    if (first == NULL)
    break;
    br_PyObject * const second = PyTuple_GetItem(item, 1);
    if (second == NULL)
    break;
    if (first == (PyObject *)&ExceptMe_type or second == (PyObject *)&ExceptMe_type)
    {
    PyErr_SetString(PyExc_ValueError, "ExceptMe object found");
    break;
    } /*if*/
    if (PyDict_SetItem(tempresult, first, second) < 0)
    break;
    ++i;
    } /*for*/
    if (PyErr_Occurred())
    break;
    /* all done */
    result = tempresult;
    tempresult = NULL; /* so I don’t dispose of it yet */
    }
    while (false);
    Py_XDECREF(tempresult);
    return
    result;
    } /*discipline_makedict*/

    That code would look a lot cleaner if the do while(false) loop got
    removed and the relevant breaks got replaced by goto's.

    A well named goto label is much more informative than a plain break.

    More details here <https://gitlab.com/ldo/a_structured_discipline_of_programming/>.

    Truly bad design.

    All the code examples would look better with the do while(false) loops
    removed and appropriate goto's.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Thu Feb 1 01:59:13 2024
    In article <upeokq$1o97f$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 1/31/2024 6:21 PM, Lawrence D'Oliveiro wrote:
    On Wed, 31 Jan 2024 17:08:44 -0500, Arne Vajhøj wrote:
    On 1/31/2024 4:28 PM, Lawrence D'Oliveiro wrote:
    [snip]
    Nesting.

    Goto work fine with nested loops. In fact it is one of the cases
    where it really makes sense.

    I think the troll was referring to nested control structures,
    with nested resource handling.

    Try to scale up to something like

    static PyObject * discipline_makedict
    (
    PyObject * self,
    PyObject * args
    )
    {
    PyObject * result = NULL;
    PyObject * tempresult = NULL;
    br_PyObject * items;
    const br_char * msg = NULL;
    do /*once*/
    {
    const bool parsed_ok = PyArg_ParseTuple(args, "Os", &items, &msg); >> if (not parsed_ok)
    break;
    fprintf(stdout, "makedict says: “%s”\n", msg);
    if (not PyTuple_Check(items))
    {
    PyErr_SetString(PyExc_TypeError, "expecting a tuple");
    break;
    } /*if*/
    const ssize_t nr_items = PyTuple_Size(items);
    if (PyErr_Occurred())
    break;
    tempresult = PyDict_New();
    if (tempresult == NULL)
    break;
    for (ssize_t i = 0;;)
    {
    if (i == nr_items)
    break;
    br_PyObject * const item = PyTuple_GetItem(items, i);
    if (item == NULL)
    break;
    if (not PyTuple_Check(item) or PyTuple_Size(item) != 2)
    {
    PyErr_SetString(PyExc_TypeError, "expecting a 2-tuple");
    break;
    } /*if*/
    br_PyObject * const first = PyTuple_GetItem(item, 0);
    if (first == NULL)
    break;
    br_PyObject * const second = PyTuple_GetItem(item, 1);
    if (second == NULL)
    break;
    if (first == (PyObject *)&ExceptMe_type or second == (PyObject *)&ExceptMe_type)
    {
    PyErr_SetString(PyExc_ValueError, "ExceptMe object found"); >> break;
    } /*if*/
    if (PyDict_SetItem(tempresult, first, second) < 0)
    break;
    ++i;
    } /*for*/
    if (PyErr_Occurred())
    break;
    /* all done */
    result = tempresult;
    tempresult = NULL; /* so I don’t dispose of it yet */
    }
    while (false);
    Py_XDECREF(tempresult);
    return
    result;
    } /*discipline_makedict*/

    That code would look a lot cleaner if the do while(false) loop got
    removed and the relevant breaks got replaced by goto's.

    I almost agree. That could is borderline unreadable, but if one
    detangles it from the weird web of style its obfuscated by, one
    realizes it can be written in a far more straight-forward manner
    without either `goto` or the weird do/while style. Near as I
    can tell, the following rough cut is equivalent to the original:

    static PyObject *
    discipline_makedict(PyObject *self, PyObject *args)
    {
    br_PyObject *items;
    const br_char *msg = NULL;

    const bool parsed_ok = PyArg_ParseTuple(args, "Os", &items, &msg);
    if (!parsed_ok)
    return NULL;

    printf("makedict says: \xe2\x80\x9c%s\xe2\x80\x9d\n", msg);
    if (!PyTuple_Check(items)) {
    PyErr_SetString(PyExc_TypeError, "expecting a tuple");
    return NULL;
    }
    const ssize_t nitems = PyTuple_Size(items);
    if (PyErr_Occurred())
    return NULL;

    PyObject *result = PyDict_New();
    if (result == NULL)
    return NULL;

    for (ssize_t i = 0; i < nitems; ++i) {
    br_PyObject *const item = PyTuple_GetItem(items, i);
    if (item == NULL)
    break;
    if (!PyTuple_Check(item) || PyTuple_Size(item) != 2) {
    PyErr_SetString(PyExc_TypeError, "expecting a 2-tuple");
    break;
    }
    br_PyObject *const first = PyTuple_GetItem(item, 0);
    if (first == NULL)
    break;
    br_PyObject *const second = PyTuple_GetItem(item, 1);
    if (second == NULL)
    break;
    if (first == (PyObject *)&ExceptMe_type || second == (PyObject *)&ExceptMe_type) {
    PyErr_SetString(PyExc_ValueError, "ExceptMe object found");
    break;
    }
    if (PyDict_SetItem(result, first, second) < 0)
    break;
    }

    if (PyErr_Occurred()) {
    Py_XDECREF(result);
    return NULL;
    }

    return result;
    }

    I would argue this is more idiomatic, shorter, simpler, easier
    to both read and to reason about, and uses fewer variables.

    I couldn't really figure out why the `printf` was in there, so I
    left it in; it looks like debugging code though. I didn't test
    it, however, since I don't really care.

    A well named goto label is much more informative than a plain break.

    Agreed. In this case, the breaks are sufficiently contained
    once the rest of the cruft is cut away that I don't think a goto
    is any better.

    More details here
    <https://gitlab.com/ldo/a_structured_discipline_of_programming/>.

    Truly bad design.

    All the code examples would look better with the do while(false) loops >removed and appropriate goto's.

    Agreed. That code is straight garbage, and should not make it
    past any serious review.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to davef@tsoft-inc.com on Thu Feb 1 01:26:12 2024
    In article <upejl0$1nkl5$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    I've seen code that did all kinds of confusing things, just avoid a GoTo branch.
    My question is, why? If the need is a simple and rather easy to understand
    branch, why get complex,

    `goto` by itself is a sharp tool; sometimes incredibly useful,
    but dangerous if misused. Our industry is littered with example
    after example of `goto` misused. For instance, https://dwheeler.com/essays/apple-goto-fail.html

    Because of the potential and history of misuse, it's a laudable
    goal to reduce use of `goto`, and indeed, over the years we've
    seen generations of languages where the primary use cases have
    been analyzed and the most useful lifted into new constructs
    that become first-class parts of their respective languages;
    `break` and `continue` for loops, exceptions, and so on.

    Moreover, this is useful in the sense that programming languages
    also serve a communicative purpose. How many of us would change
    a `for` loop to if's and gotos given the choice? I wager few
    would; the former communicates intent far more clearly than the
    latter. For that matter, if we could iterate over a collection,
    that's even better again.

    That said, `goto` obviously _does_ have a place when used
    judiciously. As Ken Thompson once said, "if you want to go
    somewhere, goto is the best way to get there." Like all goals,
    the desire to reduce `goto` prevelence is mostly aspirational.
    Certainly, we're well past the context of Djikstra's "GO TO
    STATEMENT CONSIDERED HARMFUL" CACM letter.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Thu Feb 1 02:50:41 2024
    On Wed, 31 Jan 2024 19:42:50 -0500, Arne Vajhøj wrote:

    C# is primarily for business applications.

    Never heard of it being used for anything important. For example,
    Microsoft would never use it itself in Office.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Thu Feb 1 02:49:13 2024
    On Wed, 31 Jan 2024 19:29:14 -0500, Arne Vajhøj wrote:

    That code would look a lot cleaner if the do while(false) loop got
    removed and the relevant breaks got replaced by goto's.

    Show us how you would do it. I can take you through my code step by step,
    block by block, if that will help.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to Dan Cross on Wed Jan 31 22:57:47 2024
    On 1/31/2024 8:26 PM, Dan Cross wrote:
    In article <upejl0$1nkl5$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    I've seen code that did all kinds of confusing things, just avoid a GoTo branch.
    My question is, why? If the need is a simple and rather easy to understand >> branch, why get complex,

    `goto` by itself is a sharp tool; sometimes incredibly useful,
    but dangerous if misused. Our industry is littered with example
    after example of `goto` misused. For instance, https://dwheeler.com/essays/apple-goto-fail.html

    Cars are dangerous, should we go back to horses?
    Horses are dangerous, should we go back to walking?
    Walking is dangerous ...

    Flying is dangerous ...
    Boats are dangerous ...

    Crossing the street is dangerous. But we're taught to look before stepping in front of the bus.

    GoTo can be dangerous ...
    Learn good programming habits ...


    That said, `goto` obviously _does_ have a place when used
    judiciously.

    Yes, that ...


    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to All on Wed Jan 31 23:00:35 2024
    On 1/31/2024 7:29 PM, Arne Vajhøj wrote:
    On 1/31/2024 6:21 PM, Lawrence D'Oliveiro wrote:
    On Wed, 31 Jan 2024 17:08:44 -0500, Arne Vajhøj wrote:

    On 1/31/2024 4:28 PM, Lawrence D'Oliveiro wrote:

    I have never written a goto in C code (not production code, anyway). These >>>> days, you need to do so much dynamic allocation, there is nearly always >>>> some need for cleanup when exiting an inner block anyway, so you can’t >>>> just jump directly somewhere else first. The overall pattern looks like >>>> this:

    MyPtr obj = NULL;
    do /*once*/
    {
    ... possible other stuff ...
    «allocate memory for obj»;
    if («error occurred»)
    break;
    ... possible other stuff using obj ...
    }
    while (false);
    free(obj);

    You can confirm, just by inspection, that there is no path out of the
    block that does not pass through the free() call precisely once.

    And the difference compared to:

    MyPtr obj = NULL;
    ... possible other stuff ...
    «allocate memory for obj»;
    if («error occurred»)
    goto lbl_freeobj;
    ... possible other stuff using obj ...
    lbl_freeobj:
    free(obj);

    are?

    Nesting.

    Goto work fine with nested loops. In fact it is one of the cases
    where it really makes sense.

    Try to scale up to something like

    static PyObject * discipline_makedict
    (
    PyObject * self,
    PyObject * args
    )
    {
    PyObject * result = NULL;
    PyObject * tempresult = NULL;
    br_PyObject * items;
    const br_char * msg = NULL;
    do /*once*/
    {
    const bool parsed_ok = PyArg_ParseTuple(args, "Os", &items, &msg); >> if (not parsed_ok)
    break;
    fprintf(stdout, "makedict says: “%s”\n", msg);
    if (not PyTuple_Check(items))
    {
    PyErr_SetString(PyExc_TypeError, "expecting a tuple");
    break;
    } /*if*/
    const ssize_t nr_items = PyTuple_Size(items);
    if (PyErr_Occurred())
    break;
    tempresult = PyDict_New();
    if (tempresult == NULL)
    break;
    for (ssize_t i = 0;;)
    {
    if (i == nr_items)
    break;
    br_PyObject * const item = PyTuple_GetItem(items, i);
    if (item == NULL)
    break;
    if (not PyTuple_Check(item) or PyTuple_Size(item) != 2)
    {
    PyErr_SetString(PyExc_TypeError, "expecting a 2-tuple");
    break;
    } /*if*/
    br_PyObject * const first = PyTuple_GetItem(item, 0);
    if (first == NULL)
    break;
    br_PyObject * const second = PyTuple_GetItem(item, 1);
    if (second == NULL)
    break;
    if (first == (PyObject *)&ExceptMe_type or second == (PyObject >> *)&ExceptMe_type)
    {
    PyErr_SetString(PyExc_ValueError, "ExceptMe object found"); >> break;
    } /*if*/
    if (PyDict_SetItem(tempresult, first, second) < 0)
    break;
    ++i;
    } /*for*/
    if (PyErr_Occurred())
    break;
    /* all done */
    result = tempresult;
    tempresult = NULL; /* so I don’t dispose of it yet */
    }
    while (false);
    Py_XDECREF(tempresult);
    return
    result;
    } /*discipline_makedict*/

    That code would look a lot cleaner if the do while(false) loop got
    removed and the relevant breaks got replaced by goto's.

    A well named goto label is much more informative than a plain break.

    More details here
    <https://gitlab.com/ldo/a_structured_discipline_of_programming/>.

    Truly bad design.

    All the code examples would look better with the do while(false) loops removed and appropriate goto's.

    Arne


    It's called do whatever to avoid a goto, and it can be very bad ...

    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Single Stage to Orbit@21:1/5 to Dave Froble on Thu Feb 1 08:43:12 2024
    On Wed, 2024-01-31 at 22:57 -0500, Dave Froble wrote:

    GoTo can be dangerous ...
    Learn good programming habits ...

    Linux uses goto in the kernel a lot. Should I throw it in the bin?
    --
    Tactical Nuclear Kittens

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to alex.buell@munted.eu on Thu Feb 1 13:04:13 2024
    In article <3c16a3a0f6100e01b49cf3de3d3411f051b23cab.camel@munted.eu>,
    Single Stage to Orbit <alex.buell@munted.eu> wrote:
    On Wed, 2024-01-31 at 22:57 -0500, Dave Froble wrote:

    GoTo can be dangerous ...
    Learn good programming habits ...

    Linux uses goto in the kernel a lot. Should I throw it in the bin?

    I see the point has gone over multiple people's heads, which
    probably means I did a poor job explaining. Like I said, `goto`
    *can* be useful. Does that mean we should use it in lieu of
    structued constructs like loops, when available? No.

    It's silly to deny that `goto` has been abused, leading to lots
    of very poor code. This is and was well-known. Rising to the
    defense of `goto` without acknowledging its faults is similarly
    silly.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to davef@tsoft-inc.com on Thu Feb 1 13:00:47 2024
    In article <upf4q6$1tp4r$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 1/31/2024 8:26 PM, Dan Cross wrote:
    In article <upejl0$1nkl5$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    I've seen code that did all kinds of confusing things, just avoid a GoTo branch.
    My question is, why? If the need is a simple and rather easy to understand
    branch, why get complex,

    `goto` by itself is a sharp tool; sometimes incredibly useful,
    but dangerous if misused. Our industry is littered with example
    after example of `goto` misused. For instance,
    https://dwheeler.com/essays/apple-goto-fail.html

    Cars are dangerous, should we go back to horses?

    I think the analogy is more like, "cars are dangerous, so should
    we get rid of seatbelts?" Or, "Takata made dangerous air bags,
    so what's the point of having them at all?"

    Horses are dangerous, should we go back to walking?
    Walking is dangerous ...

    Flying is dangerous ...
    Boats are dangerous ...

    Crossing the street is dangerous. But we're taught to look before stepping in >front of the bus.

    GoTo can be dangerous ...
    Learn good programming habits ...

    I wonder if you read the rest of my post which tried, perhaps
    imperfectly, to say more or less the same thing.

    That said, `goto` obviously _does_ have a place when used
    judiciously.

    Yes, that ...

    Just so.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Simon Clubley@21:1/5 to Dan Cross on Thu Feb 1 13:21:10 2024
    On 2024-01-31, Dan Cross <cross@spitfire.i.gajendra.net> wrote:

    I would argue this is more idiomatic, shorter, simpler, easier
    to both read and to reason about, and uses fewer variables.


    I agree and this is the general style I use, but with one difference.
    In my code, I always, always, use braces in an if() statement, even
    if the conditional code is only a single statement. For example:

    const bool parsed_ok = PyArg_ParseTuple(args, "Os", &items, &msg);
    if (!parsed_ok)
    {
    return NULL;
    }

    I think that makes it more clear and removes any possibility of future
    code changes accidentally not adding the braces at that time.

    [And yes, about the above indentation, Simon _is_ indeed a Whitesmiths
    person. :-)]

    Simon.

    --
    Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
    Walking destinations on a map are further away than they appear.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Simon Clubley@21:1/5 to Dave Froble on Thu Feb 1 13:24:46 2024
    On 2024-01-31, Dave Froble <davef@tsoft-inc.com> wrote:
    On 1/31/2024 8:26 PM, Dan Cross wrote:
    In article <upejl0$1nkl5$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    I've seen code that did all kinds of confusing things, just avoid a GoTo branch.
    My question is, why? If the need is a simple and rather easy to understand
    branch, why get complex,

    `goto` by itself is a sharp tool; sometimes incredibly useful,
    but dangerous if misused. Our industry is littered with example
    after example of `goto` misused. For instance,
    https://dwheeler.com/essays/apple-goto-fail.html

    Cars are dangerous, should we go back to horses?

    No, but we introduced safety measures based on experience.

    Horses are dangerous, should we go back to walking?

    No, but we introduced safety measures based on experience.

    Walking is dangerous ...

    We introduced safety measures based on experience (depending on
    the type of walking you are doing).


    Flying is dangerous ...

    We introduced safety measures based on experience.

    Boats are dangerous ...

    We introduced safety measures based on experience.


    GoTo can be dangerous ...
    Learn good programming habits ...


    We introduced safer alternatives based on experience.

    Simon.

    --
    Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
    Walking destinations on a map are further away than they appear.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to clubley@remove_me.eisner.decus.org- on Thu Feb 1 13:41:03 2024
    In article <upg5s6$2346b$1@dont-email.me>,
    Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
    On 2024-01-31, Dan Cross <cross@spitfire.i.gajendra.net> wrote:

    I would argue this is more idiomatic, shorter, simpler, easier
    to both read and to reason about, and uses fewer variables.


    I agree and this is the general style I use, but with one difference.
    In my code, I always, always, use braces in an if() statement, even
    if the conditional code is only a single statement. For example:

    const bool parsed_ok = PyArg_ParseTuple(args, "Os", &items, &msg);
    if (!parsed_ok)
    {
    return NULL;
    }

    I think that makes it more clear and removes any possibility of future
    code changes accidentally not adding the braces at that time.

    That's fine. Indeed, many modern languages mandate braces in
    around the bodies of conditionals and loops as part of the base
    syntax of the language (Go and Rust both do). I didn't bother
    because I only made the minimal changes to that crank's code.

    [And yes, about the above indentation, Simon _is_ indeed a Whitesmiths >person. :-)]

    From, Henry Spencer's, "The Ten Commandments for C Programmers":

    |8. Thou shalt make thy program's purpose and structure clear to
    |thy fellow man by using the One True Brace Style, even if thou
    |likest it not, for thy creativity is better used in solving
    |problems than in creating beautiful new impediments to
    |understanding.

    It is somewhat odd to me how contentious this is after so many
    years, but I kind of get how attached one can be to a particular
    code style. When I worked at Google, I thought the mandated
    style for C++ code was hideously ugly; after a few weeks, I
    stopped noticing. When `clang-format` came along, it was great
    because it essentially eliminated all of the stupid style things
    from reviews. Go and Rust (and other modern languages)
    effectively ended this as an issue by shipping with code
    formatters and making people use them.

    The bottom line for me, for C/C++ code, is that I don't care
    what style one uses, as long as one is consistent; it is
    shocking the extent to which divergent styles within a code base
    can increase cognitive load.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to ldo@nz.invalid on Thu Feb 1 13:18:31 2024
    In article <upf0r9$1t7cn$1@dont-email.me>,
    Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Wed, 31 Jan 2024 19:29:14 -0500, Arne Vajhøj wrote:

    That code would look a lot cleaner if the do while(false) loop got
    removed and the relevant breaks got replaced by goto's.

    Show us how you would do it. I can take you through my code step by step, >block by block, if that will help.

    As I posted in my other message (untested):

    #define PY_SSIZE_T_CLEAN
    #include <Python.h>
    #include <stdio.h>

    static PyObject *
    discipline_makedict(PyObject *self, PyObject *args)
    {
    PyObject *items;
    const char *msg = NULL;

    const int parsed_ok = PyArg_ParseTuple(args, "Os", &items, &msg);
    if (!parsed_ok)
    return NULL;

    printf("makedict says: \xe2\x80\x9c%s\xe2\x80\x9d\n", msg);
    if (!PyTuple_Check(items)) {
    PyErr_SetString(PyExc_TypeError, "expecting a tuple");
    return NULL;
    }
    const ssize_t nitems = PyTuple_Size(items);
    if (PyErr_Occurred())
    return NULL;

    PyObject *result = PyDict_New();
    if (result == NULL)
    return NULL;

    for (ssize_t i = 0; i < nitems; ++i) {
    PyObject *const item = PyTuple_GetItem(items, i);
    if (item == NULL)
    break;
    if (!PyTuple_Check(item) || PyTuple_Size(item) != 2) {
    PyErr_SetString(PyExc_TypeError, "expecting a 2-tuple");
    break;
    }
    PyObject *const first = PyTuple_GetItem(item, 0);
    if (first == NULL)
    break;
    PyObject *const second = PyTuple_GetItem(item, 1);
    if (second == NULL)
    break;
    if (first == (PyObject *)&ExceptMe_type || second == (PyObject *)&ExceptMe_type) {
    PyErr_SetString(PyExc_ValueError, "ExceptMe object found");
    break;
    }
    if (PyDict_SetItem(result, first, second) < 0)
    break;
    }

    if (PyErr_Occurred()) {
    Py_XDECREF(result);
    }

    return result;
    }

    No gotos, no simulated goto-via-early-break in a do/while(false)
    loop.

    As I said previously, this is more idiomatic, simpler, easier to
    reason about, easier to read, and uses fewer variables. Your
    initial code was, to be blunt, unreadable and truly awful shit.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Simon Clubley on Thu Feb 1 18:40:00 2024
    On 2/1/2024 8:21 AM, Simon Clubley wrote:
    On 2024-01-31, Dan Cross <cross@spitfire.i.gajendra.net> wrote:
    I would argue this is more idiomatic, shorter, simpler, easier
    to both read and to reason about, and uses fewer variables.

    I agree and this is the general style I use, but with one difference.
    In my code, I always, always, use braces in an if() statement, even
    if the conditional code is only a single statement. For example:

    const bool parsed_ok = PyArg_ParseTuple(args, "Os", &items, &msg);
    if (!parsed_ok)
    {
    return NULL;
    }

    I think that makes it more clear and removes any possibility of future
    code changes accidentally not adding the braces at that time.

    That is a common coding convention.

    Including the original SUN Java coding convention from 1999.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Thu Feb 1 23:59:49 2024
    On Thu, 1 Feb 2024 18:40:00 -0500, Arne Vajhøj wrote:

    const bool parsed_ok = PyArg_ParseTuple(args, "Os", &items, &msg);
    if (!parsed_ok)
    {
    return NULL;
    }

    That is a common coding convention.

    How do you handle nesting? Remember this part?

    if (PyDict_SetItem(tempresult, first, second) < 0)
    break;

    If you did a return instead at that point, it would leak memory.

    Note also the handover of ownership after all successful allocations, at
    the end of the block:

    } /*for*/
    if (PyErr_Occurred())
    break;
    /* all done */
    result = tempresult;
    tempresult = NULL; /* so I don’t dispose of it yet */

    This way, the cleanup at the end does not need to distinguish between
    success and failure returns:

    Py_XDECREF(tempresult);
    return
    result;

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Dorsey@21:1/5 to arne@vajhoej.dk on Fri Feb 2 01:44:41 2024
    =?UTF-8?Q?Arne_Vajh=C3=B8j?= <arne@vajhoej.dk> wrote:
    On 1/31/2024 11:17 AM, Scott Dorsey wrote:
    Michael S <already5chosen@yahoo.com> wrote:

    The third option, the one I like least (an understatement) is use of
    exceptions. Despite my personal preferences, it's quite popular.

    Exceptions can be very elegant or very inelegant... and it is entirely
    possible to have an exception that doesn't clean anything up at all and
    just exits and lets the operating system deal with the memory. On many
    systems this is a great idea because being able to exit quickly on a failure >> is more important than people give it credit for. On some other systems
    that have memory management issues it can lead to leakage.

    It is probably a bit easier to implement exceptions in languages
    with garbage collection and a lot easier for developers to avoid
    memory leak bugs.

    True, but "dispose of all memory belonging to this process" should not be
    a big deal on a demand-paged machine. There are some architectures where
    it can be, though.
    --scott

    --
    "C'est un Nagra. C'est suisse, et tres, tres precis."

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to Single Stage to Orbit on Thu Feb 1 21:43:42 2024
    On 2/1/2024 3:43 AM, Single Stage to Orbit wrote:
    On Wed, 2024-01-31 at 22:57 -0500, Dave Froble wrote:

    GoTo can be dangerous ...
    Learn good programming habits ...

    Linux uses goto in the kernel a lot. Should I throw it in the bin?


    Pitch it because it's Linux, not because of the goto

    :-)

    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Thu Feb 1 22:11:20 2024
    On 1/31/2024 9:50 PM, Lawrence D'Oliveiro wrote:
    On Wed, 31 Jan 2024 19:42:50 -0500, Arne Vajhøj wrote:
    C# is primarily for business applications.

    Never heard of it being used for anything important. For example,
    Microsoft would never use it itself in Office.

    It is correct that MS never rewrote MSO from C++ to C#.
    They did port VS to C# though.

    But C# is all over. Finance, e-commerce, government etc..

    The one C# app that I suspect that everyone here has used
    is Wikipedia search. Wikipedia choose to do their search
    using Lucene.NET instead of normal Lucene (Java based).

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Scott Dorsey on Thu Feb 1 21:29:57 2024
    On 2/1/2024 8:44 PM, Scott Dorsey wrote:
    =?UTF-8?Q?Arne_Vajh=C3=B8j?= <arne@vajhoej.dk> wrote:
    On 1/31/2024 11:17 AM, Scott Dorsey wrote:
    Michael S <already5chosen@yahoo.com> wrote:
    The third option, the one I like least (an understatement) is use of
    exceptions. Despite my personal preferences, it's quite popular.

    Exceptions can be very elegant or very inelegant... and it is entirely
    possible to have an exception that doesn't clean anything up at all and
    just exits and lets the operating system deal with the memory. On many
    systems this is a great idea because being able to exit quickly on a failure
    is more important than people give it credit for. On some other systems >>> that have memory management issues it can lead to leakage.

    It is probably a bit easier to implement exceptions in languages
    with garbage collection and a lot easier for developers to avoid
    memory leak bugs.

    True, but "dispose of all memory belonging to this process" should not be
    a big deal on a demand-paged machine. There are some architectures where
    it can be, though.

    The issue is not if the process goes away but if the process
    continue after execution flow has dropped back a number of levels
    on the call stack.

    The C++ code I posted did exit, but main could have called
    f1 again after catching the exception. Maybe doing it
    a billion times leaking one object for every call.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Thu Feb 1 21:49:56 2024
    On 1/31/2024 9:49 PM, Lawrence D'Oliveiro wrote:
    On Wed, 31 Jan 2024 19:29:14 -0500, Arne Vajhøj wrote:
    That code would look a lot cleaner if the do while(false) loop got
    removed and the relevant breaks got replaced by goto's.

    Show us how you would do it. I can take you through my code step by step, block by block, if that will help.

    It is pretty simple.

    do {
    allocate(o1);
    ...
    if(...) break;
    ...
    } while(false);
    deallocate(o1);

    can be done as:

    allocate(o1);
    ...
    if(...) goto cleanup;
    ...
    cleanup:
    deallocate(o1);

    The first piece of code is pretty bad as it confuses the
    reader by using a loop and the break is not very
    self documenting.

    The second piece of code is straight forward to read
    despite using goto.

    It gets even more clear in the nested case.

    do {
    allocate(o1);
    ...
    if(...) break;
    ...
    flag = FALSE;
    do {
    allocate(o2)
    ...
    if(...) {
    flag = TRUE;
    break;
    }
    ...
    }
    deallocate(o2)
    if(flag) break;
    ...
    } while(false);
    deallocate(o1);

    vs:

    allocate(o1);
    ...
    if(...) goto cleanup_1;
    ...
    allocate(o2);
    ...
    if(...) goto cleanup_1_and_2;
    ...
    cleanup_1_and_2:
    deallocate(o2);
    cleanup_1:
    deallocate(o1);

    The nested do while loop is a big mess. The goto solution
    is still simple.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dave Froble on Thu Feb 1 22:44:56 2024
    On 2/1/2024 10:38 PM, Dave Froble wrote:
    On 2/1/2024 9:49 PM, Arne Vajhøj wrote:
    It gets even more clear in the nested case.

        do {
            allocate(o1);
            ...
            if(...) break;
            ...
            flag = FALSE;
            do {
                allocate(o2)
                ...
                if(...) {
                    flag = TRUE;
                    break;
                }
                ...
            }
            deallocate(o2)
            if(flag) break;
            ...
        } while(false);
        deallocate(o1);

    vs:

        allocate(o1);
        ...
        if(...) goto cleanup_1;
        ...
        allocate(o2);
        ...
        if(...) goto cleanup_1_and_2;
        ...
    cleanup_1_and_2:
        deallocate(o2);
    cleanup_1:
        deallocate(o1);

    The nested do while loop is a big mess. The goto solution
    is still simple.

    Well, I'd use:

    Select <something>
        Case = "1"
            Some code
        Case = "2"
            Some other code
    End Select

    That code does something completely different.

    But even that can be abused.

    Got a friend that got carried away with Select and indenting.

    When the Select statements got nested a dozen times, and indents became
    8-10 tabs, and the code for each CASE was several pages long ...

    If the damn code was going to be so massive and complex, he should have
    just branched/performed/whatever to a separate place to do all that work.

    To quote from Linux kernel coding style doc:

    <quote>
    Now, some people will claim that having 8-character indentations makes
    the code move too far to the right, and makes it hard to read on a
    80-character terminal screen. The answer to that is that if you need
    more than 3 levels of indentation, you’re screwed anyway, and should fix
    your program.

    In short, 8-char indents make things easier to read, and have the added
    benefit of warning you when you’re nesting your functions too deep. Heed
    that warning.
    </quote>

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to All on Thu Feb 1 22:38:21 2024
    On 2/1/2024 9:49 PM, Arne Vajhøj wrote:
    On 1/31/2024 9:49 PM, Lawrence D'Oliveiro wrote:
    On Wed, 31 Jan 2024 19:29:14 -0500, Arne Vajhøj wrote:
    That code would look a lot cleaner if the do while(false) loop got
    removed and the relevant breaks got replaced by goto's.

    Show us how you would do it. I can take you through my code step by step,
    block by block, if that will help.

    It is pretty simple.

    do {
    allocate(o1);
    ...
    if(...) break;
    ...
    } while(false);
    deallocate(o1);

    can be done as:

    allocate(o1);
    ...
    if(...) goto cleanup;
    ...
    cleanup:
    deallocate(o1);

    The first piece of code is pretty bad as it confuses the
    reader by using a loop and the break is not very
    self documenting.

    The second piece of code is straight forward to read
    despite using goto.

    It gets even more clear in the nested case.

    do {
    allocate(o1);
    ...
    if(...) break;
    ...
    flag = FALSE;
    do {
    allocate(o2)
    ...
    if(...) {
    flag = TRUE;
    break;
    }
    ...
    }
    deallocate(o2)
    if(flag) break;
    ...
    } while(false);
    deallocate(o1);

    vs:

    allocate(o1);
    ...
    if(...) goto cleanup_1;
    ...
    allocate(o2);
    ...
    if(...) goto cleanup_1_and_2;
    ...
    cleanup_1_and_2:
    deallocate(o2);
    cleanup_1:
    deallocate(o1);

    The nested do while loop is a big mess. The goto solution
    is still simple.

    Arne


    Well, I'd use:

    Select <something>
    Case = "1"
    Some code
    Case = "2"
    Some other code
    End Select

    No need for the dreaded GoTo statement ...

    But even that can be abused.

    Got a friend that got carried away with Select and indenting.

    When the Select statements got nested a dozen times, and indents became 8-10 tabs, and the code for each CASE was several pages long ...

    If the damn code was going to be so massive and complex, he should have just branched/performed/whatever to a separate place to do all that work.


    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Fri Feb 2 04:50:22 2024
    On Thu, 1 Feb 2024 21:49:56 -0500, Arne Vajhøj wrote:

    The nested do while loop is a big mess.

    Looks like you are adding a whole lot more lines of code in the form of
    jumps and places to jump to, and flags to control what to do when you get there. Adding a bit of a combinatorial explosion in possible cases that
    have to be verified somehow.

    In short, you are making a bigger mess.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Fri Feb 2 04:51:01 2024
    On Thu, 1 Feb 2024 22:44:56 -0500, Arne Vajhøj wrote:

    To quote from Linux kernel coding style doc:

    <quote>
    Now, some people will claim that having 8-character indentations makes
    the code move too far to the right, and makes it hard to read on a 80-character terminal screen. The answer to that is that if you need
    more than 3 levels of indentation, you’re screwed anyway, and should fix your program.

    I think this is a load of nonsense.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Fri Feb 2 04:48:28 2024
    On Thu, 1 Feb 2024 22:11:20 -0500, Arne Vajhøj wrote:

    On 1/31/2024 9:50 PM, Lawrence D'Oliveiro wrote:

    On Wed, 31 Jan 2024 19:42:50 -0500, Arne Vajhøj wrote:

    C# is primarily for business applications.

    Never heard of it being used for anything important. For example,
    Microsoft would never use it itself in Office.

    It is correct that MS never rewrote MSO from C++ to C#.
    They did port VS to C# though.

    Maybe, but VS Code takes an entirely different tack, using Electron (the Chromium engine + TypeScript/JavaScript) instead. Wonder why?

    But C# is all over. Finance, e-commerce, government etc..

    All that stuff that’s now in the cloud?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Single Stage to Orbit@21:1/5 to Dave Froble on Fri Feb 2 10:36:47 2024
    On Thu, 2024-02-01 at 21:43 -0500, Dave Froble wrote:
    GoTo can be dangerous ...
    Learn good programming habits ...

    Linux uses goto in the kernel a lot. Should I throw it in the bin?


    Pitch it because it's Linux, not because of the goto

    Oo them's flammable words. :-D
    --
    Tactical Nuclear Kittens

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to All on Fri Feb 2 07:42:22 2024
    On 2/2/2024 7:38 AM, Arne Vajhøj wrote:
    On 2/1/2024 11:48 PM, Lawrence D'Oliveiro wrote:
    On Thu, 1 Feb 2024 22:11:20 -0500, Arne Vajhøj wrote:
    It is correct that MS never rewrote MSO from C++ to C#.
    They did port VS to C# though.

    Maybe, but VS Code takes an entirely different tack, using Electron (the
    Chromium engine + TypeScript/JavaScript) instead. Wonder why?

    VSC was intended to compete with Atom on Windows/Linux/macOS. VSC
    was released before .NET Core. So MS did not have much of a choice.

    Correction: they had lots of choices, but C# was just not one of them.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Fri Feb 2 07:38:14 2024
    On 2/1/2024 11:48 PM, Lawrence D'Oliveiro wrote:
    On Thu, 1 Feb 2024 22:11:20 -0500, Arne Vajhøj wrote:

    On 1/31/2024 9:50 PM, Lawrence D'Oliveiro wrote:

    On Wed, 31 Jan 2024 19:42:50 -0500, Arne Vajhøj wrote:

    C# is primarily for business applications.

    Never heard of it being used for anything important. For example,
    Microsoft would never use it itself in Office.

    It is correct that MS never rewrote MSO from C++ to C#.
    They did port VS to C# though.

    Maybe, but VS Code takes an entirely different tack, using Electron (the Chromium engine + TypeScript/JavaScript) instead. Wonder why?

    VSC was intended to compete with Atom on Windows/Linux/macOS. VSC
    was released before .NET Core. So MS did not have much of a choice.

    But C# is all over. Finance, e-commerce, government etc..

    All that stuff that’s now in the cloud?

    A lot of it.

    But C# does not care if if the hardware it runs on is
    bought or rented.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Fri Feb 2 07:56:33 2024
    On 2/1/2024 11:51 PM, Lawrence D'Oliveiro wrote:
    On Thu, 1 Feb 2024 22:44:56 -0500, Arne Vajhøj wrote:
    To quote from Linux kernel coding style doc:

    <quote>
    Now, some people will claim that having 8-character indentations makes
    the code move too far to the right, and makes it hard to read on a
    80-character terminal screen. The answer to that is that if you need
    more than 3 levels of indentation, you’re screwed anyway, and should fix >> your program.

    I think this is a load of nonsense.

    Apparently Linus doesn't think so.

    And while few may have worded is this blunt, then it is
    generally accepted that deep nesting is a code smell and
    should be refactored and code moved out to functions/methods.

    The specifics may depend a little on the language. 3 may
    make sense in C, but VB.NET may justify a higher value
    (namespace and class add levels before even getting started
    and try catch blocks plus using statements also tend to
    add more levels without the levels impacting flow).

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to ldo@nz.invalid on Fri Feb 2 13:49:57 2024
    In article <uphsad$2fg0v$3@dont-email.me>,
    Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Thu, 1 Feb 2024 21:49:56 -0500, Arne Vajhøj wrote:

    The nested do while loop is a big mess.

    Looks like you are adding a whole lot more lines of code in the form of
    jumps and places to jump to, and flags to control what to do when you get >there. Adding a bit of a combinatorial explosion in possible cases that
    have to be verified somehow.

    In short, you are making a bigger mess.

    Again, for this example, the code needs neither goto nor
    the abstruse loop structure you wrote. See my earlier
    post for details.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Fri Feb 2 08:44:00 2024
    On 2/1/2024 11:50 PM, Lawrence D'Oliveiro wrote:
    On Thu, 1 Feb 2024 21:49:56 -0500, Arne Vajhøj wrote:
    The nested do while loop is a big mess.

    Looks like you are adding a whole lot more lines of code in the form of
    jumps and places to jump to, and flags to control what to do when you get there. Adding a bit of a combinatorial explosion in possible cases that
    have to be verified somehow.

    I "added" lines so that the total number of lines "increased" from
    7 to 6 in the one-level example and from 20 to 12 in the two-level
    example.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dan Cross on Fri Feb 2 08:56:06 2024
    On 2/2/2024 8:49 AM, Dan Cross wrote:
    In article <uphsad$2fg0v$3@dont-email.me>,
    Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Thu, 1 Feb 2024 21:49:56 -0500, Arne Vajhøj wrote:
    The nested do while loop is a big mess.

    Looks like you are adding a whole lot more lines of code in the form of
    jumps and places to jump to, and flags to control what to do when you get
    there. Adding a bit of a combinatorial explosion in possible cases that
    have to be verified somehow.

    In short, you are making a bigger mess.

    Again, for this example, the code needs neither goto nor
    the abstruse loop structure you wrote. See my earlier
    post for details.

    He cut so much that the context was not obvious.

    But his post was a reply to my post with generic
    ... blocks.

    It is true the first specific example he provided
    did not need to solve this problem if it was
    restructured a little.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Fri Feb 2 15:30:01 2024
    In article <upis9l$2kald$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 2/2/2024 8:49 AM, Dan Cross wrote:
    In article <uphsad$2fg0v$3@dont-email.me>,
    Lawrence D'Oliveiro <ldo@nz.invalid> wrote:
    On Thu, 1 Feb 2024 21:49:56 -0500, Arne Vajhøj wrote:
    The nested do while loop is a big mess.

    Looks like you are adding a whole lot more lines of code in the form of
    jumps and places to jump to, and flags to control what to do when you get >>> there. Adding a bit of a combinatorial explosion in possible cases that
    have to be verified somehow.

    In short, you are making a bigger mess.

    Again, for this example, the code needs neither goto nor
    the abstruse loop structure you wrote. See my earlier
    post for details.

    He cut so much that the context was not obvious.

    But his post was a reply to my post with generic
    ... blocks.

    This seems to be his MO: when presented with an
    argument that disconfirms one of his preconceptions,
    ignore it and respond to something else, usually
    a strawman of his own creation.

    It is true the first specific example he provided
    did not need to solve this problem if it was
    restructured a little.

    Yes. I suspect most of his code similarly.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stephen Hoffman@21:1/5 to Lawrence D'Oliveiro on Fri Feb 2 16:43:15 2024
    On 2024-01-31 21:22:33 +0000, Lawrence D'Oliveiro said:

    On Wed, 31 Jan 2024 11:05:22 -0500, Stephen Hoffman wrote:

    (Not that I prefer to have to implement manual cleanup, much as I'd
    like to avoid explicitly deallocating memory in C.

    Note that free(3) is defined as idempotent; freeing a NULL pointer is a harmless no-op. That simplifies things a lot.

    Pragmatically, the difference between (pseudo-code) free(xyz) where xyz
    is nulllptr or ((void*)0) or whatever, and the same brute-force if
    (xyz) free(xyz); code, or a macro of same, is negligible.

    No, that free ignores a null doesn't simplify the bookkeeping. There
    are other languages that are easier here.

    Though semi-similarly, sending a null at a method in Objective C can be
    useful. And can be a source of confusion and bugs.

    On OpenVMS, using VM zones reduces the memory management bookkeeping in
    some contexts, as the whole zone can be freed in one shot. This
    technique can be handy for command parsers, where you know you're done
    with ~everything parsing-related when you're parsing the next command.

    There are other trade-offs that can make this effort easier, not the
    least of which is garbage collection.

    Apropos of nothing, asctime() and ctime() are now (C23) deprecated.

    And some semi-related reading: https://jorengarenar.github.io/blog/less-known-c


    --
    Pure Personal Opinion | HoffmanLabs LLC

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Dorsey@21:1/5 to arne@vajhoej.dk on Sat Feb 3 01:23:27 2024
    In article <uphk35$2akla$1@dont-email.me>,
    =?UTF-8?Q?Arne_Vajh=C3=B8j?= <arne@vajhoej.dk> wrote:
    On 2/1/2024 8:44 PM, Scott Dorsey wrote:
    =?UTF-8?Q?Arne_Vajh=C3=B8j?= <arne@vajhoej.dk> wrote:
    On 1/31/2024 11:17 AM, Scott Dorsey wrote:
    Michael S <already5chosen@yahoo.com> wrote:
    The third option, the one I like least (an understatement) is use of >>>>> exceptions. Despite my personal preferences, it's quite popular.

    Exceptions can be very elegant or very inelegant... and it is entirely >>>> possible to have an exception that doesn't clean anything up at all and >>>> just exits and lets the operating system deal with the memory. On many >>>> systems this is a great idea because being able to exit quickly on a failure
    is more important than people give it credit for. On some other systems >>>> that have memory management issues it can lead to leakage.

    It is probably a bit easier to implement exceptions in languages
    with garbage collection and a lot easier for developers to avoid
    memory leak bugs.

    True, but "dispose of all memory belonging to this process" should not be
    a big deal on a demand-paged machine. There are some architectures where
    it can be, though.

    The issue is not if the process goes away but if the process
    continue after execution flow has dropped back a number of levels
    on the call stack.

    Yes, but that's a different problem. I'm talking about an "abort and get
    the hell out of there" routine.
    --scott

    --
    "C'est un Nagra. C'est suisse, et tres, tres precis."

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Stephen Hoffman on Sat Feb 3 01:48:30 2024
    On Fri, 2 Feb 2024 16:43:15 -0500, Stephen Hoffman wrote:

    No, that free ignores a null doesn't simplify the bookkeeping.

    It does though, in the code example I have posted elsewhere. You can just
    put a sequence of unconditional free(3) calls, which is much shorter than useless things like

    if (ptr)
    free(ptr);

    which I see all too often.

    By the way, the C++ “delete” statement is similarly specified to treat an attempt to dispose of a NULL pointer as a harmless no-op.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Andreas Eder@21:1/5 to bill on Sat Feb 3 18:26:38 2024
    On Di 30 Jan 2024 at 11:45, bill <bill.gunshannon@gmail.com> wrote:

    On 1/29/2024 7:50 PM, kludge@panix.com wrote:
    =?UTF-8?Q?Arne_Vajh=C3=B8j?= <arne@vajhoej.dk> wrote:
    The code is VB6.

    But none of the problems are Basic specific. It is possible
    to write the same bad code in C or Fortran or whatever.

    So it just shows that there are some really really bad programmers out
    there.
    I have worked with people who could write spaghetti Fortran in any
    programming language available. Did you know that LISP has a goto?
    It does.

    PS: Good compilers may have detected the unreachable code. But it
    is still good vs bad compiler not good vs bad language.
    The exciting part is when they tell you not to remove the unreachable
    code,
    because the program crashes at runtime when you do that.

    Many moons ago I had to try to fix a number of programs that
    crashed whenever run. Back in those days a common method was
    to add statements to display variables during execution. I
    had many cases where adding those statements made the program
    work.

    bill

    So it was a Heisenbug :-)

    'Andreas

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Sun Feb 4 22:51:30 2024
    On Fri, 2 Feb 2024 07:38:14 -0500, Arne Vajhøj wrote:

    On 2/1/2024 11:48 PM, Lawrence D'Oliveiro wrote:

    On Thu, 1 Feb 2024 22:11:20 -0500, Arne Vajhøj wrote:

    But C# is all over. Finance, e-commerce, government etc..

    All that stuff that’s now in the cloud?

    A lot of it.

    But C# does not care if if the hardware it runs on is bought or rented.

    Looks like Microsoft now wants to get rid of at least some of its own C#
    code. It is looking for developers to convert it to Rust.

    Not exactly a vote of confidence in the future of C#/Dotnet, is it?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Mon Feb 5 23:25:26 2024
    On Fri, 2 Feb 2024 07:56:33 -0500, Arne Vajhøj wrote:

    On 2/1/2024 11:51 PM, Lawrence D'Oliveiro wrote:
    On Thu, 1 Feb 2024 22:44:56 -0500, Arne Vajhøj wrote:
    To quote from Linux kernel coding style doc:

    <quote>
    Now, some people will claim that having 8-character indentations makes
    the code move too far to the right, and makes it hard to read on a
    80-character terminal screen. The answer to that is that if you need
    more than 3 levels of indentation, you’re screwed anyway, and should
    fix your program.

    I think this is a load of nonsense.

    Apparently Linus doesn't think so.

    I know he doesn’t.

    And while few may have worded is this blunt, then it is generally
    accepted that deep nesting is a code smell and should be refactored and
    code moved out to functions/methods.

    I do deep nesting all the time. This one goes 8 levels deep.

    (defun prev_less_indent (count)
    "moves to the last prior line with a lesser indentation level."
    (interactive "p")
    (loop break
    (back-to-indentation)
    (let
    (
    (indent_end (point))
    indent_amt
    line_start
    )
    (beginning-of-line)
    (cond
    ((> indent_end (point))
    (setq indent_amt (- indent_end (point) 1))
    (unless
    (loop done
    (when (= (point) (point-min))
    (ding)
    (done nil)
    ) ; when
    (previous-logical-line)
    (beginning-of-line)
    (setq line_start (point))
    (end-of-line)
    (when (/= line_start (point)) ; skip over empty lines
    (back-to-indentation)
    (setq indent_end (point))
    (beginning-of-line)
    (when (< (- indent_end (point)) indent_amt)
    (done t)
    ) ; when
    ) ; when
    ) ; loop
    (break)
    ) ; unless
    )
    (t ; on line with no leading whitespace
    (ding)
    (break)
    )
    ) ; cond
    ) ; let
    (setq count (- count 1))
    (when (<= count 0)
    (break)
    ) ; when
    ) ; loop
    (back-to-indentation)
    ) ; prev_less_indent

    Feel free to show us how it should be “refactored and code moved out
    to functions/methods”.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Mon Feb 5 23:20:29 2024
    On Fri, 2 Feb 2024 08:44:00 -0500, Arne Vajhøj wrote:

    On 2/1/2024 11:50 PM, Lawrence D'Oliveiro wrote:

    On Thu, 1 Feb 2024 21:49:56 -0500, Arne Vajhøj wrote:

    The nested do while loop is a big mess.

    Looks like you are adding a whole lot more lines of code in the form of
    jumps and places to jump to, and flags to control what to do when you
    get there. Adding a bit of a combinatorial explosion in possible cases
    that have to be verified somehow.

    I "added" lines so that the total number of lines "increased" from 7 to
    6 in the one-level example and from 20 to 12 in the two-level example.

    Fine. Now put it all together into a finished example, and show us how it looks.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Dave Froble on Sun Feb 18 21:16:54 2024
    On Wed, 31 Jan 2024 13:27:57 -0500, Dave Froble wrote:

    Final cleanup, if required, and exit the program.

    If the program is exiting, a lot of the leftover cleanup (e.g. memory deallocation) becomes unnecessary.

    Knew a guy that would us a gosub to go to the END statement. Drove me
    nuts.

    Did it have a comment next to it saying “I’ll be back!”?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Dave Froble on Sun Feb 18 21:19:20 2024
    On Wed, 31 Jan 2024 22:57:47 -0500, Dave Froble wrote:

    Cars are dangerous, should we go back to horses?

    Fun fact: according to drug expert David Nutt, horse-riding is about as dangerous as taking Ecstasy.

    Do horses have seatbelts and crumple zones yet?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)