[comp.lang.pascal] The gaping hole left by var parameters ...

markh@csd4.milw.wisc.edu (Mark William Hopkins) (05/25/88)

What's wrong with var parameters?
Try these out to see how they compile and run:
Enjoy ...

(1) ALIASING:
      procedure Alias1(var X, Y : integer);
      begin
	 X := X + 1; Y := X + 1
      end;

      ...

   begin
      A := 3; Alias1(A, A); writeln(A)
   end.

   You might say that the whole is more than the sum of its parts ...
--------------------------------------------------------------------------------
      procedure Alias2(X : integer; var Y : integer);
      begin
	 X := X + Y + 1; A := A + Y + 1
      end;

      ...

    begin
       A := 3; Alias2(A, A); writeln(A)
    end.
--------------------------------------------------------------------------------
(2) INSIDUOUS SIDE-EFFECTS:

     function Insiduous1(var X, Y : integer; Z : integer) : boolean;
     begin
	X := X + 1; Y := Y + X; Insiduous1 := (X <= Z)
     end;
 
     ...

   begin
      A := 0; B := 0; C := 5;
      while Insiduous1(A, B, C) do {nothing};
      writeln('The sum of the integers from 0 to ', C:1, ' is :', B)
   end.
--------------------------------------------------------------------------------
      function ForLoop(var I, Bound : integer) : boolean;
      begin
	 ForLoop := (I < Bound);
	 I := I + 1
      end;

      ...

    begin
       I := 0; while ForLoop(I, 3) do A[I] := 2*I;
       I := 0; while ForLoop(I, 3) do write(A[I]:1, ' ');
       writeln
    end.

Why even use a for loop with this dandy available?
--------------------------------------------------------------------------------
    function Insiduous2(var X : integer) : integer;
    var Dummy : integer;
    begin
       if X >= 0 then begin
	  writeln('The final result is :', X:1)
	  Insiduous2 := X
       end
       else begin
	  Dummy := X + Insiduous2(X + 1);
	  writeln('The intermediate result was :', Dummy);
	  Insiduous2 := Dummy
       end
    end;

   begin
      A := -10;
      writeln(Insiduous2(A))
   end.

   This illustrates that an entire program could effectively be executed in one
write statement.
--------------------------------------------------------------------------------
String processing in Pascal?!

     function String : char;
     const PERIOD = '.';
     begin
	write('This is an arbitrary string');
	String := PERIOD
     end

     ...

   begin
      writeln(String)
   end;

   The function declaration is effectively the same as the assignment:

               String := 'This is an arbitrary string.';

bobdi@omepd (Bob Dietrich) (05/27/88)

In article <5879@uwmcsd1.UUCP> markh@csd4.milw.wisc.edu (Mark William Hopkins) writes:
>What's wrong with var parameters?
>Try these out to see how they compile and run:
>Enjoy ...

I see you've rediscovered aliasing and functions having side-effects, but
you're certainly not pointing out anything new. Languages that have a
variable parameter mechanism and scoping have always had this problem, and
it isn't likely to go away. Likewise functions with side-effects. Both
mechanisms have their drawbacks, but are generally too useful to plug all the
holes (the old "double-edged sword" argument). Attempts are made from time to
time, but they usually just force the programmer into an alternate and
perhaps less natural construct (like returning a result in a parameter
instead of as a function result).

Reminds me of a Pascal compiler brought out a few years ago by a
semiconductor company (not my current employer). The implementors had
read that functions with side-effects are evil, and so their functions
disallowed side-effects (Hmmmm. Did they disallow all file operations? I
can't remember). Anyway, it turns out they also distended procedures so that
they could return values just like functions. So if you wanted a function with
side-effects, you had to call it a procedure returning a value. Someone wanted
good marketing copy, but also saw a need to be filled.

See the Pascal Validation Suite for many dandy examples of aliasing and
side-effects.

> [...]
>--------------------------------------------------------------------------------
>      function ForLoop(var I, Bound : integer) : boolean;
>      begin
>	 ForLoop := (I < Bound);
>	 I := I + 1
>      end;
>
>      ...
>
>    begin
>       I := 0; while ForLoop(I, 3) do A[I] := 2*I;
>       I := 0; while ForLoop(I, 3) do write(A[I]:1, ' ');
>       writeln
>    end.
>
>Why even use a for loop with this dandy available?

I sure hope this fragment doesn't make it through any purported Pascal
processor you have! For the invocations of ForLoop to work, the second
parameter should be a value parameter, and the declaration as follows:

      function ForLoop(var I: integer; Bound : integer) : boolean;

As far as the question goes, when I actually DO use a for-statement, I want
to use it for other than counting integers upwards. I'm just as likely to
use a for-statement with an enumeration, subrange, or the char type. My
programs have few if any variables declared as integer; instead, I use
subranges. I don't know how the variable A is declared in your fragment, but
it looks like its index type begins at one; therefore, any variable used to
index A should probably have a lower bound of one as well. Since Pascal uses
name type compatibility, your function would have few if any uses in any of
my programs.

You might also note that a function like this will get errors if the counter
variable is at the last value of its type (e.g., "ForLoop(I, maxint)").

				Bob Dietrich
				Intel Corporation, Hillsboro, Oregon
				(503) 696-4400 or 2092(messages x4188,2111)
		usenet:		tektronix!ogcvax!omepd!bobdi
		  or		tektronix!psu-cs!omepd!bobdi
		  or		ihnp4!verdix!omepd!bobdi

markh@csd4.milw.wisc.edu (Mark William Hopkins) (05/29/88)

In article <3499@omepd> bobdi@omepd.UUCP (Bob Dietrich) writes:
>In article <5879@uwmcsd1.UUCP> markh@csd4.milw.wisc.edu (Mark William Hopkins) writes:
>>What's wrong with var parameters?
>>Try these out to see how they compile and run:
>>Enjoy ...
>
>I see you've rediscovered aliasing and functions having side-effects, but
>you're certainly not pointing out anything new. Languages that have a
>variable parameter mechanism and scoping have always had this problem, and
>it isn't likely to go away. Likewise functions with side-effects. Both
>mechanisms have their drawbacks, but are generally too useful to plug all the
>holes (the old "double-edged sword" argument). Attempts are made from time to
>time, but they usually just force the programmer into an alternate and
>perhaps less natural construct (like returning a result in a parameter
>instead of as a function result).

You have a point on one matter: as long a Pascal does not allow files-as-values
side-effects must occur be allowed in functions.  Also, as long as Pascal does 
not allow the one to construct functions that can return MULTIPLE values, one
will need to write procedures with var parameters in their stead.

Example:

		 procedure Switch(var A, B : char);
		 var C : char;
		 begin
		    C := A; A := B; B := C
                 end;

called in the environment 

			 Switch (X, Y)

would become:

		function Switch(A, B : char) --> (char, char);
		var C : char;
		begin
		   C := A; A := B; B := C;
		   return (A, B)
                end;

called as follows:

		      (X, Y) := Switch(X, Y)

The function could even be simplified to:
	       
	           function Switch(A, B : char) --> (char, char);...
	           begin return (B, A) end;

so that it would no longer be necessary to declare it, it could be directly 
substituted into the calling environment:

		         (X, Y) := (Y, X)  

These kinds of simplifications would result in general.  The cost is modest:
introducing a new type constructor for either LISTS or for variable-sized
arrays (TUPLES) and introducing functions that return values of such types.