1. goto considered essential, revisited

This conversation seems to be wandering away from my original
point. I am NOT advocating the addition of the goto statement
to Euphoria. In my 38 years of experience as a systems
programmer, I have seen much confusion caused by the unrestricted
use of goto statements (or, before 1977, branch instructions), 
and I have spent literally thousands of hours untangling and 
rewriting the resulting spaghetti code.  What I AM advocating is 
the addition of a very constrained control flow construct that 
will allow graceful coding of abnormal procedure returns, AND 
NOTHING ELSE. Please read the following code carefully.

    function    copyfile
    (
        sequence    input_file_name
        sequence    output_file_name
    )
        integer     input_file_nr
        integer     output_file_nr
        object      line
   
        input_file_nr = open ( input_file_name, "r" )
        exception cant_open_input_file if input_file_nr = -1
        output_file_nr = open ( output_file_name, "w" )
        exception cant_open_output_file if output_file_nr = -1
        while 1 do
            line = gets ( input_file_nr )
            exit if atom ( line )
            puts ( output_file_nr, line )
        end while
        close ( input_file_nr )
        close ( output_file_nr )
        return outcome__success
        --
        -- Exception handlers must follow the main body of 
        -- the function or procedure. They are ONLY executed
        -- via an exception statement in the main body.
        --
        when cant_open_input_file do
            return outcome__cant_open_input_file
        when cant_open_output_file do
            close ( input_file_nr )
            return  outcome__cant_open_output_file
   
    end procedure -- copyfile

In considering this code, remember that, in a real world case,
a function might detect 5 or 6 abnormal conditions, and, for
each one, need to perform several cleanup actions before returing
an appropriate error code. The proposed exception handling
construct is merely a disciplined mechanism for removing such
actions from the main (non-error) logic, with the intent of 
making that logic easier to read.

Tom

new topic     » topic index » view message » categorize

2. Re: goto considered essential, revisited

Tom Dailey wrote:
> 
> 
> This conversation seems to be wandering away from my original
> point. I am NOT advocating the addition of the goto statement
> to Euphoria. In my 38 years of experience as a systems
> programmer, I have seen much confusion caused by the unrestricted
> use of goto statements (or, before 1977, branch instructions), 
> and I have spent literally thousands of hours untangling and 
> rewriting the resulting spaghetti code.  What I AM advocating is 
> the addition of a very constrained control flow construct that 
> will allow graceful coding of abnormal procedure returns, AND 
> NOTHING ELSE. Please read the following code carefully.
> 
>     function    copyfile
>     (
>         sequence    input_file_name
>         sequence    output_file_name
>     )
>         integer     input_file_nr
>         integer     output_file_nr
>         object      line
>    
>         input_file_nr = open ( input_file_name, "r" )
>         exception cant_open_input_file if input_file_nr = -1
>         output_file_nr = open ( output_file_name, "w" )
>         exception cant_open_output_file if output_file_nr = -1
>         while 1 do
>             line = gets ( input_file_nr )
>             exit if atom ( line )
>             puts ( output_file_nr, line )
>         end while
>         close ( input_file_nr )
>         close ( output_file_nr )
>         return outcome__success
>         --
>         -- Exception handlers must follow the main body of 
>         -- the function or procedure. They are ONLY executed
>         -- via an exception statement in the main body.
>         --
>         when cant_open_input_file do
>             return outcome__cant_open_input_file
>         when cant_open_output_file do
>             close ( input_file_nr )
>             return  outcome__cant_open_output_file
>    
>     end procedure -- copyfile
> 
> In considering this code, remember that, in a real world case,
> a function might detect 5 or 6 abnormal conditions, and, for
> each one, need to perform several cleanup actions before returing
> an appropriate error code. The proposed exception handling
> construct is merely a disciplined mechanism for removing such
> actions from the main (non-error) logic, with the intent of 
> making that logic easier to read.
> 
> Tom


Hello Tom,

Try please:

     function    copyfile
     (
         sequence    input_file_name
         sequence    output_file_name
     )
         integer     input_file_nr
         integer     output_file_nr
         object      line
    
         input_file_nr = open ( input_file_name, "r" )
--         exception cant_open_input_file if input_file_nr = -1
  if input_file_nr = -1 then 
      return outcome__cant_open_input_file 
  end if
         output_file_nr = open ( output_file_name, "w" )
--         exception cant_open_output_file if output_file_nr = -1

  if output_file_nr = -1 then 
      close(input_file_nr) 
      return outcome__cant_open_output_file 
  end if

         while 1 do
             line = gets ( input_file_nr )
             exit if atom ( line )
             puts ( output_file_nr, line )
         end while
         close ( input_file_nr )
         close ( output_file_nr )
         return outcome__success
--         --
--         -- Exception handlers must follow the main body of 
--         -- the function or procedure. They are ONLY executed
--         -- via an exception statement in the main body.
--         --
  --       when cant_open_input_file do
    --         return outcome__cant_open_input_file
      --   when cant_open_output_file do
        --     close ( input_file_nr )
          --   return  outcome__cant_open_output_file
   
    end function  -- procedure -- copyfile


You can do it just now, program can *jump* from *any* point of a procedure
or a function body. Just put 'return' in a procedure, and 'return something'
in a function.

Same thing with loops - just put 'exit' and program jumps to the next
operator after 'end for' or 'end while'.  

Maybe I just do not understand your problem here ...

But these 'return' and 'exit' work good, at least in your example.
You can have many of these returns and exits in a body of every blok.

A single door to enter a room but as many windows as you wish to
jump out, so to say.

Good Luck!

HTH.

Regards,
Igor Kachan
kinz at peterlink.ru

new topic     » goto parent     » topic index » view message » categorize

3. Re: goto considered essential, revisited

Igor Kachan wrote:
> 
> Tom Dailey wrote:
> > 
> > 
> > This conversation seems to be wandering away from my original
> > point. I am NOT advocating the addition of the goto statement
> > to Euphoria. In my 38 years of experience as a systems
> > programmer, I have seen much confusion caused by the unrestricted
> > use of goto statements (or, before 1977, branch instructions), 
> > and I have spent literally thousands of hours untangling and 
> > rewriting the resulting spaghetti code.  What I AM advocating is 
> > the addition of a very constrained control flow construct that 
> > will allow graceful coding of abnormal procedure returns, AND 
> > NOTHING ELSE. Please read the following code carefully.
> > 
> >     function    copyfile
> >     (
> >         sequence    input_file_name
> >         sequence    output_file_name
> >     )
> >         integer     input_file_nr
> >         integer     output_file_nr
> >         object      line
> >    
> >         input_file_nr = open ( input_file_name, "r" )
> >         exception cant_open_input_file if input_file_nr = -1
> >         output_file_nr = open ( output_file_name, "w" )
> >         exception cant_open_output_file if output_file_nr = -1
> >         while 1 do
> >             line = gets ( input_file_nr )
> >             exit if atom ( line )
> >             puts ( output_file_nr, line )
> >         end while
> >         close ( input_file_nr )
> >         close ( output_file_nr )
> >         return outcome__success
> >         --
> >         -- Exception handlers must follow the main body of 
> >         -- the function or procedure. They are ONLY executed
> >         -- via an exception statement in the main body.
> >         --
> >         when cant_open_input_file do
> >             return outcome__cant_open_input_file
> >         when cant_open_output_file do
> >             close ( input_file_nr )
> >             return  outcome__cant_open_output_file
> >    
> >     end procedure -- copyfile
> > 
> > In considering this code, remember that, in a real world case,
> > a function might detect 5 or 6 abnormal conditions, and, for
> > each one, need to perform several cleanup actions before returing
> > an appropriate error code. The proposed exception handling
> > construct is merely a disciplined mechanism for removing such
> > actions from the main (non-error) logic, with the intent of 
> > making that logic easier to read.
> > 
> > Tom
> 
> 
> Hello Tom,
> 
> Try please:
> 
> }}}
<eucode>
> 
>      function    copyfile
>      (
>          sequence    input_file_name
>          sequence    output_file_name
>      )
>          integer     input_file_nr
>          integer     output_file_nr
>          object      line
>     
>          input_file_nr = open ( input_file_name, "r" )
> --         exception cant_open_input_file if input_file_nr = -1
>   if input_file_nr = -1 then 
>       return outcome__cant_open_input_file 
>   end if
>          output_file_nr = open ( output_file_name, "w" )
> --         exception cant_open_output_file if output_file_nr = -1
> 
>   if output_file_nr = -1 then 
>       close(input_file_nr) 
>       return outcome__cant_open_output_file 
>   end if
> 
>          while 1 do
>              line = gets ( input_file_nr )
>              exit if atom ( line )
>              puts ( output_file_nr, line )
>          end while
>          close ( input_file_nr )
>          close ( output_file_nr )
>          return outcome__success
> --         --
> --         -- Exception handlers must follow the main body of 
> --         -- the function or procedure. They are ONLY executed
> --         -- via an exception statement in the main body.
> --         --
>   --       when cant_open_input_file do
>     --         return outcome__cant_open_input_file
>       --   when cant_open_output_file do
>         --     close ( input_file_nr )
>           --   return  outcome__cant_open_output_file
>    
>     end function  -- procedure -- copyfile
> 
> </eucode>
{{{

> 
> You can do it just now, program can *jump* from *any* point of a procedure
> or a function body. Just put 'return' in a procedure, and 'return something'
> in a function.
> 
> Same thing with loops - just put 'exit' and program jumps to the next
> operator after 'end for' or 'end while'.  
> 
> Maybe I just do not understand your problem here ...
> 
<snip>

Yeah, procedures and functions with multiple returns, along with if/else/elsif
structures are the gotos of Euphoria.

I like that quote "A single door to enter a room, but many windows to jump out."
That's clever.

With yield(), though, there'll be more than one door as well!

--
"The author regrets that he is unable to reconcile himself to the
thoughtful point of view you have expressed. However, it must be kept
in mind that being raised in different cultures and different places can
result in such differences of viewpoint between individuals.
The author is from planet Earth." [author unknown]

j.

new topic     » goto parent     » topic index » view message » categorize

4. Re: goto considered essential, revisited

Igor Kachan wrote:

[snip]

> 
> Hello Tom,
> 
> Try please:
> 
> }}}
<eucode>
> 
>      function    copyfile
>      (
>          sequence    input_file_name
>          sequence    output_file_name
>      )
>          integer     input_file_nr
>          integer     output_file_nr
>          object      line
>     
>          input_file_nr = open ( input_file_name, "r" )
> --         exception cant_open_input_file if input_file_nr = -1
>   if input_file_nr = -1 then 
>       return outcome__cant_open_input_file 
>   end if
>          output_file_nr = open ( output_file_name, "w" )
> --         exception cant_open_output_file if output_file_nr = -1
> 
>   if output_file_nr = -1 then 
>       close(input_file_nr) 
>       return outcome__cant_open_output_file 
>   end if
> 
>          while 1 do
>              line = gets ( input_file_nr )
>              exit if atom ( line )
>              puts ( output_file_nr, line )
>          end while
>          close ( input_file_nr )
>          close ( output_file_nr )
>          return outcome__success
> --         --
> --         -- Exception handlers must follow the main body of 
> --         -- the function or procedure. They are ONLY executed
> --         -- via an exception statement in the main body.
> --         --
>   --       when cant_open_input_file do
>     --         return outcome__cant_open_input_file
>       --   when cant_open_output_file do
>         --     close ( input_file_nr )
>           --   return  outcome__cant_open_output_file
>    
>     end function  -- procedure -- copyfile
> 
> </eucode>
{{{

> 
> You can do it just now, program can *jump* from *any* point of a procedure
> or a function body. Just put 'return' in a procedure, and 'return something'
> in a function.
> 
> Same thing with loops - just put 'exit' and program jumps to the next
> operator after 'end for' or 'end while'.  
> 
> Maybe I just do not understand your problem here ...
> 
> But these 'return' and 'exit' work good, at least in your example.
> You can have many of these returns and exits in a body of every blok.

Hello again Tom,

Let me to offer more refined version of the above function.
It is rewritten in pure EU code now, not in pseudocode,
and as I like to see it, just as example - to really copy a file,
the 'system' command may be better:

-- file.exu
  function copy_text_file(
	      sequence in,  -- name of the input file
	     sequence out)  -- name of the output file

	  integer in_fn, out_fn -- the file numbers
	   object line -- the buffer string
     
	  in_fn = open(in, "r")

   if in_fn = -1 then -- can not open the input file
       return -1      -- code for bad input file
   end if 

	out_fn = open(out, "w")

   if out_fn = -1 then  -- can not open the output file,
       close(in_fn)     -- but input file it open already
	return -2       -- code for bad output file
   end if
 
	  while 1 do
	      line = gets(in_fn)
		  if sequence(line) then
		     puts(out_fn, line)
		  else  
		     close(in_fn )
		     close(out_fn)
		     return 1 -- code for success
		  end if   
	  end while
   end function -- copy_text_file()
    
   integer i
    
   i= copy_text_file("file.exu","file.exuu")
    
   ? i
-- end of file.exu


See please, inside a subprogram, program can jump from the loop
body just with the 'return' command too, if it is a convenient
jump for your function or procedure. 

To be without 'goto', Euphoria has the very clear and very flexible
syntax, be sure. Just try it to do what you want.

Good Luck!

Regards,
Igor Kachan
kinz at peterlink.ru

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu