comp.lang.ada
 help / color / mirror / Atom feed
* GOTO considered necessary (reworked)
@ 1997-06-11  0:00 Samuel Mize
  1997-06-11  0:00 ` Bryce Bardin
                   ` (4 more replies)
  0 siblings, 5 replies; 63+ messages in thread
From: Samuel Mize @ 1997-06-11  0:00 UTC (permalink / raw)




Greetings,

[-------------------------------------------------------------------]
[ I'm re-doing this since a lot of people were apparently at an Ada ]
[ conference recently, and weren't reading net news.  This version  ]
[ is updated based on previous comments.  -- Mize                   ]
[-------------------------------------------------------------------]

I'm rebeating a dead horse, in order to write up a consensus paper to
submit to adahome.  I'll appreciate your input.

This one concerns use of "goto" statements.

I have scanned through the back c.l.a messages in DejaNews.  I request
your comments on this summary.

Samuel Mize

                        USE OF "GOTO" IN ADA
                        --------------------

1.0 SUMMARY:
------------

a) In general, "goto" statements should be avoided.  They create confusing
   execution flow structures -- at first, or after a few maintenance changes.
   They also reduce opportunities for compiler optimization of code.

b) As a rule of thumb, if your code needs a "goto" to work efficiently
   (or at all), you may have overlooked a simpler, better design.

c) Exceptions to "goto" avoidance:

   c1) "Goto"s can be used to create a well-defined code structure that is
       not supported in the language.  Examples are in Section 2.0.

   c2) "Goto"s are acceptable in machine-generated code, IF a human is
       NEVER expected to read the code.  (For example, a module generated
       by a tool from data-flow diagrams.)

   c3) Finite State Machines (FMSs) are often implemented with "goto"s.
       These are also called Finite State Automatons (FSAs).  This is
       discussed in detail in Section 3.0.  These are used in compiler
       theory, business processes, command and control, ASIC or other
       custom chips.

   c4) Other usages are suspect, but may be OK.  If a "goto" really
       improves clarity, use it -- but document WHY you used it, and
       why other approaches were found lacking.  Look at your design at
       a higher level to see if you can eliminate "goto" usage with a
       clearer design approach -- the advantage here, of course, is not
       the mechanical elimination of the "goto", but the clearer design.
       See section 4.0, and the example in section 5.0.

d) Eliminating a "goto" may prevent maintenance errors in the future (for
   instance, code being put on the wrong side of a label).  However, it also
   may not be worth the effort to redesign without the "goto."  Using an
   extraneous state variable or other kludge is no improvement on a "goto".

e) Norm Cohen recommended Knuth's article in the December 1974 Computing
   Surveys as "the best discussion I've ever seen of the goto issue."
   Other respected Ada developers have concurred.

f) The shared Ada culture avoids "goto" statements.  Gellerich et al examined
   34428 files containing 8.5 million lines of code, coded by many projects,
   institutions, and programmers.  They found a "goto" density of 1 "goto" per
   13614 lines of code.  They excluded some directly-translated Fortran, and
   some code written to validate Ada compilers (which must test "goto").
   ["Where does GOTO go to?", Gellerich Kosiol and Erhard, U of Stuttgart,
   http://www.informatik.uni-stuttgart.de/ifi/ps/Gellerich/publications.html]


2.0 UNSUPPORTED CODE STRUCTURES
-------------------------------
The central feature of structured programming is not some specific set
of code structures, but the fact that well-defined structures are used
to organize the code.  Arbitrary "goto"s are avoided; transfers of
control occur as part of a larger, coherent structure that helps the
reader understand the overall program's activity.

Modern languages like Ada provide a large set of useful structures: "if"
statements (supporting "then", "elsif", and "else" clauses), "case"
statements, "while" and "for" loops, etc.

However, there are some useful structures that are not directly supported.
This will always be true.  Some of these structures are rarely used, so
are not worth the cost to add into the compiler; others may be invented,
or may be domain-specific.

It is generally acceptable to use a "goto" to implement a well-defined
code structure that is not directly implemented in the language.

For instance, the Ada gurus at ACT use "goto" in the GNAT compiler.  On the
other hand, it occurs in only 3 places (in 3.07), and all are instances of
the "not-found" pattern shown below.

Many recommend using "flag" comments to identify jumps that are not part of
a structure.  This includes "return" and "exit" statements, as well as "goto"
statements.  Thus, a loop might look like:

   loop
      ...
      exit when A; -------------------EXIT
      ...
      if B then
         return; ---------------------RETURN
      ...
      if C then
         goto CONTINUE; --------------GOTO
      ...
      <<CONTINUE>>
   end loop;

For example, here are three structures that require "goto" in Ada:

a) Process continuation logic

   A sequential process may have several natural completion points.  One
   example is parsing a string that ends with optional items.  Avoiding
   "goto" in this case requires increasing levels of "if" indentation:

      [process first part of string]
      if [not end-of-line] then
         [process option1]

         if [not end-of-line] then
            [process option2]

            if [not end-of-line] then
               [process option3]

               if [not end-of-line] then
                  [process option4]
                   ...
               endif;
            endif;
         endif;
      endif;

   This is hard to read, and confusing since all the parsing is really at
   the same logical level.  A "completed" flag may also be used, but this
   does not usually improve clarity over the "goto" solution:

      [process first part of string]
      if [end-of-line] then
         goto NO_MORE_OPTIONS;
      end if;

      [process option1]
      if [end-of-line] then
         goto NO_MORE_OPTIONS;
      end if;

      [process option2]
      if [end-of-line] then
         goto NO_MORE_OPTIONS;
      end if;

      [process option3]
      if [end-of-line] then
         goto NO_MORE_OPTIONS;
      end if;
      [process option4]
      ...
      <<NO_MORE_OPTIONS>>

   The same effect can be achieved by putting the processing sequence into a
   block statement and raising an exception on end-of-line.  However, this
   is generally considered even worse than the "goto" solution.  Most
   standards limit exceptions to error conditions, not normal processing.

b) "Continue" loop logic

   The "continue" function of C has to be emulated in Ada with a "goto":

      loop
        ...
        goto <<CONTINUE>>
        ...
        <<CONTINUE>>
      end loop;

   This is a special case of the process continuation structure.

c) "Not-Found" loop logic

   Loops frequently scan through a sequence -- for instance, an array --
   followed by special processing if the item was not found.  An example
   would be inserting an item in an ordered array:

      Items: array (Positive range Lo .. Hi) of Item;
      Last_Item: Natural := Items'First - 1;
      ...
      -- for each item to be inserted

         for I in Items'First .. Last_Item loop
            -- duplicates are allowed, and inserted as separate items
            if Items (I) >= New_Item then
               Items (I + 1 .. Last_Item + 1) := Items (I .. Last_Item);
               Items (I) := New_Item;
               goto ITEM_INSERTED;
            end if;
         end loop;

         -- New_Item's place not found before end of array
         Last_Item := Last_Item + 1;
         Items (Last_Item) := Item;

         <<ITEM_INSERTED>>
         ...

   Avoiding "goto" in this case requires one of these approaches:

    - A "found" boolean.  When element is processed in loop, Found is set
      and loop exits.  No-element processing is skipped when Found is true.

    - An "Index" variable, initially set past the end of the array, and reset
      in the loop if the element is found.  Processing is always done after
      loop exit, based on this index.

    - Last-iteration detection in the loop.

    Each of these is also unclear in its own way.


3.0 FINITE STATE MACHINES (FSMs)
--------------------------------
An FSM is defined by a set of states.  In each state, some processing may
occur; then the abstract "machine" selects a state to transition into (this
may be the same state again).

Some developers find that "goto"s improve FSM clarity, as they more directly
reflect the FSM being modelled.  Other developers prefer a case statement
inside a loop.

The "goto" implementation generally looks like:


    <<State_1>> -- A label like this exists for each state of the machine.
       declare
          [local variables]
       begin
          [processing for state 1]

          if [condition] then        -- A variable holding the "current"
             goto [State_X];         -- state is not needed -- it is
          elsif [condition] then     -- represented by the current place
             goto [State_Y];         -- of executiion.
          else
             goto [State_Z];
          end if;
       end;

       -- Defensive programming: ensures that the machine does
       -- not accidentally "fall through" to the next state.
       raise No_Transition_Occurred; 
                                       
    <<State2>>
       ...

The "loop-and-case" alternative would be:

    type State is (Initial_State, State1, ... Staten);
    Current_State: State;
   
    -- variables that may affect the next transition
    ...

    function Next_State (Current_State: State) return State;
   
    loop
       exit when
         (Current_State = [a terminal state])
         or 
         (Current_State = [another terminal state])
             ...;
   
       -------------------------------------------------------- AAA

       case Current_State is
          when State_1 =>
             [Processing for state 1]
             Current_State := Next_State (Current_State);
          ...
       end case;

       if Debug then
          Text_Io.Put_Line (State'Image (Current_State)); ----- BBB
       end if;

    end loop;

Next_State can use an if/elsif cascade, or an array or hash-table lookup,
or whatever is appropriate for the application-specific transition table.

Different developers will argue for the clarity of either approach.

Aside from clarity, the "goto" design has these advantages:

a) The transition logic is separate from the processing logic for each state.
   This may be good or bad, depending on how distinct these naturally are.
   If they are naturally separate, having transition logic gathered into a
   separate function is clearer.  If they are intertwined, the transition
   function will duplicate much of the logic from the processing.

b) It is more efficient.  Instead of looping and and evaluating a case
   expression, it jumps directly to the next state.

c) It may be easier to locate accidentally "killed" states: a
   cross-reference tool could identify unused statement labels.

Aside from clarity, the "loop-and-case" design has these advantages:

a) The transition logic is separate from the processing logic for each state.

b) There is a place to put processing that must occur at the start or end of
   each state (note lines AAA and BBB).

c) The possible states are listed in an enumeration, usable for I/O or to
   represent a "memory" of previous states, if needed.

Adding or deleting a state is about equally hard for both designs.  It is
harder with the case structure because you have to edit in two locations,
keeping the type definition and the case structure synchronized.  It is
harder with the "goto" structure because the logic that jumps to the new
(or deleted) state is less localized -- you have to hunt through all the
code for the "goto"s.  This seems to be a wash.

The final decision must be made by the developer, according to clarity or
other advantages for the specific application, within the constraints of
the project and the overall design.


4.0 IMPROVING A "GOTO"-BASED DESIGN
---------------------------------
The existence of "goto"s in code creates some purely mechanical problems for
maintenance programmers.  New code may be added on the wrong side of a "goto"
target, and "goto"-based structures are often harder to maintain when
intervening code changes significantly.  This creates a small but definite
advantage to eliminating many "goto" statements.

However, once a "goto"-based design has been coded, it may not be worth the
effort to redesign it to eliminate the "goto."  This is especially the case
if the "goto" is close to its target, and it is unlikely that other code
would be inserted between them.

In many cases, use of a "goto" indicates that a clearer, simpler design may
be available.  This is especially the case if the "goto" is not part of a
clearly-defined design structure.  The advantage to eliminating THESE "goto"
statements is not the mechanical elimination of a "goto", but the clearer
design that results.

Extraneous state variables or other unclear design kludges do not improve on
a "goto".  If there is no overall design improvement that replaces a "goto"
with a cleaner structure, you may as well leave the "goto".  For instance,
the code in section 5.0 would not be improved by mechanically replacing the
"goto" by adding a "Done" boolean or some other kludge -- this would simply
trade one unclear design for another.

The critical point is that a program should be built in discrete sections,
each of which accomplishes a clear task.  These sections should be defined
and separated by control-flow structures that show their relationship.  This
lets you (or a later maintenance programmer) define clearly in what state the
program will be when it reaches a given point, and reason about what the
section of code is supposed to be doing.  Formally defined approaches to this
kind of design are called "structured programming."

For instance, you should be able to say what a loop does each iteration, and
what it has done once it exits.  (If you like semi-mathematical jargon, it
needs an invariant and a termination condition).

So, IF (1) it's worth the effort to review a "goto"-based design, and
(2) the code can be reorganized into a clearer structure, then you should
do so to eliminate the "goto".  If a "goto" is needed to create the
appropriate structure for your code, use it -- and document WHY you used it.

The best approach to eliminating "goto" from your code is to write code in
the first place that divides the task into logical chunks, organized by
simple control structures.  If you design your overall approach carefully,
you will only use "goto" when it really does improve your code.

5.0 EXAMPLE OF "GOTO"-REDUCING DESIGN IMPROVEMENT
-----------------------------------------------
Some code was posted to the net (quoting an example by Knuth) as one example
of a "goto" being a reasonable design decision.  It appears at first to be an
example of "not-found" loop logic.  However, a little more analysis reveals a
non-"goto" design that is clearer.

Again, the advantage to eliminating these "goto" statements is not the
mechanical elimination of a "goto", but the clearer design that results.

The code as given (with minor corrections) was: - - - - - - - - - - - - -

   type Node_Type;

   type Tree_Type is access Node_Type;

   type Node_Type is
      record
         Count       : Natural := 0;
         Left, Right : Tree_Type;
      end record;

   type Bit_Vector_Index is Natural range 0 .. Natural'Last - 1;
   type Bit_Vector_Type is array (Bit_Vector_Index) of Boolean;

   type Bit_Vector_Pointer_Type is access Bit_Vector_Type;

   Root : Tree_Type := new Node_Type;
   BV   : Bit_Vector_Pointer_Type;
   Bit  : Bit_Vector_Index;

-- BV points to a bit vector describing a path (False = left, True = right)
-- through the tree pointed to by Root.  We are counting the number of times
-- a given bit vector is encountered in the Count component of the
-- corresponding tree node.  Root starts out pointing to a tree consisting
-- only of a root node, and new nodes are added to the tree as needed.  The
-- loop below has three exits, and the actions appropriate when one of the
-- exits is taken is different from the actions appropriate when the other
-- two are taken, so a goto comes in handy.  Here's the code:

      Node := Root;
      Bit := BV'First;
      loop
         if Bit > BV'Last then
            goto Increment;
         end if;
         if BV(Bit) then
            if Node.Left = null then
               Node.Left := new Node;
               Node := Node.Left;
               exit;
            else
               Node := Node.Left;
            end if;
         else
            if Node.Right = null then
               Node.Right := new Node;
               Node := Node.Right;
               exit;
            else
               Node := Node.Right;
            end if;
         end if;
         Bit := Bit + 1;
      end loop;

      -- We've reached a leaf.  Read the rest of BV.all while extending
      --    the tree along the corresponding path only.
      for I in Bit+1 .. BV'Last loop
         if BV(I) then
            Node.Left := new Node;
            Node := Node.Left;
         else
            Node.Right := new Node;
            Node := Node.Right;
         end if;
      end loop;

   <<Increment>>
      Node.Count := Node.Count + 1;


It would be clearer to just let the first loop do all the work.  Eliminate
the "exit" statements and turn it into a "for" loop over the array bounds.
This works, but it checks for "null" in nodes that were just created.  If
this makes a significant performance difference for your application, you can
hand-optimize the code.  (The compiler probably can't do this optimization.)

First, we could simply replace the "goto" with an exit statement.  The loop
parameter specification would compute a null range and skip the loop.

The end processing could also be enclosed in an "if" statement to skip it if
the entire boolean array were processed.

However, this would still be less readable, since nodes are created inside
two different loops.  Instead, let's use two clearly-defined loops:

    -- Move to the last existing node on the path
    FOR all existing nodes on path
        move to node

    -- Create any new nodes
    FOR all new nodes on path
        create the node

The new code is: - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

     -- Declarations the same
   begin

      Node := Root;
      Bit := BV'First;

      ---------------------------------------------
      -- Move to the connect-node for the first  --
      -- node that needs to be created (if any). --
      ---------------------------------------------
      -- We are manually simulating a "for" loop to
      -- retain the index after loop termination.
      loop
         exit when Bit > BV'Last;

         if BV(Bit) then
            if Node.Left = null then
               exit;
            else
               Node := Node.Left;
            end if;
         else
            if Node.Right = null then
               exit;
            else
               Node := Node.Right;
            end if;
         end if;
         Bit := Bit + 1;
      end loop;

      ---------------------------------------------------
      -- We are at the last existing node in the path. --
      -- If there are any non-existent nodes on the    --
      -- path, Bit defines the first; create them.     --
      ---------------------------------------------------

      for I in Bit .. BV'Last loop
         if BV(I) then
            Node.Left := new Node;
            Node := Node.Left;
         else
            Node.Right := new Node;
            Node := Node.Right;
         end if;
      end loop;

      -------------------------------------------------------
      -- Increment the count at the node identified by BV. --
      -------------------------------------------------------

      Node.Count := Node.Count + 1;

This is exactly as efficient, and easier to maintain.  The loops have
clear missions, node creation is more localized, and the Increment
statement is only reached by one path of execution.

-- end --

-- 
Samuel Mize -- smize@imagin.net -- Team Ada
(personal net account)




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-11  0:00 GOTO considered necessary (reworked) Samuel Mize
@ 1997-06-11  0:00 ` Bryce Bardin
  1997-06-12  0:00 ` Anonymous
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 63+ messages in thread
From: Bryce Bardin @ 1997-06-11  0:00 UTC (permalink / raw)



A point that should be made in your treatment of Ada goto's is that
it is *much* safer to use than goto's in most other languages, because: 

  o You can't transfer into a construct
  o You can't transfer out of a body
  o You can't transfer between the branches of 
    an if_statement or case statement

Bryce Bardin




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-12  0:00 ` Anonymous
  1997-06-12  0:00   ` John G. Volan
@ 1997-06-12  0:00   ` Robert Dewar
  1997-06-12  0:00     ` John G. Volan
  1 sibling, 1 reply; 63+ messages in thread
From: Robert Dewar @ 1997-06-12  0:00 UTC (permalink / raw)



Jeff Carter responded to Sam's article with a typical bunch of dogmatic
never-use-gotos stuff that smacks of the fanaticism that was popular in
the 70's, but I would have hoped had disappeared by now.

Anyway Sam, take this as a vote from me that your treatment is very nice,
and just at the right level of dont-use-goto-except-where-useful.

I particularly object to Jeff's notion that introducing miscellaneous
boolean flags to replace structured use of gotos (like the CONTINUE)
makes code more readable. Far from it in my opinion, The use of Boolean's
to encode state that is more reasonably and clearly encoded in the program
counter is a big mistake in my opinion, and can often severely damage
readability in these rare cases we are talking about.






^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-12  0:00 ` Anonymous
@ 1997-06-12  0:00   ` John G. Volan
  1997-06-16  0:00     ` Anonymous
  1997-06-12  0:00   ` Robert Dewar
  1 sibling, 1 reply; 63+ messages in thread
From: John G. Volan @ 1997-06-12  0:00 UTC (permalink / raw)



Anonymous (Jeff Carter) wrote:
> 
> On 11 Jun 1997 15:40:22 -0500, smize@news.imagin.net (Samuel Mize)
> wrote:
> 
> > b) "Continue" loop logic
> >
> >    The "continue" function of C has to be emulated in Ada with a "goto":
> >
> >       loop
> >         ...
> >         goto <<CONTINUE>>
> >         ...
> >         <<CONTINUE>>
> >       end loop;
> >
> >    This is a special case of the process continuation structure.
> 
> Of course, the code in this example is the same as
> 
>    loop
>       ... -- This is the first "..." in the example
>    end loop;
> 
> since the second "..." is never executed. Real use of continue involves
> a conditional:
> 
>    loop
>       ... -- 1
> 
>       if Condition then
>          continue;
>       end if;
> 
>       ... -- 2
>    end loop;
> 
> (assuming "continue" were part of Ada :). This is equivalent to
> 
>    loop
>       ... -- 1
> 
>       if not Condition then
>          ... -- 2
>       end if;
>    end loop;
> 
> This is just as readable, and less error-prone on modification than
> using a goto.

But what if you had this:

  loop
     ... --1

     if <condition expression 1> then
       continue;
     end if;

     ... --2

     if <condition expression 2> then
       continue;
     end if;

     ... -- 3

     if <condition expression 3> then
       continue;
     end if;

     ... -- 4

  end loop;

Without goto or continue, this would have to be restructured as:

  loop
    ... --1

    if not <condition expression 1> then

      ... --2

      if not <condition expression 2> then

        ... -- 3

        if not <condition expression 3> then

          ... -- 4

        end if;
      end if;
    end if;
  end loop;

Whichever side you fall on in this debate, you have to at least agree
that a "continue" within a loop is just another example of the "process
continuation logic" situation Sam Mize described.

------------------------------------------------------------------------
Internet.Usenet.Put_Signature 
  (Name       => "John G. Volan",
   Employer   => "Texas Instruments Advanced C3I Systems, San Jose, CA",
   Work_Email => "johnv@ti.com",
   Home_Email => "johnvolan@sprintmail.com",
   Slogan     => "Ada95: World's *FIRST* International-Standard OOPL",
   Disclaimer => "My employer never defined these opinions, so using " & 
                 "them would be totally erroneous...or is that just "  &
                 "nondeterministic behavior now? :-) ");
------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-12  0:00   ` Robert Dewar
@ 1997-06-12  0:00     ` John G. Volan
  1997-06-13  0:00       ` Robert A Duff
  0 siblings, 1 reply; 63+ messages in thread
From: John G. Volan @ 1997-06-12  0:00 UTC (permalink / raw)



Robert Dewar wrote:
> 
> Jeff Carter responded to Sam's article with a typical bunch of dogmatic
> never-use-gotos stuff that smacks of the fanaticism that was popular in
> the 70's, but I would have hoped had disappeared by now.

Funny, I read the same post and didn't come away with that impression at
all. Sounded like Jeff was voicing some reasonable concerns about the
dangers of gotos and their impact on maintainability.  (In fact, Jeff
was mostly just agreeing with some counter-arguments that Sam Mize
himself enumerated.)

> Anyway Sam, take this as a vote from me that your treatment is very nice,
> and just at the right level of dont-use-goto-except-where-useful.

I agree with that philosophy, but I'd clarify it: Gotos may be used only
as a _last_ resort, after every other possible structure has been
exhaustively tried and still found to be less understandable, or
maintainable, or efficient, or whatever, than the proposed goto
solution.  But this is a very stringent requirement, and I expect it
will be very rare that a goto solution will beat out all other
alternatives.

> I particularly object to Jeff's notion that introducing miscellaneous
> boolean flags to replace structured use of gotos (like the CONTINUE)
> makes code more readable. 

Where did Jeff say anything about extra Booleans? His point seemed to be
merely that the effect of a goto can often be achieved by abstracting an
operation out as a subprogram with one or more premature return
statements, and that this may be less prone to maintenance errors than
gotos.  For instance, Sam Mize's example of insertion would clearly be
better off as a procedure:

  Items : array (Positive range Lo .. Hi) of Item_Type;
  Last  : Natural := Items'First-1;
  ...
  procedure Insert (New_Item : in Item_Type) is
  begin
    for I in Items'First .. Last loop
      if Items(I) >= New_Item then
        -- item at index I is successor for New_Item,
        -- so move items starting from I forward and
        -- insert New_Item in front of them
        Items(I+1 .. Last+1) := Items(I .. Last);
        Items(I) := New_Item;
        Last := Last + 1;
        return; -- "premature" return
      end if;
    end loop;
    -- New_Item is greater than all Items, append onto end
    Last := Last + 1;
    Items(Last) := New_Item;
  end Insert;

I would rather trust a compiler to optimize this via pragma Inline
rather than rely on manual optimization using gotos.

> Far from it in my opinion, The use of Boolean's
> to encode state that is more reasonably and clearly encoded in the program
> counter is a big mistake in my opinion, and can often severely damage
> readability in these rare cases we are talking about.

Agreed. And agreed that these cases would be rare. (So far the only case
that I find compelling are FSAs.)  But in the procedure example above,
where pray tell are the alleged extra Booleans?  Isn't the state being
encoded in the program counter, by virtue of where the return from
procedure occurs?

------------------------------------------------------------------------
Internet.Usenet.Put_Signature 
  (Name       => "John G. Volan",
   Employer   => "Texas Instruments Advanced C3I Systems, San Jose, CA",
   Work_Email => "johnv@ti.com",
   Home_Email => "johnvolan@sprintmail.com",
   Slogan     => "Ada95: World's *FIRST* International-Standard OOPL",
   Disclaimer => "My employer never defined these opinions, so using " & 
                 "them would be totally erroneous...or is that just "  &
                 "nondeterministic behavior now? :-) ");
------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-11  0:00 GOTO considered necessary (reworked) Samuel Mize
  1997-06-11  0:00 ` Bryce Bardin
  1997-06-12  0:00 ` Anonymous
@ 1997-06-12  0:00 ` Michael F Brenner
  1997-06-17  0:00   ` Robert Dewar
  1997-06-13  0:00 ` Robert A Duff
  1997-06-16  0:00 ` Anonymous
  4 siblings, 1 reply; 63+ messages in thread
From: Michael F Brenner @ 1997-06-12  0:00 UTC (permalink / raw)



Comment: section 3 (b) on efficiency should be moved up to being
the primary reason for using GOTOs in FSAs, other posts notwithstanding.
Reasons include lack of perfect inlining, lack of perfect code hoisting,
lack of perfect hardware caching, and other specific examples which
I have to post since some people apparently really believe
that it is a stylistic issue and not an efficiency issue. A clear
efficiency difference can be shown with both a regular-expression
oriented finite state transducer, such as an automatic group or a
awk-like find-and-replace pattern, and with a Domulke bit-matrix
style parser. 




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-11  0:00 GOTO considered necessary (reworked) Samuel Mize
  1997-06-11  0:00 ` Bryce Bardin
@ 1997-06-12  0:00 ` Anonymous
  1997-06-12  0:00   ` John G. Volan
  1997-06-12  0:00   ` Robert Dewar
  1997-06-12  0:00 ` Michael F Brenner
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 63+ messages in thread
From: Anonymous @ 1997-06-12  0:00 UTC (permalink / raw)



On 11 Jun 1997 15:40:22 -0500, smize@news.imagin.net (Samuel Mize)
wrote:

> 
> Greetings,
> 
> [-------------------------------------------------------------------]
> [ I'm re-doing this since a lot of people were apparently at an Ada ]
> [ conference recently, and weren't reading net news.  This version  ]
> [ is updated based on previous comments.  -- Mize                   ]
> [-------------------------------------------------------------------]
> 
> I'm rebeating a dead horse, in order to write up a consensus paper to
> submit to adahome.  I'll appreciate your input.
> 
> This one concerns use of "goto" statements.
> 
> I have scanned through the back c.l.a messages in DejaNews.  I request
> your comments on this summary.
> 
> Samuel Mize
> 
>                         USE OF "GOTO" IN ADA
>                         --------------------
> 
> 1.0 SUMMARY:

..

> 2.0 UNSUPPORTED CODE STRUCTURES
> -------------------------------
> The central feature of structured programming is not some specific set
> of code structures, but the fact that well-defined structures are used
> to organize the code.  Arbitrary "goto"s are avoided; transfers of
> control occur as part of a larger, coherent structure that helps the
> reader understand the overall program's activity.
> 
> Modern languages like Ada provide a large set of useful structures: "if"
> statements (supporting "then", "elsif", and "else" clauses), "case"
> statements, "while" and "for" loops, etc.
> 
> However, there are some useful structures that are not directly supported.
> This will always be true.  Some of these structures are rarely used, so
> are not worth the cost to add into the compiler; others may be invented,
> or may be domain-specific.
> 
> It is generally acceptable to use a "goto" to implement a well-defined
> code structure that is not directly implemented in the language.
> 
> For instance, the Ada gurus at ACT use "goto" in the GNAT compiler.  On the
> other hand, it occurs in only 3 places (in 3.07), and all are instances of
> the "not-found" pattern shown below.
> 
> Many recommend using "flag" comments to identify jumps that are not part of
> a structure.  This includes "return" and "exit" statements, as well as "goto"
> statements.  Thus, a loop might look like:
> 
>    loop
>       ...
>       exit when A; -------------------EXIT
>       ...
>       if B then
>          return; ---------------------RETURN
>       ...
>       if C then
>          goto CONTINUE; --------------GOTO
>       ...
>       <<CONTINUE>>
>    end loop;
> 
> For example, here are three structures that require "goto" in Ada:
> 
> a) Process continuation logic
> 
>    A sequential process may have several natural completion points.  One
>    example is parsing a string that ends with optional items.  Avoiding
>    "goto" in this case requires increasing levels of "if" indentation:
> 
>       [process first part of string]
>       if [not end-of-line] then
>          [process option1]
> 
>          if [not end-of-line] then
>             [process option2]
> 
>             if [not end-of-line] then
>                [process option3]
> 
>                if [not end-of-line] then
>                   [process option4]
>                    ...
>                endif;
>             endif;
>          endif;
>       endif;
> 
>    This is hard to read, and confusing since all the parsing is really at
>    the same logical level.  A "completed" flag may also be used, but this
>    does not usually improve clarity over the "goto" solution:
> 
>       [process first part of string]
>       if [end-of-line] then
>          goto NO_MORE_OPTIONS;
>       end if;
> 
>       [process option1]
>       if [end-of-line] then
>          goto NO_MORE_OPTIONS;
>       end if;
> 
>       [process option2]
>       if [end-of-line] then
>          goto NO_MORE_OPTIONS;
>       end if;
> 
>       [process option3]
>       if [end-of-line] then
>          goto NO_MORE_OPTIONS;
>       end if;
>       [process option4]
>       ...
>       <<NO_MORE_OPTIONS>>
> 
>    The same effect can be achieved by putting the processing sequence into a
>    block statement and raising an exception on end-of-line.  However, this
>    is generally considered even worse than the "goto" solution.  Most
>    standards limit exceptions to error conditions, not normal processing.

Replace all your code by

   Process_Line (...);

where the body of Process_Line is

   [process first part]

   if [end-of-line] then
      return;
   end if;

   [process option 1]

   if [end-of-line] then
      return;
   end if;

   ...

You can inline Process_Line if the subprogram-call overhead worries you.
Just as readable, and less error-prone on modification.

> 
> b) "Continue" loop logic
> 
>    The "continue" function of C has to be emulated in Ada with a "goto":
> 
>       loop
>         ...
>         goto <<CONTINUE>>
>         ...
>         <<CONTINUE>>
>       end loop;
> 
>    This is a special case of the process continuation structure.

Of course, the code in this example is the same as

   loop
      ... -- This is the first "..." in the example
   end loop;

since the second "..." is never executed. Real use of continue involves
a conditional:

   loop
      ... -- 1

      if Condition then
         continue;
      end if;

      ... -- 2
   end loop;

(assuming "continue" were part of Ada :). This is equivalent to

   loop
      ... -- 1

      if not Condition then
         ... -- 2
      end if;
   end loop;

This is just as readable, and less error-prone on modification than
using a goto.

> 
> c) "Not-Found" loop logic
> 
>    Loops frequently scan through a sequence -- for instance, an array --
>    followed by special processing if the item was not found.  An example
>    would be inserting an item in an ordered array:
> 
>       Items: array (Positive range Lo .. Hi) of Item;
>       Last_Item: Natural := Items'First - 1;
>       ...
>       -- for each item to be inserted
> 
>          for I in Items'First .. Last_Item loop
>             -- duplicates are allowed, and inserted as separate items
>             if Items (I) >= New_Item then
>                Items (I + 1 .. Last_Item + 1) := Items (I .. Last_Item);
>                Items (I) := New_Item;
>                goto ITEM_INSERTED;
>             end if;
>          end loop;
> 
>          -- New_Item's place not found before end of array
>          Last_Item := Last_Item + 1;
>          Items (Last_Item) := Item;
> 
>          <<ITEM_INSERTED>>
>          ...

This seems to have an error: what is the value of Last_Item if the item
is found? If it is not found? If you increment Last_Item after the
label, it has an incorrect value if the item is not found; if not, it
has an incorrect value if the item is found.

If you intend to retain this example, you should correct it.

> 
>    Avoiding "goto" in this case requires one of these approaches:
> 
>     - A "found" boolean.  When element is processed in loop, Found is set
>       and loop exits.  No-element processing is skipped when Found is true.
> 
>     - An "Index" variable, initially set past the end of the array, and reset
>       in the loop if the element is found.  Processing is always done after
>       loop exit, based on this index.
> 
>     - Last-iteration detection in the loop.
> 
>     Each of these is also unclear in its own way.

I don't buy this. In the first place, who's going to use a linear search
on an ordered list instead of a binary search?

The problem is combining the search for the desired location with the
insertion. Separate these two: the loop finds the location; processing
after the loop does the insertion. This needs no goto and is completely
clear.

In summary, I'd say unsupported structures can be emulated using other
structures, of which goto is one. Use of structures other than goto
maybe less error-prone than using goto without loss of clarity. Goto
should only be used if no solution of greater or equal clarity exists,
or if such a solution is found to be too slow (by measurement!), no
faster algorithm is available (binary vs. linear search again), and the
use of goto is fast enough.

> 
> 
> 3.0 FINITE STATE MACHINES (FSMs)
> --------------------------------

..

> 4.0 IMPROVING A "GOTO"-BASED DESIGN
> ---------------------------------
> The existence of "goto"s in code creates some purely mechanical problems for
> maintenance programmers.  New code may be added on the wrong side of a "goto"
> target, and "goto"-based structures are often harder to maintain when
> intervening code changes significantly.  This creates a small but definite
> advantage to eliminating many "goto" statements.

Including, IMNSH (I hope) O, all of the cases in section 2.
 
> Extraneous state variables or other unclear design kludges do not improve on
> a "goto".  If there is no overall design improvement that replaces a "goto"
> with a cleaner structure, you may as well leave the "goto".  For instance,
> the code in section 5.0 would not be improved by mechanically replacing the
> "goto" by adding a "Done" boolean or some other kludge -- this would simply
> trade one unclear design for another.

I'd say it's worth it even if the two designs are equally clear, given
the greater chance of errors during modification if a goto is used.

> 
> For instance, you should be able to say what a loop does each iteration, and
> what it has done once it exits.  (If you like semi-mathematical jargon, it
> needs an invariant and a termination condition).

So, what has the loop in your "not found" example done once it exits?
Maybe it's done an insertion, and maybe not. You have no clear
postcondition.

> 
> So, IF (1) it's worth the effort to review a "goto"-based design, and
> (2) the code can be reorganized into a clearer structure, then you should
> do so to eliminate the "goto".  If a "goto" is needed to create the
> appropriate structure for your code, use it -- and document WHY you used it.
> 

I'd say (2) should read

   the code can be reorganized into a structure that is as clear or
clearer, then ...

> The best approach to eliminating "goto" from your code is to write code in
> the first place that divides the task into logical chunks, organized by
> simple control structures.  If you design your overall approach carefully,
> you will only use "goto" when it really does improve your code.

Which is my suggestion for the "not found" example. One structure finds
the insertion point; the next performs the insertion. Your search logic
has a clear precondition, invariant, and postcondition.

> 
> 5.0 EXAMPLE OF "GOTO"-REDUCING DESIGN IMPROVEMENT

Glad to see you've eliminated the BV'Last = Natural'Last error. However,
now Bit is constrained to the same range, so you'll get an exception if
BV'Last = Bit_Vector_Index'Last and there are no nodes to be created.
Bit should be Natural, so it can be greater than BV'Last.

Jeff Carter  PGP:1024/440FBE21
My real e-mail address: ( carter @ innocon . com )
"Now go away, or I shall taunt you a second time."
Monty Python & the Holy Grail

Posted with Spam Hater - see
http://www.compulink.co.uk/~net-services/spam/




















































































^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-11  0:00 GOTO considered necessary (reworked) Samuel Mize
                   ` (2 preceding siblings ...)
  1997-06-12  0:00 ` Michael F Brenner
@ 1997-06-13  0:00 ` Robert A Duff
  1997-06-14  0:00   ` Samuel Mize
                     ` (2 more replies)
  1997-06-16  0:00 ` Anonymous
  4 siblings, 3 replies; 63+ messages in thread
From: Robert A Duff @ 1997-06-13  0:00 UTC (permalink / raw)



In article <5nn2fm$11dk$1@prime.imagin.net>,
Samuel Mize <smize@imagin.net> wrote:
>I'm rebeating a dead horse, in order to write up a consensus paper to
>submit to adahome.  I'll appreciate your input.

I don't quite understand what the point of this is.  I mean, it's fun to
argue about goto statements, but there's no real problem here.  There's
not a lot of Ada code out there filled with rats nests of gotos, so
what's the point of admonishing people about it?  The range of opinions
on this point goes from "it's never appropriate to use goto" to "it's
hardly ever appropriate to use goto" -- not a very wide range.  I don't
hear anybody saying "avoid if/case/loop, and always use goto whenever
possible".

And new Ada programmers these days are naturally happy to use
if/case/loop most of the time (unless their mind has been polluted by
spending too much time writing code in a language that doesn't *have*
if/case/loop).

As you say:

>f) The shared Ada culture avoids "goto" statements.  Gellerich et al examined
>   34428 files containing 8.5 million lines of code, coded by many projects,
>   institutions, and programmers.  They found a "goto" density of 1 "goto" per
>   13614 lines of code. ...

If there aren't many goto's in real Ada code, then clearly there aren't
many cases of misuse of goto.

Note that the above statistic doesn't mean Ada programmers think goto is
evil.  I mean, if you count the number of delay statements, you'd come
up with a similar low density -- even a tasking program will typically
have far more if statements, assignment statements, etc than delay
statements.  The above statistic just means that people don't think goto
is appropriate very often -- just like delay isn't appropriate very
often.

Like I said, I think it's fun to argue about gotos, and if I have time
maybe I'll reply to your technical points (most of which I agree with,
by the way).  But I don't think your goto FAQ is addressing any
practical problem in the world.

- Bob




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-12  0:00     ` John G. Volan
@ 1997-06-13  0:00       ` Robert A Duff
  1997-06-16  0:00         ` John G. Volan
  0 siblings, 1 reply; 63+ messages in thread
From: Robert A Duff @ 1997-06-13  0:00 UTC (permalink / raw)



In article <33A0840B.1B41@sprintmail.com>,
John G. Volan <johnvolan@sprintmail.com> wrote:
>I agree with that philosophy, but I'd clarify it: Gotos may be used only
>as a _last_ resort, after every other possible structure has been
>exhaustively tried and still found to be less understandable, or
>maintainable, or efficient, or whatever, than the proposed goto
>solution. ...

This seems like a strange attitude to me.  I mean, why not say the same
thing about any other language feature, like if statements?  You
shouldn't use an if statement if there is another way of writing the
code that's more understandable, maintainable, or whatever.  The same
applies to goto.  Why does that make goto a "last resort"?

I certainly agree that there are lots more cases where if statements are
appropriate than cases where goto is appropriate.  But both can be
judged according to the same criteria -- as you said, "understandable,
or maintainable, or efficient, or whatever".

I would also agree, if you said, "As a rule of thumb, if you think you
want to use a goto, think twice."

>...  But this is a very stringent requirement, and I expect it
>will be very rare that a goto solution will beat out all other
>alternatives.

And everybody seems to agree with *that*.

By the way, for most programs, it seems far more important to worry
about how you structure the thing using packages, types, subprograms,
tasks, etc, than to worry about the control structures.  Usually the
control structures are so small (within a single subprogram), that even
if you *only* used goto for control flow (which I don't recommend, of
course!) you could still understand the program.

- Bob




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-14  0:00   ` Samuel Mize
@ 1997-06-14  0:00     ` Matthew Heaney
  0 siblings, 0 replies; 63+ messages in thread
From: Matthew Heaney @ 1997-06-14  0:00 UTC (permalink / raw)



In article <5nufle$d1q$1@prime.imagin.net>, smize@imagin.net (Samuel Mize)
wrote:

>As I said in my other reply, my main point was just to put a writeup
>somewhere so we can tell people "yes, that's a good question -- the
>issues are discussed in <URL>".
>
>Nobody replied "This is all covered in XXX," so I have to assume that
>there isn't already a good issue-specific write-up to point people at.

Good idea.  Did you talk to Magnus?  Can he add something to the FAQ?

This was the ostensible purpose of the SPC Quality and Style Guidelines;
perhaps we need modify that document to make it more clear when a goto
really is the preferred control structure.

I for one am not averse to these types of discussions.  It's not the goto
itself that's interesting: it's the discussion that it engenders that
creates awareness of the fact that a lot coding standards out there are
pretty silly.  

Any coding convention that says Thou Shalt Not Use Gotos is a silly coding
standard, and we have to make people aware of that.  Implementing a finite
state machine (a scanner, say) is very natural using gotos, and we should
proudly state that in writing somewhere.  Obviously, when a higher-level
control structure will do, use it, but that does not mean never use gotos.

There's a great section in the 2nd ed of Meyer's Object-Oriented Software
Construction (an important book that every software engineer and his
manager should read), where he explains that a "rule" should be phrased as
a "guideline, plus a list of those times when the guideline doesn't apply." 
Shops preparing a coding standard would do well to follow Meyer's advice. 
The goal always is to simplify the code, so a standard should state what
language tools should be used for what kinds of problems, including stating
that gotos are useful for implementing FSMs.

Ada all by itself is a "tool for simplifying the code," so my expectation
is that Ada coding standards be pretty slim and simple.  However, that is
often not the case in many shops.  Why is this?  A lot of really smart guys
from all over the world debated how to design a language that was safe and
simplifies programming, so why are shops writing huge complex coding
standards to "simplify" Ada programming?  It's already simple!

Another "rule" similar to not using gotos is to not use early returns from
a subprogram, or not use an exit from a loop.  Why would you ban the use of
these constructs?  Computer scientists from all over the world decided that
these features were a good thing, or else they wouldn't have made it into
the language.  So I always need to ask a shop that prohibits them, What do
you know that they don't?  As if adding a flag to an already-complex loop
predicate is better than an exit!  What are these people thinking?  (A
question perhaps better phrased as, Why are these people not thinking?)

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
<mailto:matthew_heaney@acm.org>
(818) 985-1271




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-13  0:00 ` Robert A Duff
  1997-06-14  0:00   ` Samuel Mize
  1997-06-14  0:00   ` Samuel Mize
@ 1997-06-14  0:00   ` Robert Dewar
  1997-06-16  0:00     ` Robert A Duff
  1997-06-16  0:00     ` Spam Hater
  2 siblings, 2 replies; 63+ messages in thread
From: Robert Dewar @ 1997-06-14  0:00 UTC (permalink / raw)



Bob says

<<Note that the above statistic doesn't mean Ada programmers think goto is
evil>>


No, but we do know, without statistics, that some Ada programmers regard 
goto's as evil, and go through nasty contortions to avoid them. So Sam's
very reasonable position statement is not completely irrelevant, if it
convinces even one of these anti-goto fanatics to moderate their position,
that is useful.

I agree that it is not necessary to admonish Ada programmers not to use
goto statements.


However, there are some useful points here that apply more widely. Machine
generated code that will not be looked at by people can have all the gotos
it likes (Sam covers this point). This is of course obvious to anyone with
the slightest sense. BUT, I know at least one case in which a perfectly
reasonable tool was rejected because the Ada it output did not meet
corporate standards (which had a silly zero-tolerance position on gotos).


Yes, among reasonable people, we have a reasonable consensus that style
issues are almost never absolute, and that it is a BAD THING to convert
recomendations into hard clad rules, and in particular, to convert rules
that say "minimize the use of X", to "avoid the use of X". But in the
real world, there are plenty of nitwits around writing style manuals
who do exactly that.

I have several times now run into people saying that they were forced to
code in C in situation XXX. Incredulous, I query them, and suggest that
they could perfectly well do that in Ada using Unchecked_Conversion.
"Oh, they say, we can't use UC, it's forbidden by our coding conventions."

Then when I complain that that is a silly idea, they follow up with

"But UC is potentially implementation dependent, we are required to write
portable code"

Of course their criterion for beautiful guaranteed implementation dependent
code in C is that it passes at least some execution tests on the platform
they happen to be running on!

(note for example, Joe Gwinn's repeated claim that you can manage IO mapped
memory in C. Totally bogus of course, there is nothing in the ANSI standard
for C that assures you of this -- what is true of both C and Ada is that
in practice, given reasonable assmptions, you can handle memory mapped
IO, even though there is no guarantee from the language that it will work.






^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-13  0:00 ` Robert A Duff
@ 1997-06-14  0:00   ` Samuel Mize
  1997-06-14  0:00     ` Matthew Heaney
  1997-06-14  0:00   ` Samuel Mize
  1997-06-14  0:00   ` Robert Dewar
  2 siblings, 1 reply; 63+ messages in thread
From: Samuel Mize @ 1997-06-14  0:00 UTC (permalink / raw)



In article <EBpyKy.J3@world.std.com>,
Robert A Duff <bobduff@world.std.com> wrote:
>In article <5nn2fm$11dk$1@prime.imagin.net>,
>Samuel Mize <smize@imagin.net> wrote:
>>I'm rebeating a dead horse, in order to write up a consensus paper to
>>submit to adahome.  I'll appreciate your input.
>
>I don't quite understand what the point of this is.

I should have included these in my previous reply.

1) Many people seem to be getting a very biased introduction to the
   language.  For instance, I just read a posting from someone whose
   CS instructor said that there is no good reason to use enumeration
   values or arrays, object-oriented methods should be used instead.
   Others are self-teaching as part of their jobs, coming from using
   Fortran or C or whatever.

   I personally think it will be useful to have some of the periodic
   and/or older discussion from comp.lang.ada encapsulated so that
   people who want to know can read the summarized results.

2) Since I'm trying to express a consensus of opinion, it's not
   surprising that the write-up adds nothing new to the discussion.

As I said in my other reply, my main point was just to put a writeup
somewhere so we can tell people "yes, that's a good question -- the
issues are discussed in <URL>".

Nobody replied "This is all covered in XXX," so I have to assume that
there isn't already a good issue-specific write-up to point people at.

Sam Mize

-- 
Samuel Mize -- smize@imagin.net -- Team Ada
(personal net account)




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-13  0:00 ` Robert A Duff
  1997-06-14  0:00   ` Samuel Mize
@ 1997-06-14  0:00   ` Samuel Mize
  1997-06-14  0:00   ` Robert Dewar
  2 siblings, 0 replies; 63+ messages in thread
From: Samuel Mize @ 1997-06-14  0:00 UTC (permalink / raw)



In article <EBpyKy.J3@world.std.com>,
Robert A Duff <bobduff@world.std.com> wrote:
>In article <5nn2fm$11dk$1@prime.imagin.net>,
>Samuel Mize <smize@imagin.net> wrote:
>>I'm rebeating a dead horse, in order to write up a consensus paper to
>>submit to adahome.  I'll appreciate your input.
>
>I don't quite understand what the point of this is.

Well, I was looking through Deja News and found that there had been quite
a lively discussion about it, I think roughly a year ago, and a few others
had popped up from time to time.

>...But I don't think your goto FAQ is addressing any
>practical problem in the world.

It isn't the Wisdom of the Ages.  It's just intended to be an item we
can point people toward if the issue comes up again, rather than
re-hashing the same arguments.  Unfortunately, generating it fairly
requires re-hashing them again.

Sam Mize


-- 
Samuel Mize -- smize@imagin.net -- Team Ada
(personal net account)




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-16  0:00 ` Anonymous
@ 1997-06-16  0:00   ` Robert Dewar
  0 siblings, 0 replies; 63+ messages in thread
From: Robert Dewar @ 1997-06-16  0:00 UTC (permalink / raw)



Jeff Carter says

<<My point on all cases was that goto introduces an increased likelihood
of error on modification, and all of these cases had an alternative that
was as clear as the goto version, but eliminated that increased chance
of error. Of course, at some point clarity becomes a taste issue, so you
may claim that my versions are not as clear as the versions with goto,
IYNSHO.>>


This is exactly the kind of absolute statement that I regard as fanatic.

It is NOT the case that goto always introduces an increased likelihood
of error on modification, and it is NOT the case that the alternative
to using goto always has the same clarity.

Indeed the whole point is to identify cases, like the <<CONTINUE>> case
where goto is easier and clear from a maintenance point of view.

And it is of course the case that the general case of CONTINUE of
course requires Boolean variables to be introduced to eliminate the
gotos (this is as I mentioned before, a well known fact, well treated
in the literature).





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-13  0:00       ` Robert A Duff
@ 1997-06-16  0:00         ` John G. Volan
  1997-06-17  0:00           ` Robert A Duff
                             ` (3 more replies)
  0 siblings, 4 replies; 63+ messages in thread
From: John G. Volan @ 1997-06-16  0:00 UTC (permalink / raw)



Robert A Duff wrote:
> 
> In article <33A0840B.1B41@sprintmail.com>,
> John G. Volan <johnvolan@sprintmail.com> wrote:
> >I agree with that philosophy, but I'd clarify it: Gotos may be used only
> >as a _last_ resort, after every other possible structure has been
> >exhaustively tried and still found to be less understandable, or
> >maintainable, or efficient, or whatever, than the proposed goto
> >solution. ...
> 
> This seems like a strange attitude to me.  I mean, why not say the same
> thing about any other language feature, like if statements?  You
> shouldn't use an if statement if there is another way of writing the
> code that's more understandable, maintainable, or whatever.  The same
> applies to goto.  Why does that make goto a "last resort"?
>
> I certainly agree that there are lots more cases where if statements are
> appropriate than cases where goto is appropriate.  But both can be
> judged according to the same criteria -- as you said, "understandable,
> or maintainable, or efficient, or whatever".
> 

I could certainly be persuaded that, e.g., there are even some
situations where if statements would be a poor choice or a "last
resort".  But I think it's a matter of degree:  On the structural
continuum, gotos are considerably farther down in the primitive
direction.

Looking at the cases Sam Mize enumerates, I think they can all
essentially be boiled down to this: A programmer has a well-defined
control structure in mind (e.g., FSA's, or loop continue), but the
language does not provide a syntax for it (although such a syntax could
easily be imagined).

If the structure were available in the language, of course there would
be no question of using gotos for the same purpose.  Barring that, gotos
can be used to _simulate_ this structure, but this will always be a
dangerous practice, because the gotos are only at best a simulation of
the actual construct the programmer has in mind.  Gotos lack
"robustness"; certain important properties of the hypothetical structure
(e.g., prevention of "fall-through" between states in an FSA) cannot be
guaranteed except by programmer vigilance.

Yes, a very capable programmer may be quite skilled at navigating this
mine-field, and may be quite dilligent about documenting exactly what
structure is being simulated.  And a very skilled maintenance programmer
may be able to take such goto-laden code (and its documentation) and,
with a great deal of dilligence, successfully modify it when necessary,
without introducing accidental bugs that violate the desired properties
of the structure.

But even very skilled programmers are human and capable of errors or
omissions. It would be very useful if some automated tool (e.g., the
compiler) could provide the programmer with an analysis of whether this
use of goto satisfied the desired properties -- but the whole point is
that the compiler is incapable of this, by definition, because the
language lacked the desired construct in the first place. Bottom line,
the appearance of gotos in a program obligates both the original
programmer and all future maintainers to exert a greater than usual
effort to make sure that they get them right.

Therefore, if the programmer can think of a way to apply a different
structure to the problem, one which the language does support, then this
structure should tend to be favored over simulating a hypothetical
structure with gotos.  Of course, if the alternative structure reduces
efficiency or adds complexity (e.g., spurious levels of nesting,
auxiliary Boolean variables, or e.g. in an FSA, encoding the states with
an enumerated type), then this is a point against that alternative, and
the engineer must weigh this very carefully.

On the other hand, just because _some_ workarounds for avoiding gotos
have these undesirable properties does not automatically mean _all_
workarounds in _all_ situations will suffer from these maladies
(notwithstanding Robert Dewar's attempt to brand any suggestion along
these lines as being tantamount to advocating Boolean junk variables).
For example, in the specific case of that Insert operation, my point
(and I believe Jeff Carter's, too) was that wrapping it up as a
subprogram with multiple returns, and then inlining the subprogram, can
be every bit as efficient, no more complex, and considerably safer from
a maintenance point of view, than inlining it by hand with gotos instead
of returns. (And neither Jeff Carter nor I made _any_ mention of Boolean
junk variables for this case.)

Add to that the fact that, in that _specific case_, the Insert
subprogram is a useful, cohesive abstraction for an important operation
in the given problem domain, one with well-defined preconditions and
post-conditions which can be unit-tested, and one that might be usefully
called from many other places within the same program; then under these
circumstances, the choice for me at least would be very clear, and I
would look very critically at any claim that a goto solution would be
better.

> I would also agree, if you said, "As a rule of thumb, if you think you
> want to use a goto, think twice."

Well, that's exactly what I was trying to get across, but that's a very
nice way of putting it.

> By the way, for most programs, it seems far more important to worry
> about how you structure the thing using packages, types, subprograms,
> tasks, etc, than to worry about the control structures.  

Agreed. In fact, sometimes the temptation to resort to gotos may be
tip-off that there is a more general, systemic problem in the way your
application design has been laid out (in terms of, as you say,
high-level abstractions like packages, types, subprograms, etc.). For
instance, if I saw a lot of snippets of insertion code scattered through
a program that were all hand-inlined with gotos, I'd see that as a
failure on the part of the designer(s) to abstract out the common Insert
subprogram -- unless they _prominently_ documented the fact that they
only did this because their compiler's implementation of pragma Inline
just didn't give them the performance they needed. (But then it would
have been more profitable in the long run to fix the _compiler_.)

> Usually the
> control structures are so small (within a single subprogram), that even
> if you *only* used goto for control flow (which I don't recommend, of
> course!) you could still understand the program.

Hmm, I'm not sure what else you'd use goto for if not "control flow",
but perhaps you just mean "_local_ control flow" within a very small
procedure, as opposed to large-scale spaghetti code (which I'm sure
nobody is advocating).

------------------------------------------------------------------------
Internet.Usenet.Put_Signature 
  (Name       => "John G. Volan",
   Employer   => "Texas Instruments Advanced C3I Systems, San Jose, CA",
   Work_Email => "johnv@ti.com",
   Home_Email => "johnvolan@sprintmail.com",
   Slogan     => "Ada95: World's *FIRST* International-Standard OOPL",
   Disclaimer => "My employer never defined these opinions, so using " & 
                 "them would be totally erroneous...or is that just "  &
                 "nondeterministic behavior now? :-) ");
------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-14  0:00   ` Robert Dewar
@ 1997-06-16  0:00     ` Robert A Duff
  1997-06-17  0:00       ` Spam Hater
  1997-06-16  0:00     ` Spam Hater
  1 sibling, 1 reply; 63+ messages in thread
From: Robert A Duff @ 1997-06-16  0:00 UTC (permalink / raw)



In article <dewar.866304502@merv>, Robert Dewar <dewar@merv.cs.nyu.edu> wrote:
>No, but we do know, without statistics, that some Ada programmers regard 
>goto's as evil, and go through nasty contortions to avoid them. So Sam's
>very reasonable position statement is not completely irrelevant, if it
>convinces even one of these anti-goto fanatics to moderate their position,
>that is useful.

True, although even the fanatic won't produce *horrible* code.  OK, the
fanatic will introduce some extra boolean flags here and there, and
otherwise damage the code, but not by a lot.  Whenever somebody posts
some code that is claimed to desperately need a goto, the anti-goto
fanatics can produce similar code that doesn't use goto.  And we can
have endless arguments about whether the goto-less version is better --
this is because the goto-full and goto-less versions tend to be very
*similar* in terms of readability, maintainability, etc.  Because people
disagree about a particular program (whether or not it should contain a
goto), I claim that the readability difference can't be huge -- if it
were huge, it would be obvious to all.

>However, there are some useful points here that apply more widely. Machine
>generated code that will not be looked at by people can have all the gotos
>it likes (Sam covers this point). This is of course obvious to anyone with
>the slightest sense. BUT, I know at least one case in which a perfectly
>reasonable tool was rejected because the Ada it output did not meet
>corporate standards (which had a silly zero-tolerance position on gotos).

Yes, I agree.  I've even seen some people claim that goto can't be any
better than 'if' and 'case' and 'loop', since those are all transated
into gotos at the machine level anyway!

>Yes, among reasonable people, we have a reasonable consensus that style
>issues are almost never absolute, and that it is a BAD THING to convert
>recomendations into hard clad rules, and in particular, to convert rules
>that say "minimize the use of X", to "avoid the use of X". But in the
>real world, there are plenty of nitwits around writing style manuals
>who do exactly that.

Good point.

>I have several times now run into people saying that they were forced to
>code in C in situation XXX. Incredulous, I query them, and suggest that
>they could perfectly well do that in Ada using Unchecked_Conversion.
>"Oh, they say, we can't use UC, it's forbidden by our coding conventions."
>
>Then when I complain that that is a silly idea, they follow up with
>
>"But UC is potentially implementation dependent, we are required to write
>portable code"
>
>Of course their criterion for beautiful guaranteed implementation dependent
>code in C is that it passes at least some execution tests on the platform
>they happen to be running on!

Yes, I've heard such nonsense, too.  Of course U_C is a bit different --
if you need it, and don't have it, it's not easy to work around.  Goto,
on the other hand, has easy workarounds.

>(note for example, Joe Gwinn's repeated claim that you can manage IO mapped
>memory in C. Totally bogus of course, there is nothing in the ANSI standard
>for C that assures you of this -- what is true of both C and Ada is that
>in practice, given reasonable assmptions, you can handle memory mapped
>IO, even though there is no guarantee from the language that it will work.

I'm still waiting to see the C.  ;-)

- Bob




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-14  0:00   ` Robert Dewar
  1997-06-16  0:00     ` Robert A Duff
@ 1997-06-16  0:00     ` Spam Hater
  1997-06-17  0:00       ` Robert Dewar
  1 sibling, 1 reply; 63+ messages in thread
From: Spam Hater @ 1997-06-16  0:00 UTC (permalink / raw)



> "But UC is potentially implementation dependent, we are required to 
> write portable code"

Similar sob-story: Rep-specs written to make data structures portable 
were rejected because "rep-specs are implementation-dependent."

----------------------------------------------------------------------
    Wes Groleau, Hughes Defense Communications, Fort Wayne, IN USA
Senior Software Engineer - AFATDS                  Tool-smith Wanna-be

Don't send advertisements to this domain unless asked!  All disk space
on fw.hac.com hosts belongs to either Hughes Defense Communications or 
the United States government.  Using email to store YOUR advertising 
on them is trespassing!
----------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-11  0:00 GOTO considered necessary (reworked) Samuel Mize
                   ` (3 preceding siblings ...)
  1997-06-13  0:00 ` Robert A Duff
@ 1997-06-16  0:00 ` Anonymous
  1997-06-16  0:00   ` Robert Dewar
  4 siblings, 1 reply; 63+ messages in thread
From: Anonymous @ 1997-06-16  0:00 UTC (permalink / raw)



<199706121410.QAA05823@basement.replay.com>

On 12 Jun 1997 13:04:05 -0400, dewar@merv.cs.nyu.edu (Robert Dewar)
wrote:

> Jeff Carter responded to Sam's article with a typical bunch of dogmatic
> never-use-gotos stuff that smacks of the fanaticism that was popular in
> the 70's, but I would have hoped had disappeared by now.

Yes, that would explain why I did *not* object to the FSM example. I'm
sorry to see this typical dogmatic never-say-never-use-gotos stuff that
smacks of fanaticism from you :)

> 
> Anyway Sam, take this as a vote from me that your treatment is very nice,
> and just at the right level of dont-use-goto-except-where-useful.
> 
> I particularly object to Jeff's notion that introducing miscellaneous
> boolean flags to replace structured use of gotos (like the CONTINUE)
> makes code more readable. Far from it in my opinion, The use of Boolean's
> to encode state that is more reasonably and clearly encoded in the program
> counter is a big mistake in my opinion, and can often severely damage
> readability in these rare cases we are talking about.

I think I did not introduce any Boolean flags. I certainly did not
introduce one in the continue example. I introduced a condition because
the example, as given, was meaningless.

On continue, I find it interesting that Kernighan & Plauger included
continue in ratfor, and ever once used it in _Software Tools_. (I speak
from memory, so please correct me if I'm wrong.)

My point on all cases was that goto introduces an increased likelihood
of error on modification, and all of these cases had an alternative that
was as clear as the goto version, but eliminated that increased chance
of error. Of course, at some point clarity becomes a taste issue, so you
may claim that my versions are not as clear as the versions with goto,
IYNSHO.

Jeff Carter  PGP:1024/440FBE21
My real e-mail address: ( carter @ innocon . com )
"Now go away, or I shall taunt you a second time."
Monty Python & the Holy Grail

Posted with Spam Hater - see
http://www.compulink.co.uk/~net-services/spam/




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-12  0:00   ` John G. Volan
@ 1997-06-16  0:00     ` Anonymous
  0 siblings, 0 replies; 63+ messages in thread
From: Anonymous @ 1997-06-16  0:00 UTC (permalink / raw)



<5nn2fm$11dk$1@prime.imagin.net>
<199706121410.QAA05823@basement.replay.com>

On Thu, 12 Jun 1997 12:50:21 -0700, "John G. Volan"
<johnvolan@sprintmail.com> wrote:
..
> But what if you had this:
> 
>   loop
>      ... --1
> 
>      if <condition expression 1> then
>        continue;
>      end if;
> 
>      ... --2
> 
>      if <condition expression 2> then
>        continue;
>      end if;
> 
>      ... -- 3
> 
>      if <condition expression 3> then
>        continue;
>      end if;
> 
>      ... -- 4
> 
>   end loop;
> 
> Without goto or continue, this would have to be restructured as:
> 
>   loop
>     ... --1
> 
>     if not <condition expression 1> then
> 
>       ... --2
> 
>       if not <condition expression 2> then
> 
>         ... -- 3
> 
>         if not <condition expression 3> then
> 
>           ... -- 4
> 
>         end if;
>       end if;
>     end if;
>   end loop;
> 
> Whichever side you fall on in this debate, you have to at least agree
> that a "continue" within a loop is just another example of the "process
> continuation logic" situation Sam Mize described.

Yep, that's a mess, and I'd wonder if it might be possible to represent
the data in a way that simplified the code. If not, I'd put the contents
of the loop in a procedure and return when finished.

Jeff Carter  PGP:1024/440FBE21
My real e-mail address: ( carter @ innocon . com )
"Now go away, or I shall taunt you a second time."
Monty Python & the Holy Grail

Posted with Spam Hater - see
http://www.compulink.co.uk/~net-services/spam/






























^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-17  0:00   ` Robert Dewar
@ 1997-06-17  0:00     ` Robert A Duff
  1997-06-20  0:00       ` Robert Dewar
  0 siblings, 1 reply; 63+ messages in thread
From: Robert A Duff @ 1997-06-17  0:00 UTC (permalink / raw)



In article <dewar.866539123@merv>, Robert Dewar <dewar@merv.cs.nyu.edu> wrote:
>Within broad boundaries, I think the best approach is to write in the
>clearest way possible, and then, if there is an efficiency problem, examine
>ways to improve the code.

Agreed.

>I say within broad boundaries, because one needs to have a reasonable feel
>for gross levels of efficiency. For example, I sometimes see Ada 95 
>programs where controlled types have been used with complete abandon and
>obvious obliviousness to the fundamental inefficiencies that result.

I object to the term "fundamental" above.  I believe it is possible
(though not easy) to implement controlled types with near-zero overhead
on entering and leaving the scope of a controlled variable.

>But I would seldom chose between ways of doing things on an efficiency
>basis, and I certainly would not do so in this case. I would use the
>goto approach because I think it is clearer, even if it was less efficient,
>unless I found that it made a critical efficiency difference.

I agree on the criteria, but I disagree on the conclusion -- I like the
non-goto version of FSM's better.  I think it's important that we
recognize that it's a close call, which is why intelligent people
disagree on whether goto is appropriate in this situation.

- Bob




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-17  0:00           ` Robert Dewar
@ 1997-06-17  0:00             ` Robert A Duff
  1997-06-18  0:00               ` Spam Hater
                                 ` (3 more replies)
  1997-06-19  0:00             ` Karel Th�nissen
  1997-06-23  0:00             ` John G. Volan
  2 siblings, 4 replies; 63+ messages in thread
From: Robert A Duff @ 1997-06-17  0:00 UTC (permalink / raw)



In article <dewar.866548262@merv>, Robert Dewar <dewar@merv.cs.nyu.edu> wrote:
>First, to me, the mapping of states into sections of code, and the mapping
>of transitions as gotos, seems pretty direct -- direct enough that I do not
>think it would make sense to dream up some syntactic gizmo -- although as
>Robert Eachus points out, a preprocessor can very well provide the equivalent
>of this syntactic gizmo.

The reason some syntactic gizmo shouldn't be in the language is that
these FSM cases are rare.  If they were common, then we would get enough
benefit from such a syntactic gizmo to make it worthwhile.  (See also
languages like Lisp, where you can create your own gizmos.)

>As for fall through, that is quite a bogus argument. If you map a FSM into
>a loop/case structure with an explicit state variable, then you have to be
>equally careful not to forget to modify the state variable. The error in one
>case is accidental transition to the following state, the error in the other
>is an infinite loop in one state -- not much to call there.

I disagree.  In the loop/case method, you can put "State := Bad_State;"
at the top of the loop, and then "when Bad_State => Assert(False);" in
the case statement.  With the goto solution, you have to use care on
each state, rather than once for the whole mess.

If you want to stay in the same state, then you would write (under "when
Some_State =>", "State := Some_State;".

>Of course in practice, one of the advantages of the goto model is that in
>some cases, it is quite natural to fall through to the following state:
>
>   <<Sign>>
>      code to acquire sign
>
>   <<Digits>>
>      code to acquire digit
>      ..
>
>      if Another_Digit then
>	 goto Digits;
>      else
>	 goto Exponent;
>      end if;
>
>or somesuch, where Sign does fall through to Digits. I find this quite
>readable, and code of this kind can be found in many lexical analyzers
>in compilers.
>
>yes, of course you can often replace a specific instance (like the one above
>if that is all there is to it), with a simpler structure (e.g. a loop for
>the Digits above).

In my experience, a hand-coded lexical analyzer is always better done
with loops and ifs and case statements, rather than as above.  That is,
forget that it's a FSM, and just write it in the natural way.  ("An
identifier is a letter, followed by a sequence of zero or more letters
and digits" translates quite nicely into loops, not gotos.)  I know you
agree, since I've seen the GNAT lexer.  (A tool-generated lexer is a
whole 'nother story, of course -- throw readability to the winds, and go
for efficiency.  Funny thing is, tool-generated lexers are less
efficient, in practise, in my experience.)

>The time that a goto threaded structure becomes appropriate is when you have
>a very involved FSM with many intertwined transitions.

Yes.  In this case, I would use loop/case, whereas you would use goto.
At least we agree on the meta rule: Goto is not *always* evil, and
should be considered on a case-by-case basis.

>Basically an FSM of this kind *fundamentally* corresponds to spaghetti code,
>in that the states are executed in some non-structured sequence depending on
>the input, and therfore cannot be arranged into neat structures.
>
>We have only two methods of handling such spaghetti sequences in typical
>PL's, the code+goto representation, or the loop-case representation. 

I can think of others: E.g. an array of pointers-to-procedures, indexed
by state.

>...One
>might say that neither is perfectly happy, and that is right, since the
>underlying sequence of control is in some sense unhappy. 

That's why I don't like viewing a lexer as an FSM, nor coding it as such.

>...But given this
>choice I prefer the code+goto representation.
>
>As Robert Eachus notes, for a complex FSM, there is considerable merit in
>using one of the standard tools to generate the code.

Well, if tools are generating the code, then this whole argument is
irrelevant.  If a tool is generating it, then efficiency is paramount,
and readability of the generated Ada code is unimportant.  (Unless
you're debugging the tool, of course!)

- Bob




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-17  0:00       ` Spam Hater
  1997-06-17  0:00         ` Robert Dewar
@ 1997-06-17  0:00         ` Robert A Duff
  1997-06-19  0:00           ` Spam Hater
  1 sibling, 1 reply; 63+ messages in thread
From: Robert A Duff @ 1997-06-17  0:00 UTC (permalink / raw)



In article <33A6A9C4.7B87@no.such.com>,
Spam Hater  <no.such.user@no.such.com> wrote:
>Even more (unfortunately) common: 
>  "An exception is basically a goto, so don't use exceptions."

An exception is even *worse* than a goto, since it's more powerful: It
jumps to a run-time-determined place, which can't necessarily be
determined by reading the source code.  And that place can be very far
away in the program (whereas a goto is local to a single subprogram).

Nonetheless, it's good to use exceptions when appropriate.

(It's interesting, though, that we're having a huge discussion about
fine-tuning the rules-of-thumb about exactly when it is, and is not,
appropriate to use goto.  But I haven't seen any such discussion about
exceptions.)

- Bob




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-16  0:00         ` John G. Volan
@ 1997-06-17  0:00           ` Robert A Duff
  1997-06-25  0:00             ` Van Snyder
  1997-06-17  0:00           ` Robert I. Eachus
                             ` (2 subsequent siblings)
  3 siblings, 1 reply; 63+ messages in thread
From: Robert A Duff @ 1997-06-17  0:00 UTC (permalink / raw)



In article <33A58C79.1C7A@sprintmail.com>,
John G. Volan <johnvolan@sprintmail.com> wrote:
>I could certainly be persuaded that, e.g., there are even some
>situations where if statements would be a poor choice or a "last
>resort".

There are *lots* of situations where 'if' is a poor choice -- where
'case', or a table lookup, or a dispatching call, or a raise/handle of
an exception, is a better way.  That doesn't mean "last resort" -- it
just means you have to use some intelligence in writing your code.

>...  But I think it's a matter of degree:  On the structural
>continuum, gotos are considerably farther down in the primitive
>direction.

Agreed -- I mean you'll find more if's than goto's in *my* code.

>Looking at the cases Sam Mize enumerates, I think they can all
>essentially be boiled down to this: A programmer has a well-defined
>control structure in mind (e.g., FSA's, or loop continue), but the
>language does not provide a syntax for it (although such a syntax could
>easily be imagined).
>
>If the structure were available in the language, of course there would
>be no question of using gotos for the same purpose.  Barring that, gotos
>can be used to _simulate_ this structure, but this will always be a
>dangerous practice, because the gotos are only at best a simulation of
>the actual construct the programmer has in mind.  Gotos lack
>"robustness"; certain important properties of the hypothetical structure
>(e.g., prevention of "fall-through" between states in an FSA) cannot be
>guaranteed except by programmer vigilance.

Ada doesn't have any FSM feature with *exactly* the right semantics and
checks.  Fine, so you can *simulate* it with gotos, or with loop/case,
or with a table of access-to-procedures, etc.  I agree with you that in
this particular case, the goto solution is not the best.  But it's not
too bad, either.

>Yes, a very capable programmer may be quite skilled at navigating this
>mine-field, and may be quite dilligent about documenting exactly what
>structure is being simulated.  And a very skilled maintenance programmer
>may be able to take such goto-laden code (and its documentation) and,
>with a great deal of dilligence, successfully modify it when necessary,
>without introducing accidental bugs that violate the desired properties
>of the structure.
>
>But even very skilled programmers are human and capable of errors or
>omissions. It would be very useful if some automated tool (e.g., the
>compiler) could provide the programmer with an analysis of whether this
>use of goto satisfied the desired properties -- but the whole point is
>that the compiler is incapable of this, by definition, because the
>language lacked the desired construct in the first place. Bottom line,
>the appearance of gotos in a program obligates both the original
>programmer and all future maintainers to exert a greater than usual
>effort to make sure that they get them right.
>
>Therefore, if the programmer can think of a way to apply a different
>structure to the problem, one which the language does support, then this
>structure should tend to be favored over simulating a hypothetical
>structure with gotos.

The non-goto solution should be used if it's "better", and the goto
solution should be used if it's "worse" (judgement calls).  If they're
"equally good", then it's a toss up.  It seems silly to say that ties
somehow go to the non-goto solution.

>...  Of course, if the alternative structure reduces
>efficiency or adds complexity (e.g., spurious levels of nesting,
>auxiliary Boolean variables, or e.g. in an FSA, encoding the states with
>an enumerated type), then this is a point against that alternative, and
>the engineer must weigh this very carefully.
>
>On the other hand, just because _some_ workarounds for avoiding gotos
>have these undesirable properties does not automatically mean _all_
>workarounds in _all_ situations will suffer from these maladies
>(notwithstanding Robert Dewar's attempt to brand any suggestion along
>these lines as being tantamount to advocating Boolean junk variables).

Not sure what you mean here.  We *all* agree that in *most* situations
(the vast majority, in fact), the non-goto solution is better.  If you
read Robert Dewar's code, you won't find very many gotos -- so he
obviously agrees.

>For example, in the specific case of that Insert operation, my point
>(and I believe Jeff Carter's, too) was that wrapping it up as a
>subprogram with multiple returns, and then inlining the subprogram, can
>be every bit as efficient, no more complex, and considerably safer from
>a maintenance point of view, than inlining it by hand with gotos instead
>of returns. (And neither Jeff Carter nor I made _any_ mention of Boolean
>junk variables for this case.)

Well, be careful about "return".  It has *some* of the same dangers goto
does.  For example, I've more than once had a bug, where I added code to
a procedure that needs to get executed just before returning from that
procedure -- but I didn't notice the "return" buried deeply within some
loop's and if's.  This is similar to the "adding code on the wrong side
of the label" bug that you can get with gotos.

>Add to that the fact that, in that _specific case_, the Insert
>subprogram is a useful, cohesive abstraction for an important operation
>in the given problem domain, one with well-defined preconditions and
>post-conditions which can be unit-tested, and one that might be usefully
>called from many other places within the same program; then under these
>circumstances, the choice for me at least would be very clear, and I
>would look very critically at any claim that a goto solution would be
>better.

Yeah, but not because it's spelled "goto".  Because you have some
rational argument why that particular goto solution is worse than an
alternative non-goto solution.

>> I would also agree, if you said, "As a rule of thumb, if you think you
>> want to use a goto, think twice."
>
>Well, that's exactly what I was trying to get across, but that's a very
>nice way of putting it.

OK, you like my way of putting it.  I don't really like your way, which
seemed to say, "If two pieces of code are equally 'good', then if one of
them contains the token 'goto', then they're *not* equally good after
all", which seems illogical (self-contradictory) to me.

>> Usually the
>> control structures are so small (within a single subprogram), that even
>> if you *only* used goto for control flow (which I don't recommend, of
>> course!) you could still understand the program.
>
>Hmm, I'm not sure what else you'd use goto for if not "control flow",
>but perhaps you just mean "_local_ control flow" within a very small
>procedure, as opposed to large-scale spaghetti code (which I'm sure
>nobody is advocating).

Sorry, my statement was confusingly ungrammatical -- the usual problem
in English about how "only" binds.  I didn't mean, "use goto only for
control flow" -- as you say, that's a truism.  I meant, "for all of your
control flow, you use only goto (and not if/case/loop)".  My point was
just that control flow is far less important than the "bigger" stuff
like packages and procedures.  So even if you obfuscated all of your
control flow by using goto exclusively (no if/case/loop), you would
*still* end up with an understandable program, since all of your
procedures would be fairly small.  As compared to a program that has
giant procedures, lots of global variables, puts everything in visible
parts (but never, never uses goto).

- Bob




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-17  0:00         ` Robert Dewar
  1997-06-17  0:00           ` Spam Hater
@ 1997-06-17  0:00           ` Robert A Duff
  1997-06-19  0:00             ` John Herro
  1997-06-20  0:00             ` GOTO considered necessary (reworked) Robert Dewar
  1 sibling, 2 replies; 63+ messages in thread
From: Robert A Duff @ 1997-06-17  0:00 UTC (permalink / raw)



In article <dewar.866578231@merv>, Robert Dewar <dewar@merv.cs.nyu.edu> wrote:
>Another form of this I find annoying is "a return is basically a goto,
>so don't use returns" (for example SPARK forbids the use of gotos in
>procedures).

But a return is like a goto in a lot of ways.  E.g. when reading some
code from the top, you don't know whether a given loop might terminate
prematurely due to a return.  And, as I've said in another posting, I've
inserted code at the end of a procedure, thinking it will always be
executed just before the procedure returns, only to find that this is
one of those unusual procedures that contains a "return;" statement.

I'd like to have a language where there was a statement "some returns
coming up soon" at the front, so I can see that easily.

Of course, for functions, Ada doesn't allow you to set the result
without doing a return.  Which I've sometimes found annoying.

>I personally find returns very handy, even though I know perfectly well 
>they are gotos:
>
>  procedure ... is
>  begin
>     if condition then
>        do something simple
>        return;
>
>     else
>       LOTS MORE CODE
>
>it is very handy to read the procedure and immediately know that you
>have the whole story if condition is true, without having to see if
>there is some code following the end if.

I'm curious: Why don't you code this as:

 procedure ... is
 begin
    if condition then
       do something simple
       return;
    end if;

    LOTS MORE CODE

?  I mean, the "else" is redundant nonsense, isn't it?

>I occasionally use gotos in a similar way, almost like an exception (and
>some fanatics would insist on turning them into exceptions) -- you are
>buried deep in complex logic, and you want to say
>
>"get out, abandon all this stuff, this is not what we are looking for, go
>and do something else"
>
>occasionally a goto conveys this intention as clearly as anything :-)

I agree -- if a goto works, then it's usually better than an exception,
in a given case.  Exceptions should be reserved for the case where the
"do something else" needs to be dynamically determined (by the caller,
presumably).

>\x1adp
>
>(a little quiz, why do my messages occasionally end with ^Zdp?
> I know the answer, I am just wondering if it is obvious :-) :-)

I always assumed it's because Robert Dewar uses some weird editor, and
he's sloppy about typing.  No?

- Bob

P.S. "Weird editor" means "editor I'm not used to".  I'm not interesting
in starting a flame war about editors.




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-17  0:00       ` Robert Dewar
@ 1997-06-17  0:00         ` Spam Hater
  0 siblings, 0 replies; 63+ messages in thread
From: Spam Hater @ 1997-06-17  0:00 UTC (permalink / raw)



> <<Similar sob-story: Rep-specs written to make data structures portable
> were rejected because "rep-specs are implementation-dependent.">>
> 
> rep specs cannot in general make code more portable. They can make data
> structures better specified for interchange with the outside world,

That's the point.  Someone who had read that "rep specs cannot ... 
make code more portable" wanted to reject rep clauses that made them
"better specified for interchange with the outside" - including
data to be exchanged with a different CPU and a different HOL!

-- 
----------------------------------------------------------------------
    Wes Groleau, Hughes Defense Communications, Fort Wayne, IN USA
Senior Software Engineer - AFATDS                  Tool-smith Wanna-be

Don't send advertisements to this domain unless asked!  All disk space
on fw.hac.com hosts belongs to either Hughes Defense Communications or 
the United States government.  Using email to store YOUR advertising 
on them is trespassing!
----------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-16  0:00     ` Robert A Duff
@ 1997-06-17  0:00       ` Spam Hater
  1997-06-17  0:00         ` Robert Dewar
  1997-06-17  0:00         ` Robert A Duff
  0 siblings, 2 replies; 63+ messages in thread
From: Spam Hater @ 1997-06-17  0:00 UTC (permalink / raw)



> Yes, I agree.  I've even seen some people claim that goto can't be any
> better than 'if' and 'case' and 'loop', since those are all transated
> into gotos at the machine level anyway!

Even more (unfortunately) common: 
  "An exception is basically a goto, so don't use exceptions."
-- 
----------------------------------------------------------------------
    Wes Groleau, Hughes Defense Communications, Fort Wayne, IN USA
Senior Software Engineer - AFATDS                  Tool-smith Wanna-be

Don't send advertisements to this domain unless asked!  All disk space
on fw.hac.com hosts belongs to either Hughes Defense Communications or 
the United States government.  Using email to store YOUR advertising 
on them is trespassing!
----------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-17  0:00       ` Spam Hater
@ 1997-06-17  0:00         ` Robert Dewar
  1997-06-17  0:00           ` Spam Hater
  1997-06-17  0:00           ` Robert A Duff
  1997-06-17  0:00         ` Robert A Duff
  1 sibling, 2 replies; 63+ messages in thread
From: Robert Dewar @ 1997-06-17  0:00 UTC (permalink / raw)



Wes says

<<Even more (unfortunately) common: 
  "An exception is basically a goto, so don't use exceptions."
-- >>


Another form of this I find annoying is "a return is basically a goto,
so don't use returns" (for example SPARK forbids the use of gotos in
procedures).

I personally find returns very handy, even though I know perfectly well 
they are gotos:

  procedure ... is
  begin
     if condition then
        do something simple
        return;

     else
       LOTS MORE CODE

it is very handy to read the procedure and immediately know that you
have the whole story if condition is true, without having to see if
there is some code following the end if.

I occasionally use gotos in a similar way, almost like an exception (and
some fanatics would insist on turning them into exceptions) -- you are
buried deep in complex logic, and you want to say

"get out, abandon all this stuff, this is not what we are looking for, go
and do something else"

occasionally a goto conveys this intention as clearly as anything :-)

\x1adp

(a little quiz, why do my messages occasionally end with ^Zdp?
 I know the answer, I am just wondering if it is obvious :-) :-)






^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-17  0:00         ` Robert Dewar
@ 1997-06-17  0:00           ` Spam Hater
  1997-06-17  0:00           ` Robert A Duff
  1 sibling, 0 replies; 63+ messages in thread
From: Spam Hater @ 1997-06-17  0:00 UTC (permalink / raw)



> I personally find returns very handy, even though I know perfectly well
> they are gotos:
> 
>   [snip]
> 
> it is very handy to read the procedure and immediately know that you
> have the whole story if condition is true, without having to see if
> there is some code following the end if.

Or 'if' statements nested eight levels deep, each one checking
for an error condition, and the deepest 'else' doing the real work.

> (a little quiz, why do my messages occasionally end with ^Zdp?
>  I know the answer, I am just wondering if it is obvious :-) :-)

My guess is you are accutomed to an editor which uses that pattern
to save and exit, and when you type it by habit in another tool, you
don't waste the time to edit it out.

-- 
----------------------------------------------------------------------
    Wes Groleau, Hughes Defense Communications, Fort Wayne, IN USA
Senior Software Engineer - AFATDS                  Tool-smith Wanna-be

Don't send advertisements to this domain unless asked!  All disk space
on fw.hac.com hosts belongs to either Hughes Defense Communications or 
the United States government.  Using email to store YOUR advertising 
on them is trespassing!
----------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-16  0:00         ` John G. Volan
  1997-06-17  0:00           ` Robert A Duff
@ 1997-06-17  0:00           ` Robert I. Eachus
  1997-06-17  0:00           ` Robert Dewar
  1997-07-21  0:00           ` Shmuel (Seymour J.) Metz
  3 siblings, 0 replies; 63+ messages in thread
From: Robert I. Eachus @ 1997-06-17  0:00 UTC (permalink / raw)



In article <33A58C79.1C7A@sprintmail.com> "John G. Volan" <johnvolan@sprintmail.com> writes:

 > Looking at the cases Sam Mize enumerates, I think they can all
 > essentially be boiled down to this: A programmer has a well-defined
 > control structure in mind (e.g., FSA's, or loop continue), but the
 > language does not provide a syntax for it (although such a syntax could
 > easily be imagined).

 > If the structure were available in the language, of course there would
 > be no question of using gotos for the same purpose.

 Stop right there!  A web of sequences ended by gotos is the structure
 of a finite state machine.  It is not a simulation or substitute for
 the "real" structure, it IS the real structure.  Proof by example:
 ten years ago most computers were finite state machines.  What was
 the primary control structure?  End of discussion.

 (Well, being a nit-picker from way back I can't leave it at that.
 First, the reason I said "most computers" and "ten years ago" is that
 most CPUs today are not finite state machines, they emulate FSMs!
 Usually the hardware manual has a long chapter about when you can
 count on which properties of the simulation holding.  But the times
 when all of a modern CPU is in any defined state are few and far
 between.  Second, there are a few computers around which have tried
 different models.  Data flow architectures never became popular as
 APIs, but some computer chips use a dataflow model, and emulate a FSM
 for the API.)

 > Barring that, gotos can be used to _simulate_ this structure, but
 > this will always be a dangerous practice, because the gotos are
 > only at best a simulation of the actual construct the programmer
 > has in mind.  Gotos lack "robustness"; certain important properties
 > of the hypothetical structure (e.g., prevention of "fall-through"
 > between states in an FSA) cannot be guaranteed except by programmer
 > vigilance.

   ROTFL!  It does take lots of misdirected vigilence to prevent
 fall-through.  Of course, most tools for building FSMs spend a great
 deal of effort restructuring the tables to MAXIMIZE the amount of
 space conserved by such techniques.  And anyone who builds a
 non-trivial FSM without tool support needs their head examined.
 (Hmmm.  Better clarify that...I have built several non-trivial FSMs
 using rudimentary tool support, but that support, mapping states in
 the final machine back to the orginal grammar is crucial.  Without
 that formal verification support, you spend more time chasing your
 tail than programming.  It is always worth building those tools.)

 > Yes, a very capable programmer may be quite skilled at navigating this
 > mine-field, and may be quite dilligent about documenting exactly what
 > structure is being simulated.  And a very skilled maintenance programmer
 > may be able to take such goto-laden code (and its documentation) and,
 > with a great deal of dilligence, successfully modify it when necessary,
 > without introducing accidental bugs that violate the desired properties
 > of the structure.

 > But even very skilled programmers are human and capable of errors or
 > omissions. It would be very useful if some automated tool (e.g., the
 > compiler) could provide the programmer with an analysis of whether this
 > use of goto satisfied the desired properties...

   The right tool is not the compiler, or at least not the Ada
compiler.  There are lots of tools for building FSMs from grammars,
non-deterministic FSMs and regular expressions.  I spent over four
year supporting and enhancing one such tool.  Some of them make Ada
compilers look like simple tools.

   But believe me, they put the gotos in the right place, even when it
would take you years by hand to figure out that that was the right place.
For instance the tool mentioned above, LALR on Multics would accept
all LALR(k) grammars (and some non-context free but right-regular
grammars) and produce tables which implemented a non-context free
grammar equivalent to but much smaller than the original grammar.

 > -- but the whole point is that the compiler is incapable of this,
 > by definition, because the language lacked the desired construct in
 > the first place. Bottom line, the appearance of gotos in a program
 > obligates both the original programmer and all future maintainers
 > to exert a greater than usual effort to make sure that they get
 > them right.

   Why should the compiler be the only tool that has a hand in
converting your design into machine code?  There are many projects
where the non-compiler tools used in producing the final product make
a much larger contribution than the compilers.  How to measure such
things?  Computer cycles burned?  Wall-clock time?  Function points?
In any case, I have worked on building compilers, and there the SLOC
count for actual sources is a good measure.  I have worked on compiler
projects where the compiler, linker, and run-time accounted for less
than a third of the total source code, and of course, a lot of that
source was not in Ada or even PL/I, but in various tool defined
languages.  Even if you have never worked on a compiler, take a look
at Motif UIL or the output of some screen generator programs.  When
such tools generate high-level code for FSMs, gotos ARE the right
abstraction.

   Incidently, I chided Mike Brenner for putting too much emphasis on
the efficiency issue.  Correctness is of equal or higher importance
and the clarity form using gotos WHERE APPROPRIATE is a huge
contributor to correctness.




--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-16  0:00     ` Spam Hater
@ 1997-06-17  0:00       ` Robert Dewar
  1997-06-17  0:00         ` Spam Hater
  0 siblings, 1 reply; 63+ messages in thread
From: Robert Dewar @ 1997-06-17  0:00 UTC (permalink / raw)



Wes said

<<Similar sob-story: Rep-specs written to make data structures portable 
were rejected because "rep-specs are implementation-dependent.">>

rep specs cannot in general make code more portable. They can make data
structures better specified for interchange with the outside world, but
I don't quite understand what you mean by portable data structures. I
do understand what you mean by data structures (actually in this case
you *really* mean storage structures) more interchangable between different
Ada compilers, but that is quite a different matter.

Writing in Ada 95, you really should try to stick to the rep clauses (note
that the phrase rep specs is popular but has always been quite wrong in both
Ada 83 and Ada 95) that are guaranteed to work in Annex C.





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-12  0:00 ` Michael F Brenner
@ 1997-06-17  0:00   ` Robert Dewar
  1997-06-17  0:00     ` Robert A Duff
  0 siblings, 1 reply; 63+ messages in thread
From: Robert Dewar @ 1997-06-17  0:00 UTC (permalink / raw)



Michael Brenner says

<<Comment: section 3 (b) on efficiency should be moved up to being
the primary reason for using GOTOs in FSAs, other posts notwithstanding.>>

I agree that few (but not no) compilers will be able to convert the canonical
case/state formulation to the formulation with jumps, so it is certainly
reasonable to cite the efficiency argument.

Still I think the cases in which one should let efficiency dominate stylistic
considerations are very rare. To do this other than in cases where you really
KNOW that the efficiency is that critical seems to be to be premature
optimization. In addition, the general approach of trying to outguess an
optimizing compiler often leads people to do quite counterproductive things.

Within broad boundaries, I think the best approach is to write in the
clearest way possible, and then, if there is an efficiency problem, examine
ways to improve the code.

I say within broad boundaries, because one needs to have a reasonable feel
for gross levels of efficiency. For example, I sometimes see Ada 95 
programs where controlled types have been used with complete abandon and
obvious obliviousness to the fundamental inefficiencies that result.

But I would seldom chose between ways of doing things on an efficiency
basis, and I certainly would not do so in this case. I would use the
goto approach because I think it is clearer, even if it was less efficient,
unless I found that it made a critical efficiency difference.

Obviously if you do not share the quite common view that the goto
representation of FSM's (i.e. encoding the state in the code location)
is clearer, then you will think that efficiency is the concern, but to
elevate efficiency as the primary motive in this document would be quite
misleading, since it would miss the point that the FSM case is one of 
those rare cases where a significant number of people *do* consider
that the goto representation is clearer.





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-16  0:00         ` John G. Volan
  1997-06-17  0:00           ` Robert A Duff
  1997-06-17  0:00           ` Robert I. Eachus
@ 1997-06-17  0:00           ` Robert Dewar
  1997-06-17  0:00             ` Robert A Duff
                               ` (2 more replies)
  1997-07-21  0:00           ` Shmuel (Seymour J.) Metz
  3 siblings, 3 replies; 63+ messages in thread
From: Robert Dewar @ 1997-06-17  0:00 UTC (permalink / raw)




John Volan said

<<If the structure were available in the language, of course there would
be no question of using gotos for the same purpose.  Barring that, gotos
can be used to _simulate_ this structure, but this will always be a
dangerous practice, because the gotos are only at best a simulation of
the actual construct the programmer has in mind.  Gotos lack
"robustness"; certain important properties of the hypothetical structure
(e.g., prevention of "fall-through" between states in an FSA) cannot be
guaranteed except by programmer vigilance.
>>

First, to me, the mapping of states into sections of code, and the mapping
of transitions as gotos, seems pretty direct -- direct enough that I do not
think it would make sense to dream up some syntactic gizmo -- although as
Robert Eachus points out, a preprocessor can very well provide the equivalent
of this syntactic gizmo.

As for fall through, that is quite a bogus argument. If you map a FSM into
a loop/case structure with an explicit state variable, then you have to be
equally careful not to forget to modify the state variable. The error in one
case is accidental transition to the following state, the error in the other
is an infinite loop in one state -- not much to call there.


Of course in practice, one of the advantages of the goto model is that in
some cases, it is quite natural to fall through to the following state:

   <<Sign>>
      code to acquire sign

   <<Digits>>
      code to acquire digit
      ..

      if Another_Digit then
	 goto Digits;
      else
	 goto Exponent;
      end if;

or somesuch, where Sign does fall through to Digits. I find this quite
readable, and code of this kind can be found in many lexical analyzers
in compilers.

yes, of course you can often replace a specific instance (like the one above
if that is all there is to it), with a simpler structure (e.g. a loop for
the Digits above).

The time that a goto threaded structure becomes appropriate is when you have
a very involved FSM with many intertwined transitions.

Basically an FSM of this kind *fundamentally* corresponds to spaghetti code,
in that the states are executed in some non-structured sequence depending on
the input, and therfore cannot be arranged into neat structures.

We have only two methods of handling such spaghetti sequences in typical
PL's, the code+goto representation, or the loop-case representation. One
might say that neither is perfectly happy, and that is right, since the
underlying sequence of control is in some sense unhappy. But given this
choice I prefer the code+goto representation.

As Robert Eachus notes, for a complex FSM, there is considerable merit in
using one of the standard tools to generate the code.





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-17  0:00             ` Robert A Duff
@ 1997-06-18  0:00               ` Spam Hater
  1997-06-20  0:00               ` Robert Dewar
                                 ` (2 subsequent siblings)
  3 siblings, 0 replies; 63+ messages in thread
From: Spam Hater @ 1997-06-18  0:00 UTC (permalink / raw)



> >We have only two methods of handling such spaghetti sequences in typical
> >PL's, the code+goto representation, or the loop-case representation.
> 
> I can think of others: E.g. an array of pointers-to-procedures, indexed
> by state.

Wouldn't that be a two-dimensional array indexed by current state and
transition trigger, with pointers-to-procedures and next state in each
cell?

-- 
----------------------------------------------------------------------
    Wes Groleau, Hughes Defense Communications, Fort Wayne, IN USA
Senior Software Engineer - AFATDS                  Tool-smith Wanna-be

Don't send advertisements to this domain unless asked!  All disk space
on fw.hac.com hosts belongs to either Hughes Defense Communications or 
the United States government.  Using email to store YOUR advertising 
on them is trespassing!
----------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-17  0:00           ` Robert A Duff
@ 1997-06-19  0:00             ` John Herro
  1997-06-25  0:00               ` Function result Van Snyder
  1997-06-20  0:00             ` GOTO considered necessary (reworked) Robert Dewar
  1 sibling, 1 reply; 63+ messages in thread
From: John Herro @ 1997-06-19  0:00 UTC (permalink / raw)



bobduff@world.std.com (Robert A Duff) writes:
> Of course, for functions, Ada doesn't allow you to set the result
> without doing a return.  Which I've sometimes found annoying.

But you can set a local variable Result in as many places as you want
and later return Result.  Isn't that as good?  I do it all the time.

- John Herro
Software Innovations Technology
http://members.aol.com/AdaTutor
ftp://members.aol.com/AdaTutor






^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-17  0:00         ` Robert A Duff
@ 1997-06-19  0:00           ` Spam Hater
  0 siblings, 0 replies; 63+ messages in thread
From: Spam Hater @ 1997-06-19  0:00 UTC (permalink / raw)



> An exception is even *worse* than a goto, since it's more powerful: It
> jumps to a run-time-determined place, which can't necessarily be
> determined by reading the source code.  And that place can be very far
> away in the program (whereas a goto is local to a single subprogram).

Being more powerful doesn't make it worse.  One could argue that when
exceptions are only raised for error conditions, they are not nearly as
dangerous as a goto which is designed (or hacked) into the "normal" 
operation.

(Aside: the way some people code, the destination of an Ada goto _can_
be far away--in a 4,000 SLOC subprogram.)

-- 
----------------------------------------------------------------------
    Wes Groleau, Hughes Defense Communications, Fort Wayne, IN USA
Senior Software Engineer - AFATDS                  Tool-smith Wanna-be

Don't send advertisements to this domain unless asked!  All disk space
on fw.hac.com hosts belongs to either Hughes Defense Communications or 
the United States government.  Using email to store YOUR advertising 
on them is trespassing!
----------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-17  0:00           ` Robert Dewar
  1997-06-17  0:00             ` Robert A Duff
@ 1997-06-19  0:00             ` Karel Th�nissen
  1997-06-19  0:00               ` Karel Th�nissen
  1997-06-23  0:00               ` John G. Volan
  1997-06-23  0:00             ` John G. Volan
  2 siblings, 2 replies; 63+ messages in thread
From: Karel Th�nissen @ 1997-06-19  0:00 UTC (permalink / raw)



Robert Dewar wrote:
> 
> John Volan said
> 
> <<If the structure were available in the language, of course there would
> be no question of using gotos for the same purpose.  Barring that, gotos
> can be used to _simulate_ this structure, but this will always be a
> dangerous practice, because the gotos are only at best a simulation of
> the actual construct the programmer has in mind.  Gotos lack
> "robustness"; certain important properties of the hypothetical structure
> (e.g., prevention of "fall-through" between states in an FSA) cannot be
> guaranteed except by programmer vigilance.
> >>
> First, to me, the mapping of states into sections of code, and the mapping
> of transitions as gotos, seems pretty direct -- direct enough that I do not
> think it would make sense to dream up some syntactic gizmo -- although as
> Robert Eachus points out, a preprocessor can very well provide the equivalent
> of this syntactic gizmo.

A gizmo like this:

gizmo State : (one, two, three);
   -- the state variable is private to the gizmo (like loop indices)
   -- the state variable is read-only, but can change (like loop
indices)
   initialStuff;
   transit one;
state one;
   blaBlaTalk;
   transit ....;
state two;
   smallTalk; -- use State as a read-only variable like a loop index
   transit ....;
state three;
   fileBusterTalk;
   terminate; -- or something of that kind; needs more braincells spent
end gizmo;

> As for fall through, that is quite a bogus argument. If you map a FSM into
> a loop/case structure with an explicit state variable, then you have to be
> equally careful not to forget to modify the state variable. The error in one
> case is accidental transition to the following state, the error in the other
> is an infinite loop in one state -- not much to call there.

Yeah, a bogus argument when compared with loop+case, not when compared
with the dedicated gizmo. The gizmo should syntactically require that
every state-block explicitly transits to the next state. The gizmo
should trap ommions of transitions and unreachable states statically.
Moreover, there is a clear distinction between transits/gotos that stay
within the gizmo and the gotos that leave the gizmo all together. The
gizmo can combine the efficiency (in its implementation) of the
code+goto and the comfort of having a explicit state variable of the
loop+case and add static safety.
 
> Of course in practice, one of the advantages of the goto model is that in
> some cases, it is quite natural to fall through to the following state:
> 
>    <<Sign>>
>       code to acquire sign
> 
>    <<Digits>>
>       code to acquire digit
>       ..
> 
>       if Another_Digit then
>          goto Digits;
>       else
>          goto Exponent;
>       end if;
> 
> or somesuch, where Sign does fall through to Digits. I find this quite
> readable [...]

Right, but what happens during maintenance if the order of the states is
altered or if new states are inserted or old states removed?

This reminds me of the break in case-statements in C, with the same
problems. Oh yes, it works, it hacks, but does this outweight the
problems of ommisions in other cases, where execution accidentially
falls through? For the compiler, there is no way to detect this error.
Pretty un-Ada, I would say. The gizmo would require the safety of the
explicit transit, but it might leave it out in the resulting code.

Loop+case solutions have a similar problem of forgetting to indicate
what the next state should be, so that the loop will repeat the same
section of code over and over again. This can be fixed by invalidating
the future state before the case statement and performing a check at the
end:

state := initialState;
loop
   newState := invalidState;
   case state of
      when .... => ....; -- branches should assign newState
      when .... => ....;
      when others => raise someException; -- for missed states
   end case;
   if newState = invalidState
   then raise someOtherException
   else state := newState;
   end if;
end loop;  

(It is possible to ommit the exception trapping at the end of the code
and have the work done by the others-part of the case-statement, but
then a useful diagnostic difference between forgetting the code for a
state and forgetting to assign the new state is not reflected by the
exception.)
Look, what we have here: an auxilary variable, an additional state
value, an additional branche, additional exceptions and additional
processing. It works, errors are caught, but alas: at run time.

> Basically an FSM of this kind *fundamentally* corresponds to spaghetti code,
> in that the states are executed in some non-structured sequence depending on
> the input, and therfore cannot be arranged into neat structures.

True, therefore, one might do anything possible to avoid the programmers
getting lost in spaghetti-space. Treat FSM's at their proper level so
that errors are caught at compile time, so that maintenance is eased,
and so that formal analysis of the FSM is a possibility.
 
> As Robert Eachus notes, for a complex FSM, there is considerable merit in
> using one of the standard tools to generate the code.

True, but if we accept the added complexity of the tool and the
necessary interfacing between the tool and the language and compiler, we
might just as well extend the language with a special facility for
processing FSM's. This will result in a clearer design of the software.
A tool to generate the code for a FSM can be considered as an plug-in
extension for the compiler, but regretfully with less knowledge of the
rest of the code than a compiler would.

As long as there is no syntactic gizmo for FSM's, we should do with
code+goto or loop+case, I agree. As things are now, I do not object
against the use of gotos in FSM's. The only (marginally?) substantial
objection against the special gizmo is the extra number of reserved
words that are necessary (e.g. *gizmo* 8-) , *state* and *transit*). Do
not mention the added language complexity, because now, you either use a
special tool of at least the same complexity (but less integration) or
you use lower level approaches that are in practical life more complex
and definitely less robust.

Groeten, Karel




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-19  0:00             ` Karel Th�nissen
@ 1997-06-19  0:00               ` Karel Th�nissen
  1997-06-23  0:00               ` John G. Volan
  1 sibling, 0 replies; 63+ messages in thread
From: Karel Th�nissen @ 1997-06-19  0:00 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1319 bytes --]


Karel Th�nissen wrote:

> A gizmo like this:
> 
> gizmo State : (one, two, three);
>    -- the state variable is private to the gizmo (like loop indices)
>    -- the state variable is read-only, but can change (like loop
> indices)
>    initialStuff;
>    transit one;
> state one;
>    blaBlaTalk;
>    transit ....;
> state two;
>    smallTalk; -- use State as a read-only variable like a loop index
>    transit ....;
> state three;
>    fileBusterTalk;
>    terminate; -- or something of that kind; needs more braincells spent
> end gizmo;

Oops, the name of the state variable and the proposed reserved word for
the state blocks are the same (except for Ada-irrelevant
capitalisation)...

It should read (also adding a type definition for the state variable to
avoid an 'anonymous' type):

type StateType is (one, two, three);

gizmo StateVariable : StateType;
   -- StateVariable is private to the gizmo (like loop indices)
   -- StateVariable is read-only, but can change (like loop indices)
   initialStuff;
   transit one; -- goto initial state
state one;
   ....;        -- blocks can query StateVariable
   transit ....;
state two;
   ....;        -- transits can be burried like returns
   transit ....;
state three;
   ....;
   terminate;   -- or something of that kind
end gizmo;


> Groeten, Karel




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-17  0:00     ` Robert A Duff
@ 1997-06-20  0:00       ` Robert Dewar
  1997-06-21  0:00         ` Robert A Duff
  0 siblings, 1 reply; 63+ messages in thread
From: Robert Dewar @ 1997-06-20  0:00 UTC (permalink / raw)



Robert Duff says

<<I object to the term "fundamental" above.  I believe it is possible
(though not easy) to implement controlled types with near-zero overhead
on entering and leaving the scope of a controlled variable.>>

First, you certainly can't eliminate the actual initializatoin and
finalization (unless you are *very* clever indeed :-)

Second, eliminating the overhead from abort deferral if you are on top
of an operating system is extremely complex.





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-17  0:00             ` Robert A Duff
  1997-06-18  0:00               ` Spam Hater
  1997-06-20  0:00               ` Robert Dewar
@ 1997-06-20  0:00               ` Robert Dewar
  1997-06-21  0:00                 ` Robert A Duff
  1997-06-25  0:00               ` Wolfgang Gellerich
  3 siblings, 1 reply; 63+ messages in thread
From: Robert Dewar @ 1997-06-20  0:00 UTC (permalink / raw)



Bob Duff said

<<In my experience, a hand-coded lexical analyzer is always better done
with loops and ifs and case statements, rather than as above.  That is,
forget that it's a FSM, and just write it in the natural way.  ("An
identifier is a letter, followed by a sequence of zero or more letters
and digits" translates quite nicely into loops, not gotos.)  I know you
agree, since I've seen the GNAT lexer.>>

You may have seen it, but you have not read it all, it has a number of
gotos of the FSM type in it. Of course it is not full of this, because
FSM's don't have much to do with lexical analyzers except in unusual cases.





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-17  0:00           ` Robert A Duff
  1997-06-19  0:00             ` John Herro
@ 1997-06-20  0:00             ` Robert Dewar
  1 sibling, 0 replies; 63+ messages in thread
From: Robert Dewar @ 1997-06-20  0:00 UTC (permalink / raw)



Bob Duff asks

<<I'm curious: Why don't you code this as:
 
 procedure ... is
 begin
    if condition then
       do something simple
       return;
    end if;
 
    LOTS MORE CODE
 
?  I mean, the "else" is redundant nonsense, isn't it?>>



I find the else much clearer here, it remind you that the code under it
is code that applies to the "not condition" case, in fact I will often
write

   else -- not Still_Going

if the then part was long





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-17  0:00             ` Robert A Duff
  1997-06-18  0:00               ` Spam Hater
@ 1997-06-20  0:00               ` Robert Dewar
  1997-06-20  0:00               ` Robert Dewar
  1997-06-25  0:00               ` Wolfgang Gellerich
  3 siblings, 0 replies; 63+ messages in thread
From: Robert Dewar @ 1997-06-20  0:00 UTC (permalink / raw)



Bob Duff said

<<I disagree.  In the loop/case method, you can put "State := Bad_State;"
at the top of the loop, and then "when Bad_State => Assert(False);" in
the case statement.  With the goto solution, you have to use care on
each state, rather than once for the whole mess.>>

I disagree, I find it ugly to force you to do a state transition by
reassigning the state, when there is no state transition.

Furthermore, if you want a simple canonical way to prevent fall through,
just say

   raise Program_Error; <<state-name>>

to label a state.






^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-20  0:00       ` Robert Dewar
@ 1997-06-21  0:00         ` Robert A Duff
  1997-06-21  0:00           ` Robert Dewar
  0 siblings, 1 reply; 63+ messages in thread
From: Robert A Duff @ 1997-06-21  0:00 UTC (permalink / raw)



In article <dewar.866851059@merv>, Robert Dewar <dewar@merv.cs.nyu.edu> wrote:
>Robert Duff says
>
><<I object to the term "fundamental" above.  I believe it is possible
>(though not easy) to implement controlled types with near-zero overhead
>on entering and leaving the scope of a controlled variable.>>
>
>First, you certainly can't eliminate the actual initializatoin and
>finalization (unless you are *very* clever indeed :-)

Of course.  That's not "overhead".  That's what the program want's to
do, and of course that code needs to get executed, in general.

>Second, eliminating the overhead from abort deferral if you are on top
>of an operating system is extremely complex.

Granted.  However, a program without aborts (or, without any tasking at
all) doesn't need that overhead.  That's what pragma Restrictions is
for.  I didn't say it's "easy" to eliminate this overhead -- I said it's
possible.

But the overhead I was thinking of was the overhead of automatically
putting controlled objects onto lists and taking them off, which is also
possible, but not easy, to eliminate.

- Bob




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-20  0:00               ` Robert Dewar
@ 1997-06-21  0:00                 ` Robert A Duff
  1997-06-21  0:00                   ` Robert Dewar
  0 siblings, 1 reply; 63+ messages in thread
From: Robert A Duff @ 1997-06-21  0:00 UTC (permalink / raw)



In article <dewar.866851293@merv>, Robert Dewar <dewar@merv.cs.nyu.edu> wrote:
>Bob Duff said
>
><<In my experience, a hand-coded lexical analyzer is always better done
>with loops and ifs and case statements, rather than as above.  That is,
>forget that it's a FSM, and just write it in the natural way.  ("An
>identifier is a letter, followed by a sequence of zero or more letters
>and digits" translates quite nicely into loops, not gotos.)  I know you
>agree, since I've seen the GNAT lexer.>>
>
>You may have seen it, but you have not read it all, it has a number of
>gotos of the FSM type in it. Of course it is not full of this, because
>FSM's don't have much to do with lexical analyzers except in unusual cases.

I've read it all.  It has very few gotos (and those, I didn't object
to).  Mostly, it's made of loop/if/case.  It certainly doesn't fit into
the pattern envisioned in this thread about FSM's, where every state
starts with a label, and every state "goto"s the next state.

- Bob




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-21  0:00                 ` Robert A Duff
@ 1997-06-21  0:00                   ` Robert Dewar
  0 siblings, 0 replies; 63+ messages in thread
From: Robert Dewar @ 1997-06-21  0:00 UTC (permalink / raw)



Bob said

<<I've read it all.  It has very few gotos (and those, I didn't object
to).  Mostly, it's made of loop/if/case.  It certainly doesn't fit into
the pattern envisioned in this thread about FSM's, where every state
starts with a label, and every state "goto"s the next state.
>>

(it = GNAT scanner)

Indeed that is true. That is not surprising, in real life (as opposed to
compiler text books), scanners in compilers have little to do with finite
state machines! (unless of course you are happy with the horrible performance
of nonsense scanners generated by programs like lex)






^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-21  0:00         ` Robert A Duff
@ 1997-06-21  0:00           ` Robert Dewar
  0 siblings, 0 replies; 63+ messages in thread
From: Robert Dewar @ 1997-06-21  0:00 UTC (permalink / raw)



Bob said, replying to me

<<>First, you certainly can't eliminate the actual initializatoin and
>finalization (unless you are *very* clever indeed :-)

Of course.  That's not "overhead".  That's what the program want's to
do, and of course that code needs to get executed, in general.

>>

The context here was my observation that people used finalization too
freely in some cases, without worrying about the efficiency effects. The
actual finalization time is definitely a (perhaps the) most important
component of the casual inefficiency that unthinking use of controlled
types introduces. I never focussed on the overhead issue in the term
you are using.

<<Granted.  However, a program without aborts (or, without any tasking at
all) doesn't need that overhead.  That's what pragma Restrictions is
for.  I didn't say it's "easy" to eliminate this overhead -- I said it's
possible.

>>


The use of pragma Restrictions for this kind of improvement is in practice
not very usable. That is because you have to recompile the world, including
all libraries, to take advantage of such a restriction. If you have many
such partition wide configuration switches, you quickly need hundreds
or even thousands of different versions of your libraries. Thus in practice
the use of pragma Restrictions is not practical for general purpose
programming.

<<But the overhead I was thinking of was the overhead of automatically
putting controlled objects onto lists and taking them off, which is also
possible, but not easy, to eliminate.

>>


Well let's wait to see whether anyone actually claims to have done this
(eliminate all lists for finalization). It is *much* harder than it appears
(it reminds me of the infamous Haberman-Nassi optimization of rebdezvous --
such an obvious idea, but the devil (the one in the details) won out in that
case -- the paper was in fact never published because of fundamental
technical difficulties in marginal cases). I suspect you will find the
same thing here. It is interesting that a number of C++ implementations
are moving towards using lists as they struggle with trying to get
destructors to work "right" with exceptions.






^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-23  0:00               ` John G. Volan
@ 1997-06-23  0:00                 ` Spam Hater
  1997-06-23  0:00                 ` Robert Dewar
  1997-06-25  0:00                 ` GOTO considered necessary (reworked) Karel Th�nissen
  2 siblings, 0 replies; 63+ messages in thread
From: Spam Hater @ 1997-06-23  0:00 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 978 bytes --]


> I would not suggest inventing an entirely distinct syntactic gizmo for
> Ada (or any similar language), simply because there would not be a
> sufficient number of applications to warrant the added complexity in the
> language.

On the other hand, the gizmo that Karel Th�nissen suggested could easily
be transformed by a preprocessor into either the goto form or the lookup
table/case statement form.

----------------------------------------------------------------------
    Wes Groleau, Hughes Defense Communications, Fort Wayne, IN USA
Senior Software Engineer - AFATDS                  Tool-smith Wanna-be
                    wwgrol AT pseserv3.fw.hac.com

Don't send advertisements to this domain unless asked!  All disk space
on fw.hac.com hosts belongs to either Hughes Defense Communications or 
the United States government.  Using email to store YOUR advertising 
on them is trespassing!
----------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-23  0:00               ` John G. Volan
  1997-06-23  0:00                 ` Spam Hater
@ 1997-06-23  0:00                 ` Robert Dewar
  1997-06-24  0:00                   ` Brian Rogoff
  1997-06-25  0:00                   ` Featuritis not always bad (was re: GOTO considered necessary) Karel Th�nissen
  1997-06-25  0:00                 ` GOTO considered necessary (reworked) Karel Th�nissen
  2 siblings, 2 replies; 63+ messages in thread
From: Robert Dewar @ 1997-06-23  0:00 UTC (permalink / raw)



iJohn Volan says

<<I would not suggest inventing an entirely distinct syntactic gizmo for
Ada (or any similar language), simply because there would not be a
sufficient number of applications to warrant the added complexity in the
language.
>>

Right, I often state a rule that says that adding ANY feature AT ALL to
a language damages the language by increasing size and complexity. The
trick is to ensure that the positive contributions of the new feature
outweigh this damage.

I think this is an important language design principle. Otherwise you
end up saying "oh sure, stick this in, people do not have to use it
if they do not want it."





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-17  0:00           ` Robert Dewar
  1997-06-17  0:00             ` Robert A Duff
  1997-06-19  0:00             ` Karel Th�nissen
@ 1997-06-23  0:00             ` John G. Volan
  2 siblings, 0 replies; 63+ messages in thread
From: John G. Volan @ 1997-06-23  0:00 UTC (permalink / raw)



Robert Dewar wrote:
> 
> As for fall through, that is quite a bogus argument. If you map a FSM into
> a loop/case structure with an explicit state variable, then you have to be
> equally careful not to forget to modify the state variable. The error in one
> case is accidental transition to the following state, the error in the other
> is an infinite loop in one state -- not much to call there.
> 
> Of course in practice, one of the advantages of the goto model is that in
> some cases, it is quite natural to fall through to the following state:

[snip example of intentional fall-through]

Of course, what I was referring to was unintended or accidental
fall-through, particularly when introduced inadvertently during
maintenance. As you and others have pointed out, there are ways to
defensively guard against this whether programming a FSM using loop+case
or code+goto.

------------------------------------------------------------------------
Internet.Usenet.Put_Signature 
  (Name       => "John G. Volan",
   Employer   => "Texas Instruments Advanced C3I Systems, San Jose, CA",
   Work_Email => "jvolan@ti.com",
   Home_Email => "johnvolan@sprintmail.com",
   Slogan     => "Ada95: World's *FIRST* International-Standard OOPL",
   Disclaimer => "My employer never defined these opinions, so using" & 
                 "them would be totally erroneous ... or is that"     &
                 "just nondeterministic behavior now? :-) ");
------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-19  0:00             ` Karel Th�nissen
  1997-06-19  0:00               ` Karel Th�nissen
@ 1997-06-23  0:00               ` John G. Volan
  1997-06-23  0:00                 ` Spam Hater
                                   ` (2 more replies)
  1 sibling, 3 replies; 63+ messages in thread
From: John G. Volan @ 1997-06-23  0:00 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 4293 bytes --]


> > John Volan said
> >
> > <<If the structure were available in the language, of course there would
> > be no question of using gotos for the same purpose.  Barring that, gotos
> > can be used to _simulate_ this structure, but this will always be a
> > dangerous practice, because the gotos are only at best a simulation of
> > the actual construct the programmer has in mind.  Gotos lack
> > "robustness"; certain important properties of the hypothetical structure
> > (e.g., prevention of "fall-through" between states in an FSA) cannot be
> > guaranteed except by programmer vigilance.
> > >>

> Robert Dewar wrote:
> >
> > First, to me, the mapping of states into sections of code, and the mapping
> > of transitions as gotos, seems pretty direct -- direct enough that I do not
> > think it would make sense to dream up some syntactic gizmo -- although as
> > Robert Eachus points out, a preprocessor can very well provide the equivalent
> > of this syntactic gizmo.

I would not suggest inventing an entirely distinct syntactic gizmo for
Ada (or any similar language), simply because there would not be a
sufficient number of applications to warrant the added complexity in the
language.

Karel Th�nissen wrote:
> 
> A gizmo like this:
> 
> gizmo State : (one, two, three);
>    -- the state variable is private to the gizmo (like loop indices)
>    -- the state variable is read-only, but can change (like loop
> indices)
>    initialStuff;
>    transit one;
> state one;
>    blaBlaTalk;
>    transit ....;
> state two;
>    smallTalk; -- use State as a read-only variable like a loop index
>    transit ....;
> state three;
>    fileBusterTalk;
>    terminate; -- or something of that kind; needs more braincells spent
> end gizmo;

How about this instead:

  type State_Type is (One, Two, Three);
  State : State_Type := State_Type'First;
  ...

  FSA_Name:
  loop
    case State is
    when One =>
      ...
      if ... then
        State := ...
      elsif ... then
        State := ...
      else
        State := ...
      end if;

    when Two =>
      ...

    when Three =>
      ...

    end case;
  end loop FSA_Name;

i.e., exactly the loop+case idea, but with the following addition:

  pragma Finite_State_Automaton (FSA_Name, State);

This pragma would enforce the following criteria: (1) FSA_Name must be
the name of a loop. (2) The loop must contain only a case statement. (3)
The controlling expression of this case statement must be the State
variable given in the pragma. (4) Every when-clause in the case
statement must end with an explicit assignment of the State variable to
some value, or with a named exit from the loop. (4a) If a given
transition is from one state to the same state, this still must be
explicitly expressed with an assignment statement.  (4b) If there is
more than one possible transition from a given state, requiring
conditional code to discriminate the different possibilities, then each
branch of the conditional logic must end with an explicit assignment of
the State variable (or loop exit).

The advantage of using a pragma for this rather than a new syntax is
that it doesn't require any actual change in the language definition.
Instead, it just layers some special-case semantics on the existing
syntax of the language, which seems quite appropriate for this special
case situation.

I suppose a similar sort of pragma might be devised for the code+goto
style, requiring that every conditional branch within a given code-block
end with an explicit goto.

But again, it's hardly worth the effort to design and implement such a
pragma, given the low demand for FSAs in most software. 

------------------------------------------------------------------------
Internet.Usenet.Put_Signature 
  (Name       => "John G. Volan",
   Employer   => "Texas Instruments Advanced C3I Systems, San Jose, CA",
   Work_Email => "jvolan@ti.com",
   Home_Email => "johnvolan@sprintmail.com",
   Slogan     => "Ada95: World's *FIRST* International-Standard OOPL",
   Disclaimer => "My employer never defined these opinions, so using" & 
                 "them would be totally erroneous ... or is that"     &
                 "just nondeterministic behavior now? :-) ");
------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-23  0:00                 ` Robert Dewar
@ 1997-06-24  0:00                   ` Brian Rogoff
  1997-06-25  0:00                   ` Featuritis not always bad (was re: GOTO considered necessary) Karel Th�nissen
  1 sibling, 0 replies; 63+ messages in thread
From: Brian Rogoff @ 1997-06-24  0:00 UTC (permalink / raw)



On 23 Jun 1997, Robert Dewar wrote:
> Right, I often state a rule that says that adding ANY feature AT ALL to
> a language damages the language by increasing size and complexity. The
> trick is to ensure that the positive contributions of the new feature
> outweigh this damage.

Possible counterexample: I believe that in Ada 83, renaming of generic 
units was forbidden. That restriction was removed in Ada 95, or if you 
prefer to think of the dual of that proposition, a feature was added.

One could probably make up lots of examples of this sort where a
restriction is removed, a new feature thus enabled with an overall 
reduction in language complexity. 

I agree with your rule, if you interpret these cases as being something 
other than the addition of features.

-- Brian






^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-23  0:00               ` John G. Volan
  1997-06-23  0:00                 ` Spam Hater
  1997-06-23  0:00                 ` Robert Dewar
@ 1997-06-25  0:00                 ` Karel Th�nissen
  2 siblings, 0 replies; 63+ messages in thread
From: Karel Th�nissen @ 1997-06-25  0:00 UTC (permalink / raw)



John G. Volan wrote:
> 
> I would not suggest inventing an entirely distinct syntactic gizmo for
> Ada (or any similar language), simply because there would not be a
> sufficient number of applications to warrant the added complexity in the
> language.

I am not able to judge the frequence in sufficiently large sample of
code.

> How about this instead:
 
[snipped: standard loop+case implementation of FSM]

>   pragma Finite_State_Automaton (FSA_Name, State);
 
> This pragma would enforce the following criteria:
[snip on list of semantic constraints for the pragma]

These are the semantics I had in mind too.
 
> The advantage of using a pragma for this rather than a new syntax is
> that it doesn't require any actual change in the language definition.
> Instead, it just layers some special-case semantics on the existing
> syntax of the language, which seems quite appropriate for this special
> case situation.

The nice thing is that the code will work even if your compiler does not
understand the particular pragma. At the expense of missing the
additional security of course.

However, we should be careful (in general) not to extend this kind of
reasoning to far, because then we end up with a language design in which
everything is handled by the simplest of all control structures (the
infamous goto) that does all the dirty work, monitored by a couple of
pragmas that check semantic constraints for particular patterns (loops,
selections, etc.). If they are supported, that is.
 
> I suppose a similar sort of pragma might be devised for the code+goto
> style, requiring that every conditional branch within a given code-block
> end with an explicit goto.

Guess so.
 
> But again, it's hardly worth the effort to design and implement such a
> pragma, given the low demand for FSAs in most software.

Or is that because FSM's are avoided because people do not recognize
them or fear the goto-based programming that is implied? FSM's have more
applications than lexical analysis alone: communication protocols,
process description in discrete simulation, user interface interaction
at various levels, games, control tasks in operating systems, ...

Groeten, Karel




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Featuritis not always bad (was re: GOTO considered necessary)
  1997-06-23  0:00                 ` Robert Dewar
  1997-06-24  0:00                   ` Brian Rogoff
@ 1997-06-25  0:00                   ` Karel Th�nissen
  1997-06-26  0:00                     ` Robert Dewar
  1 sibling, 1 reply; 63+ messages in thread
From: Karel Th�nissen @ 1997-06-25  0:00 UTC (permalink / raw)



Robert Dewar wrote:

> Right, I often state a rule that says that adding ANY feature AT ALL to
> a language damages the language by increasing size and complexity.

Yes, but leaving it out may lead to increased size and complexity of
programs written in the language. If the feature is difficult to get
right, maybe it is an even better idea to have it incorporated in the
language and not in the programs. Then tens of thousands of programmers
can all save hours of trying to make it themselves in their numerous
programs (Ada-case) or millions of programmers can all save weeks trying
to make it themselves (C/C++-case 8-) in their numerous programs.

In general, I object to the use of the term complexity as a measurment
in language design. Complexity of the compiler? complexity of the
tutorial? complexity of the programs written in it, complexity of the
design, complexity of the design and programming proces, complexity of
verification, validation and testing? Usually one comes at the expense
of the other.

The most serious effect is often the consumption of precious name space
by reserved words.

> The trick is to ensure that the positive contributions of the new 
> feature outweigh this damage.

As for many things in life 8-)

> I think this is an important language design principle. Otherwise you
> end up saying "oh sure, stick this in, people do not have to use it
> if they do not want it."

Which is no problem if the feature:
1) is well designed and well behaved, so no tail biting
2) comes as a independant feature, so that people can work with the rest
of the language without ever knowing that the feature existed. This
ensures that people can write in the language safely if they have not
finished the full language course: avoid steep learning curve and memory
load.
3) comes as a clearly recognisable syntactic entity in the language. So
if one reads the code and is not familiar with the feature one at least
knows that there is a cognitive problem, and knows where to look in the
reference manual (and find there many useful informations on the feature
that would find no place if the feature was to be simulated with lower
level constructs)

This is one of the great benefits of design patterns: they allow us an
understanding of the system at a higher level of understanding and
provide an easier to grasp repetoir of solutions and a vocabulary.

I leave it as an exercise to the reader to determine whether the FSM is
such a feature.

Groeten, Karel




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-17  0:00             ` Robert A Duff
                                 ` (2 preceding siblings ...)
  1997-06-20  0:00               ` Robert Dewar
@ 1997-06-25  0:00               ` Wolfgang Gellerich
  1997-06-25  0:00                 ` Michael F Brenner
  1997-06-25  0:00                 ` Samuel T. Harris
  3 siblings, 2 replies; 63+ messages in thread
From: Wolfgang Gellerich @ 1997-06-25  0:00 UTC (permalink / raw)



In article <EBxrpn.67C@world.std.com>, bobduff@world.std.com (Robert A Duff) writes:

(...)

|> In my experience, a hand-coded lexical analyzer is always better done
|> with loops and ifs and case statements, rather than as above.  That is,
|> forget that it's a FSM, and just write it in the natural way.  ("An
|> identifier is a letter, followed by a sequence of zero or more letters
|> and digits" translates quite nicely into loops, not gotos.)  I know you
|> agree, since I've seen the GNAT lexer.  (A tool-generated lexer is a
|> whole 'nother story, of course -- throw readability to the winds, and go
|> for efficiency.  Funny thing is, tool-generated lexers are less
|> efficient, in practise, in my experience.)

Definitely. We recently made a study comparing different methods how to 
implement an Ada 95 scanner and then measured the time they needed to lexical
analyse some large Ada sources. The slowest and the fastest scanners
differed by factor 74 (!) and the fastest one was hand-coded scanner, using
no GOTOs and basically following the strategy described above.

------

  Wolfgang 




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-25  0:00               ` Wolfgang Gellerich
@ 1997-06-25  0:00                 ` Michael F Brenner
  1997-06-26  0:00                   ` Wolfgang Gellerich
  1997-06-25  0:00                 ` Samuel T. Harris
  1 sibling, 1 reply; 63+ messages in thread
From: Michael F Brenner @ 1997-06-25  0:00 UTC (permalink / raw)



Would it be possible to post your study showing it was 74 times faster?





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-17  0:00           ` Robert A Duff
@ 1997-06-25  0:00             ` Van Snyder
  0 siblings, 0 replies; 63+ messages in thread
From: Van Snyder @ 1997-06-25  0:00 UTC (permalink / raw)



Many years ago, in an April issue of Comm. ACM., somebody proposed replacing
GOTO with COMEFROM.  COMEFROM was implemented in INTERCAL.

This spoof comes to mind whenever somebody discusses GOTO.

I've decided there's some value in it.

Instead of _replacing_ GOTO by COMEFROM, require all GOTO's to be labelled,
require that they transfer to a labelled COMEFROM, and require that the
COMEFROM refers to the label of the GOTO that goes to the COMEFROM.

The primary objection mentioned in Dijkstra's original letter "GOTO considered
harmful" is the difficulty in discovering how control reaches a certain point
in a program.  Coupling GOTO and COMEFROM reduces the severity of that
objection.

-- 
What fraction of Americans believe   |  Van Snyder
Wrestling is real and NASA is fake?  |  vsnyder@math.jpl.nasa.gov




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Function result
  1997-06-19  0:00             ` John Herro
@ 1997-06-25  0:00               ` Van Snyder
  1997-06-27  0:00                 ` Robert Dewar
  1997-06-27  0:00                 ` Jon S Anthony
  0 siblings, 2 replies; 63+ messages in thread
From: Van Snyder @ 1997-06-25  0:00 UTC (permalink / raw)



In article <19970619161801.MAA18772@ladder02.news.aol.com>, johnherro@aol.com (John Herro) writes:
|> bobduff@world.std.com (Robert A Duff) writes:
|> > Of course, for functions, Ada doesn't allow you to set the result
|> > without doing a return.  Which I've sometimes found annoying.
|> 
|> But you can set a local variable Result in as many places as you want
|> and later return Result.  Isn't that as good?  I do it all the time.

This _works_ but it would be nice if you didn't need to trust the compiler
to optimize away the assignments to Result.

It doesn't seem so bad in Ada, with the explicit copy-out model of returning
function results, because you're only doubling the cost of returning the
function result.

The copy-out model, however, causes other headaches.  In particular, you
can't return a limited type, except by the "return by reference" kludge.

In Pascal and Fortran (at least) one returns a function result by assigning
to the result variable (default name = function name in Fortran 95).  The
Fortran standard is silent on _how_ function results are returned.  For
composite results (e.g. structures, arrays, character strings), most compilers
pass the address where the function result is to land as a "hidden argument."
In this way, the syntactic device of assigning to the function result
_really_is_ assigning directly to the function result -- no extra copying
involved.

By the way, this would eliminate the problem about returning a limited
type in Ada.

In the next standardization of Ada, I suggest allowing an optional "name:"
after "return" in a function header.  This would imply four things:
1.  The client is expected to supply the address where the function result
    is desired as a "hidden argument".
2.  The function result is materialized directly in the place the client
    wants it, without any copying.
3.  Since there's no copying going on outside the function, it would be OK
    to allow returning a limited type.
4.  In the function, the result would be materialized by storing into the
    result variable, not by mentioning the value in a "return" statement.
    The program could do this piece-by-piece in the case of a composite
    result.

-- 
What fraction of Americans believe   |  Van Snyder
Wrestling is real and NASA is fake?  |  vsnyder@math.jpl.nasa.gov




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-25  0:00               ` Wolfgang Gellerich
  1997-06-25  0:00                 ` Michael F Brenner
@ 1997-06-25  0:00                 ` Samuel T. Harris
  1 sibling, 0 replies; 63+ messages in thread
From: Samuel T. Harris @ 1997-06-25  0:00 UTC (permalink / raw)



Wolfgang Gellerich wrote:
> 
> In article <EBxrpn.67C@world.std.com>, bobduff@world.std.com (Robert A Duff) writes:
> 
> (...)
> 
> |> In my experience, a hand-coded lexical analyzer is always better done
> |> with loops and ifs and case statements, rather than as above.  That is,
> |> forget that it's a FSM, and just write it in the natural way.  ("An
> |> identifier is a letter, followed by a sequence of zero or more letters
> |> and digits" translates quite nicely into loops, not gotos.)  I know you
> |> agree, since I've seen the GNAT lexer.  (A tool-generated lexer is a
> |> whole 'nother story, of course -- throw readability to the winds, and go
> |> for efficiency.  Funny thing is, tool-generated lexers are less
> |> efficient, in practise, in my experience.)
> 
> Definitely. We recently made a study comparing different methods how to
> implement an Ada 95 scanner and then measured the time they needed to lexical
> analyse some large Ada sources. The slowest and the fastest scanners
> differed by factor 74 (!) and the fastest one was hand-coded scanner, using
> no GOTOs and basically following the strategy described above.
> 
> ------
> 
>   Wolfgang

While true as to efficiency, tool-generated scanners allow
you to work in the realm of the syntax of you language
and allows you to quickly modify your syntax and get a new
scanner almost instantly.

As far as the loop/case vs goto is concerned for general
FSA, I have used both on occasion, but have always perfered
tables with subprogram pointers. While not directly possible
with Ada 83 except through families of task entries (a kludge),
Ada 95's new support for access to subprogram objects makes
this an attactive alternative. The advantage of the table approach
is that you can easily maintain it by adjusting the values
within the table. The table is index by state and input, which
each component of the 2-dimentional array being a recording
containing subprogram pointers and the new state. The FSM
simply remembers the current state. The iterate operation
applies a new input to the FSM which indexes the table,
executes the subprogram, and resets the current state.

FSM which require prolog and epilog operations around
the main action routine will have additional subprogram
pointers in the record structure. If feedback from the
action routine is required to determine the next state,
then the action routine can be a function taking the
current state, input, and recommended next state and
return the actual next state.

The point is that once the logic and semantics of traversing
the FSM from one state to another has been built to whatever
level of complexity is appropriate, then the mechanism for
iterating the FSM can be encapuslated into a 2 dimentional
table and the "engine" itself is a really simply piece of
code. The table itself can be initialized with an aggregate
or read in from a data file. By separating the action
routines from the FSM code, you get easy maintenance
when the tables change. Of course, you can achieve the
same separation with the loop/case and goto model, but
you have to "touch" the source code when the transitions
change. With a table driven FSM, you only have to change
the data file.

As a side note, I'm working on an effort at the moment
where the internal FSM of the component is sometimes
an "animated" entity (running on its own in a background task)
and sometimes it is an "actuated" entity (meaning the program
doesn't want tasks hanging around and needs to control when
the FSM interates). A goto model must always be animated.
A loop/case or table driven model can be animated or actuated.

As with any debate concerning equally "powerful" alternative,
it is the application of very specific requirements which
show one method to be superior to the others, but only
for that particular case. That's which none of the three
is the best all (or even most) of the time.

-- 
Samuel T. Harris, Senior Engineer
Hughes Training, Inc. - Houston Operations
2224 Bay Area Blvd. Houston, TX 77058-2099
"If you can make it, We can fake it!"




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Featuritis not always bad (was re: GOTO considered necessary)
  1997-06-25  0:00                   ` Featuritis not always bad (was re: GOTO considered necessary) Karel Th�nissen
@ 1997-06-26  0:00                     ` Robert Dewar
  1997-06-26  0:00                       ` Karel Th�nissen
  0 siblings, 1 reply; 63+ messages in thread
From: Robert Dewar @ 1997-06-26  0:00 UTC (permalink / raw)



<<Which is no problem if the feature:
1) is well designed and well behaved, so no tail biting
2) comes as a independant feature, so that people can work with the rest
of the language without ever knowing that the feature existed. This
ensures that people can write in the language safely if they have not
finished the full language course: avoid steep learning curve and memory
load.
3) comes as a clearly recognisable syntactic entity in the language. So
if one reads the code and is not familiar with the feature one at least
knows that there is a cognitive problem, and knows where to look in the
reference manual (and find there many useful informations on the feature
that would find no place if the feature was to be simulated with lower
level constructs)
??


This is *precisely what I disagree with. The trouble is that you don't
know you don't need to know something until you know it, and then it's
too late! 

Yes, of coruse it is the case that adding features to a language, and
thus increasing the complexity of the language may easily be counterbalanced
by the resulting simplification in programs. That's exactly the tradeoff
that needs to be considered.





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-25  0:00                 ` Michael F Brenner
@ 1997-06-26  0:00                   ` Wolfgang Gellerich
  0 siblings, 0 replies; 63+ messages in thread
From: Wolfgang Gellerich @ 1997-06-26  0:00 UTC (permalink / raw)



In article <5orpi1$nei@top.mitre.org>, mfb@mbunix.mitre.org (Michael F Brenner) writes:
|> Would it be possible to post your study showing it was 74 times faster?

Currently, we are preparing a conference paper stating all the results
about scanner efficiency. I can post a notice to this newsgroup when
its published.

-----------

  Wolfgang Gellerich




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Featuritis not always bad (was re: GOTO considered necessary)
  1997-06-26  0:00                     ` Robert Dewar
@ 1997-06-26  0:00                       ` Karel Th�nissen
  0 siblings, 0 replies; 63+ messages in thread
From: Karel Th�nissen @ 1997-06-26  0:00 UTC (permalink / raw)



Robert Dewar wrote:
> 
> <<Which is no problem if the feature:
> 1) is well designed and well behaved, so no tail biting
> 2) comes as a independant feature, so that people can work with the rest
> of the language without ever knowing that the feature existed. This
> ensures that people can write in the language safely if they have not
> finished the full language course: avoid steep learning curve and memory
> load.
> 3) comes as a clearly recognisable syntactic entity in the language. So
> if one reads the code and is not familiar with the feature one at least
> knows that there is a cognitive problem, and knows where to look in the
> reference manual (and find there many useful informations on the feature
> that would find no place if the feature was to be simulated with lower
> level constructs)
> ??
> 
> This is *precisely what I disagree with. The trouble is that you don't
> know you don't need to know something until you know it,

The tutorial might tell you. Why not tell the language users what parts
of the language can be safely skipped until later. Also tell them for
what kind of problems these parts of the language are appropriate.

> and then it's too late!

Yes, then it is too late, but then what? Maybe a frustrating experience
that you could have coded the problem more easily or more safely, but
the programs you had written up to then, work exaclty as expected with
the more limited understanding of the code that you had.

Let me give two examples: Ada's exception and tasking mechanisms. These
satisfy the three criteria I gave more or less.

Regarding my first criterion, they are well designed, there are no nasty
quirks that do not stem from the very nature of exception handling and
tasking (unlike exception handling in PL/I which had a rotten design).

Regarding my second criterion, anyone not having read the part of the
manual on exceptions can use the rest of the Ada-language without
problem. Okay you miss the comfort of the mechanism, but what rests is a
language with the power of say Pascal. Anyone coming from Pascal would
not notice any important semantic difference between Pascal and an Ada
without exceptions, because errors in the programs crash the system, as
exspected. Same for tasking, if you do not use it, you never have to
worry about it. The model of an Ada without exceptions and tasking is
the same as that of an Ada with these facilities available but left
unused. So one can use Ada safely without exceptions and tasks in the
sense that the program operates as expected.

Regarding my third criterion, anyone not completly familiar with Ada
(say with a level of knowledge of Ada that covers the features provided
by Pascal) would instantly spot the presence of a task definition,
because there is nothing like it in the language model that s/he had
seen until then. S/he can see there is something special because of the
unfamiliar reserved (bold or capitalized) word 'TASK'. The best place to
fill up insufficient knowledge is in the manual under 'TASK'. Compare
that with a language where tasking is 'emulated' with platform dependant
procedure calls and where the intricacies of the tasking are burried in
procedure calls that look like normal procedure calls, but that have
lots of special semantics. The risks of misreading are severe, even it
uses concepts that he was supposed to understand. The manual cannot
provide much help, because the tasking is handled in a platform
dependant way that is outside the scope of the language. Moreover, there
is not a keyword to search for in the index.

Exceptions however, do not comply with this third requirement. They are
declared as any other object. Nothing to warn you there. Then there is
the 'raise', which looks (if not in bold) like an ordinary procedure
invocation....

To the list I should have added a fourth clause that the user should not
be allowed to accidently run into the feature. Sufficient syntactic
difference between the 'optional' feature and the rest of the language
can guarantee that. With tasking the risk is negligible, there just is
no language feature that, because of some reasonable error on the
programmer's side, could accidently form a task definition. With
exceptions the risk is bigger, but permissible. The programmer might
accidently try to define a type called 'exception' or a procedure called
'raise', but the compiler should catch that, as it is forbidden to
redefine these identifiers. Leaves the risk that the user planned to
define either a type called 'exception' or a procedure called 'raise',
and uses it, but has forgotten to give his/her own definitions. Still
then, more things must go wrong, to have the compiler swallow this as an
correct invocation of the Ada exception mechanism: both the type called
'exception' and the procedure called 'raise' should be planned, their
definitions forgotten, and used with an exception object as the argument
of the procedure 'raise'. The compiler will still catch it because of
the forbidden parentheses with the raise, but it leaves the programmer
confused as compiler error messages or not clear.

Having said this, I do not want to imply that FSM's are a candidate for
incorporation.

> Yes, of coruse it is the case that adding features to a language, and
> thus increasing the complexity of the language may easily be counterbalanced
> by the resulting simplification in programs. That's exactly the tradeoff
> that needs to be considered.

I know that this was a consideration in the design of Ada, whereas often
more academic languages look for compiler, language or definition report
simplicity.

Groeten, Karel




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Function result
  1997-06-25  0:00               ` Function result Van Snyder
@ 1997-06-27  0:00                 ` Robert Dewar
  1997-06-27  0:00                 ` Jon S Anthony
  1 sibling, 0 replies; 63+ messages in thread
From: Robert Dewar @ 1997-06-27  0:00 UTC (permalink / raw)



Van Snyder says

<<This _works_ but it would be nice if you didn't need to trust the compiler
to optimize away the assignments to Result.

It doesn't seem so bad in Ada, with the explicit copy-out model of returning
function results, because you're only doubling the cost of returning the
function result.

The copy-out model, however, causes other headaches.  In particular, you
can't return a limited type, except by the "return by reference" kludge.

In Pascal and Fortran (at least) one returns a function result by assigning
to the result variable (default name = function name in Fortran 95).  The
Fortran standard is silent on _how_ function results are returned.  For
composite results (e.g. structures, arrays, character strings), most compilers
pass the address where the function result is to land as a "hidden argument."
In this way, the syntactic device of assigning to the function result
_really_is_ assigning directly to the function result -- no extra copying
involved.

By the way, this would eliminate the problem about returning a limited
type in Ada.
>>

Oh dear, this is very confused.

First, about trusting the compiler to optimize away the assignments to
Result. Most compilers in any case have only one copy of the epilog in
a function, and all return statements share it. For example, with GCC:

procedure f is

   b,c,d : Boolean;

   function g return boolean is
   begin
      if b then
         return c;
      else
         return d;
      end if;
   end;

   function h return boolean is
      result : Boolean;
   begin
      if b then
         result := c;
      else
         result := d;
      end if;
      return result;
   end;

begin
   null;
end;

The functions g and h generate identical code. It would be surprising to
anyone who knows something about compilers if this were NOT the case. There
is no doubling of costs anywhere, to guess that there might be is simply
based on some kind of inaccurate model of code generation.

Second, Ada does not require copy-out except for scalars, where in any case
it is more efficient (and typically used in most Fortran compilers for
example. It cannot be used in Pascal, but that often *damages* the efficiency
of compiled code in a Pascal compiler, since call by reference is less
efficient than call by copy for things that fit in registers. 

In fact Ada is very similar to Fortran when it comes to parameters that
do not fit in registers, it allows the compiler to pass either by reference
or by copy in/copy out. An Ada compiler will choose the most efficient
method, and typically any large argument will be passed by reference.

And yes, in the case where the result is fixed size (always true in Pascal
and Fortran, not, of course, always true in Ada), a standard technique is
for the caller to pass the address where the result is to be stored. Your
conception that this is not possible in Ada is just wrong (for example,
this is typically the way that GNAT returns results, and it is the way
anyone would expect fixed-length resluts to be returned)

Finally your comments on limited types show further misunderstanding. The
"difficulties" on returning limited types have nothing at all to do with
some kind of implementation problem (which as per above does not exist
anyway), but rather there is a fundamental semantic issue, which is that
limitedness is there to control copying (consider for example the case of
a self-referential access discriminant). Since copying must be controlled,
the semantics of returning a limited type must be dealt with very carefully
in the language -- this is purely a semantic issue, not an implementation
issue. I suggest reading the Ada 95 Rationale for a better understanding
of what limited types are all about.

As for the suggestions at the end of your message for the next version of
Ada, they are irrelevant, since they are based on misconceptions, and make
no sense in a context of understanding (a) the parameter passing rules
in Ada (b) the typical implemenmtation approaches (c) the semantics of
limited types. In particular, the suggestion of a syntactic device for
labeling the returned value seems entirely undesirable.





^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: Function result
  1997-06-25  0:00               ` Function result Van Snyder
  1997-06-27  0:00                 ` Robert Dewar
@ 1997-06-27  0:00                 ` Jon S Anthony
  1 sibling, 0 replies; 63+ messages in thread
From: Jon S Anthony @ 1997-06-27  0:00 UTC (permalink / raw)



In article <5os5r8$4ud@netline.jpl.nasa.gov> vsnyder@gyre.jpl.nasa.gov (Van Snyder) writes:

> pass the address where the function result is to land as a "hidden argument."
> In this way, the syntactic device of assigning to the function result
> _really_is_ assigning directly to the function result -- no extra copying
> involved.
> 
> By the way, this would eliminate the problem about returning a limited
> type in Ada.

????  What problem is that???


> 1.  The client is expected to supply the address where the function result
>     is desired as a "hidden argument".

Sounds like a procedure with an out parameter...


> 3.  Since there's no copying going on outside the function, it would be OK
>     to allow returning a limited type.

There's no problem in returning a limited type.  I do it all the time.
What do mean here???


> 4.  In the function, the result would be materialized by storing into the
>     result variable, not by mentioning the value in a "return" statement.

Well, this _WOULD_ seem to cause a problem with returning limited
types, as it would require assignment.


/Jon
-- 
Jon Anthony
OMI, Belmont, MA 02178
617.484.3383
"Nightmares - Ha!  The way my life's been going lately,
 Who'd notice?"  -- Londo Mollari




^ permalink raw reply	[flat|nested] 63+ messages in thread

* Re: GOTO considered necessary (reworked)
  1997-06-16  0:00         ` John G. Volan
                             ` (2 preceding siblings ...)
  1997-06-17  0:00           ` Robert Dewar
@ 1997-07-21  0:00           ` Shmuel (Seymour J.) Metz
  3 siblings, 0 replies; 63+ messages in thread
From: Shmuel (Seymour J.) Metz @ 1997-07-21  0:00 UTC (permalink / raw)



John G. Volan wrote:
> 
> A programmer has a well-defined
> control structure in mind (e.g., FSA's, or loop continue), but the
> language does not provide a syntax for it (although such a syntax could
> easily be imagined).
> 
> If the structure were available in the language, of course there would
> be no question of using gotos for the same purpose.  Barring that, gotos
> can be used to _simulate_ this structure, but this will always be a
> dangerous practice, because the gotos are only at best a simulation of
> the actual construct the programmer has in mind.  Gotos lack
> "robustness"; certain important properties of the hypothetical structure
> (e.g., prevention of "fall-through" between states in an FSA) cannot be
> guaranteed except by programmer vigilance.

Much the same could be said of any control structures; the programmer
simulates the control structures that he has in mind using the control
sturctures that the language provides, e.g., if, while. Those control
structures "are only at best a simulation of
> the actual construct the programmer has in mind." Depending on what the programmer is attempting to simulate, the goto may be safer than the alternatives.
> 
> > I would also agree, if you said, "As a rule of thumb, if you think you
> > want to use a goto, think twice."

I would say that no matter what linguistic construct you use, you should
think twice. But then, I have a quaint predjudice in favor of programs
that work and that continue to work when they are modified. Program in
haste, debug at leisure is not prudent regardless of what language
constructs you use.
 
>   (Name       => "John G. Volan",
>    Employer   => "Texas Instruments Advanced C3I Systems, San Jose, CA",
>    Work_Email => "johnv@ti.com",
>    Home_Email => "johnvolan@sprintmail.com",

-- 

                        Shmuel (Seymour J.) Metz
                        Senior Software SE

The values in from and reply-to are for the benefit of spammers:
reply to domain eds.com, user msustys1.smetz or to domain gsg.eds.com,
user smetz.




^ permalink raw reply	[flat|nested] 63+ messages in thread

end of thread, other threads:[~1997-07-21  0:00 UTC | newest]

Thread overview: 63+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1997-06-11  0:00 GOTO considered necessary (reworked) Samuel Mize
1997-06-11  0:00 ` Bryce Bardin
1997-06-12  0:00 ` Anonymous
1997-06-12  0:00   ` John G. Volan
1997-06-16  0:00     ` Anonymous
1997-06-12  0:00   ` Robert Dewar
1997-06-12  0:00     ` John G. Volan
1997-06-13  0:00       ` Robert A Duff
1997-06-16  0:00         ` John G. Volan
1997-06-17  0:00           ` Robert A Duff
1997-06-25  0:00             ` Van Snyder
1997-06-17  0:00           ` Robert I. Eachus
1997-06-17  0:00           ` Robert Dewar
1997-06-17  0:00             ` Robert A Duff
1997-06-18  0:00               ` Spam Hater
1997-06-20  0:00               ` Robert Dewar
1997-06-20  0:00               ` Robert Dewar
1997-06-21  0:00                 ` Robert A Duff
1997-06-21  0:00                   ` Robert Dewar
1997-06-25  0:00               ` Wolfgang Gellerich
1997-06-25  0:00                 ` Michael F Brenner
1997-06-26  0:00                   ` Wolfgang Gellerich
1997-06-25  0:00                 ` Samuel T. Harris
1997-06-19  0:00             ` Karel Th�nissen
1997-06-19  0:00               ` Karel Th�nissen
1997-06-23  0:00               ` John G. Volan
1997-06-23  0:00                 ` Spam Hater
1997-06-23  0:00                 ` Robert Dewar
1997-06-24  0:00                   ` Brian Rogoff
1997-06-25  0:00                   ` Featuritis not always bad (was re: GOTO considered necessary) Karel Th�nissen
1997-06-26  0:00                     ` Robert Dewar
1997-06-26  0:00                       ` Karel Th�nissen
1997-06-25  0:00                 ` GOTO considered necessary (reworked) Karel Th�nissen
1997-06-23  0:00             ` John G. Volan
1997-07-21  0:00           ` Shmuel (Seymour J.) Metz
1997-06-12  0:00 ` Michael F Brenner
1997-06-17  0:00   ` Robert Dewar
1997-06-17  0:00     ` Robert A Duff
1997-06-20  0:00       ` Robert Dewar
1997-06-21  0:00         ` Robert A Duff
1997-06-21  0:00           ` Robert Dewar
1997-06-13  0:00 ` Robert A Duff
1997-06-14  0:00   ` Samuel Mize
1997-06-14  0:00     ` Matthew Heaney
1997-06-14  0:00   ` Samuel Mize
1997-06-14  0:00   ` Robert Dewar
1997-06-16  0:00     ` Robert A Duff
1997-06-17  0:00       ` Spam Hater
1997-06-17  0:00         ` Robert Dewar
1997-06-17  0:00           ` Spam Hater
1997-06-17  0:00           ` Robert A Duff
1997-06-19  0:00             ` John Herro
1997-06-25  0:00               ` Function result Van Snyder
1997-06-27  0:00                 ` Robert Dewar
1997-06-27  0:00                 ` Jon S Anthony
1997-06-20  0:00             ` GOTO considered necessary (reworked) Robert Dewar
1997-06-17  0:00         ` Robert A Duff
1997-06-19  0:00           ` Spam Hater
1997-06-16  0:00     ` Spam Hater
1997-06-17  0:00       ` Robert Dewar
1997-06-17  0:00         ` Spam Hater
1997-06-16  0:00 ` Anonymous
1997-06-16  0:00   ` Robert Dewar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox