[comp.lang.misc] Lessons from Algol

sakkinen@tukki.jyu.fi (Markku Sakkinen) (05/02/90)

In article <1990Apr27.171252.9503@maths.nott.ac.uk> anw@maths.nott.ac.uk (Dr A. N. Walker) writes:
>In article <4277@tukki.jyu.fi> sakkinen@jytko.jyu.fi (Markku Sakkinen) writes:
>>Pray mention one or two important lessons from Algol that C has learned
>>but "Ada, Pascal and others" haven't. My imagination fails.
>
>	Well, important is your word, not mine.[...]
If you don't think those things are important, why did you advertise them?

> ...
>	I'll leave Ada and others to others.
I assume, in part because you realised that your critique
mostly doesn't hold against Ada.

All your examples seem to be about features that are in Algol 68
but not in Algol 60. Let's quote C.A.R. Hoare once again (approximately):
"Algol 60 was a great improvement over all its predecessors and most of
its successors." Of course many of the additional features of Algol 68
_are_ good and useful.

Many people have drawn the lesson from the combined Algol 60 - Algol 68
experience (and from some other experiences with programming languages)
that the quality and usefulness of a language does not increase linearly
with the number of features.

>  a) Assignment ops:
>	Algol:  a[something very messy] +:= 1;
>	C:	a[something_very_messy]++;	/* or, += 1, of course */
>	Pascal:  ...
I agree that they are a good idea, but Ada has got them too (Cobol as well).
Score remains 0.

>  b) Brevity (same example, I suppose):
>	Algol:  while foo do a[i +:= 1] +:= 1 od;
>	...
Expressions with side effects are not very fashionable in software
engineering circles. Extreme brevity is not so important as in the
days of the Teletype 33. No point awarded.

>  c) Formatted transput:
>	Algol:  print (("i =", i, ", x =", fixed (x, 5, 2), newline, newline));
>	     or printf (($ "i =" dd, ", x =" ddd.dd 2l $, i, x));
>	C:	printf ("i =%d, x =%5.2f\n\n", i, x);
>			/* I prefer the C, really */
You must be kidding! And think about scanf (always remember the '&'s).
One bad thing about the formatted I/O of C is that the connexion between
format items and data items cannot be done at compile time.
>	Pascal: [something pretty horrible involving lots of write(ln)s, and
>		 probably extra begin-ends]
No luck. Perhaps you ought to learn a little more about Pascal before
criticising it:
	writeln ("i =", i, ", x =", x:5:2); writeln
(Of course, if one really wants adequate I/O facilities, one must look at
Cobol, PL/1, or Fortran.)

>  d) Pointers to [somewhat] arbitrary objects and parts of objects:
That is a very mixed blessing, in view of dangling pointers and
aliassing problems.
>	Algol: [adapted from a list-processing package]
> ...
>		comment
>		  Algol doesn't have the &&, || operators, so the conditions
>		  are a little convoluted compared with C.  The "then" line,
>		  however, replaces a complicated malloc + assignments.
>		comment
Standard Pascal has the same problem, but Ada has got "if then"
and "or else". Neither Pascal nor Ada allows conditional _expressions_
like both Algols and C. Both omissions combined make the following
Pascal example more complicated: here you score.
>	C:	list *dictionary = 0;
> ...
>			if (*dictp == 0 || strcmp ((*dictp)->word, aword) > 0)
                                                                         ^^^
This is obviously a typo, and "< 0" was meant.
> ...

>	Pascal: ???.  No equivalent that I've ever seen in a book on data
>		structures or that I've managed to get past a compiler.
There _are_ books on data structures in Pascal, but this example is too
easy to merit looking up one from the library..
However, you have a point in that one really needs some kind of work-around.
Presumably your "list" is meant to be a record consisting of a (pointer
to) a string and a pointer to another list, so it isn't a great sacrifice
to allocate an extra list object.

		var dictionary: ^list;
		dictionary := new (list);
		dictionary.next := nil;
		dictionary.word := nil; (* for safety's sake *)

		procedure insert (string aword);
		   var dictp, aux: ^list;
                   function higher: boolean;
		      begin
		         aux := dictp^.next;
		         if aux = nil then higher := false
		         else higher := stringlt (aux^.word, aword)
		      end;
                   function notsame: boolean;
		      begin
		         if aux = nil then notsame := true
		         else notsame := stringlt (aword, aux^.word)
		      end;

		   begin
		      dictp := dictionary;
		      while higher do dictp := aux;
		      if notsame then begin
		         aux := new (list);
		         aux^.word := aword;
		         aux^.next := dictp^.next;
		         dictp^.next := aux
                      end
                   end;

The above presupposes that a type "string" is defined and
there is a Boolean function "stringlt" for comparing "string" objects.

>  e) Array aliassing [JLG, please don't look!]:
>	Algol:  [10] int a; [] int b = a[@7];
>	C:	int a[10], *b = a+7;	/* more-or-less */
>	Pascal: ???
I refuse to consider this an advantage. If EQUIVALENCE in Fortran is
such a bad thing as most people say today, why would a similar feature
in C be good? Ada does have array slices, which are more well-behaved
objects.

>	Lots of others, in the type/mode structure, expressions as statements,
>order of declarations [ie, not rigid], etc.  I haven't bunged any of the above
>through a compiler, so please excuse any typos.
The order or declarations is in fact rigid in current standard Pascal,
but not in Ada (nor in the proposed Extended Pascal). As regards expressions
as statements - I prefer a pure statement language (like Algol 60) or a
pure expression language (like Algol 68). C hasn't even learned that it's
mostly harmful to jump into the middle of control structures.

I agree that the ability to define pointers to functions is an advantage
of C over Pascal and Ada. Otherwise C's type structure is inferior,
even disregarding the counterintuitive syntax of type definitions.
For instance, there is no Boolean type, the status of enumerations
is vague, and there is nothing similar to the conformant arrays
of standard Pascal, not to speak of the dynamic arrays of Algol.

Markku Sakkinen
Department of Computer Science
University of Jyvaskyla (a's with umlauts)
Seminaarinkatu 15
SF-40100 Jyvaskyla (umlauts again)
Finland
          SAKKINEN@FINJYU.bitnet (alternative network address)

peter@ficc.uu.net (Peter da Silva) (05/03/90)

> (Of course, if one really wants adequate I/O facilities, one must look at
> Cobol, PL/1, or Fortran.)

Fortran? Adequate I/O facilities? Well, I must admit that Fortran I/O has
lots of *features*, but how do you do:

	printf("The answer is %d, not %d\n", ans, resp);

in Fortran? The best I can come up with on the top of my head is something
like:

	WRITE (BUFFER,100) PRINTLENGTH(ANS),PRINTLENGTH(RESP)
 100	FORMAT('(''The answer is '',',I1,'I,'',not '',',I1,'I'')')
	WRITE (5,BUFFER) ANS,RESP

One time I actually went to the trouble of implementing printf in Fortran to
make free-form output easier for one application.

> I agree that the ability to define pointers to functions is an advantage
> of C over Pascal and Ada. Otherwise C's type structure is inferior,
> even disregarding the counterintuitive syntax of type definitions.

What counterintuitive syntax? Declare them as you use them. The
counterintuitive part comes from the fact that indirection is prefix
rather than postfix. If you want to slam C for something, at least
slam the right thing!
-- 
 _--_|\  `-_-' Peter da Silva. +1 713 274 5180.      <peter@ficc.uu.net>
/      \  'U`  Have you hugged your wolf today?  <peter@sugar.hackercorp.com>
\_.--._/       Disclaimer: commercial solicitation by email to this address
      v                    is acceptable.

ttw@lambda.UUCP (Tony Warnock) (05/04/90)

With respect to the C statement:
 
     printf("The answer is %d, not %d\n", ans, resp)
 
one can use the following Fortran statement
 
     write(*,*)' The answer is',ans,' not',resp
 
which seems as simple as the C version. The suggested
 
       WRITE (BUFFER,100) PRINTLENGTH(ANS),PRINTLENGTH(RESP)
  100  FORMAT('(;;The answer is '',',I1,','',not '',',I1,;I;;)')
       WRITE(5,BUFFER)ANS,RESP
 
seems to be somewhat verbose. ( Of couse my suggestion could be
in upper case if desired. )

peter@ficc.uu.net (Peter da Silva) (05/04/90)

> With respect to the C statement:

>      printf("The answer is %d, not %d\n", ans, resp)

> one can use the following Fortran statement

>      write(*,*)' The answer is',ans,' not',resp

Will this not pad the numbers "ans" and "resp" with spaces? Fortran I/O is
heavily oriented towards columnar output, to the extent that it's all but
impossible to avoid this.
-- 
`-_-' Peter da Silva. +1 713 274 5180.      <peter@ficc.uu.net>
 'U`  Have you hugged your wolf today?  <peter@sugar.hackercorp.com>
@FIN  Commercial solicitation *is* accepted by email to this address.

ttw@lambda.UUCP (Tony Warnock) (05/05/90)

In article <XT73_W7ggpc2@ficc.uu.net>, peter@ficc.uu.net (Peter da Silva) writes:
> > With respect to the C statement:
> 
> >      printf("The answer is %d, not %d\n", ans, resp)
> 
> > one can use the following Fortran statement
> 
> >      write(*,*)' The answer is',ans,' not',resp
> 
> Will this not pad the numbers "ans" and "resp" with spaces? Fortran I/O is
> heavily oriented towards columnar output, to the extent that it's all but
> impossible to avoid this.
> -- 
> `-_-' Peter da Silva. +1 713 274 5180.      <peter@ficc.uu.net>
>  'U`  Have you hugged your wolf today?  <peter@sugar.hackercorp.com>
> @FIN  Commercial solicitation *is* accepted by email to this address.


         Fortran allows both tabulated and free form output. The
         following program and associated output show the
         formatting used by the default libraries at Los Alamos.
         (Your milage may vary.)
 
 
      PROGRAM test(tty,input=tty)
      IMPLICIT INTEGER (a-z)
      ans=5
      resp=4
      WRITE(*,*)' The answer is ',ans,'not ',resp
      ans=5555555555
      resp=4444444444
      WRITE(*,*)' The answer is ',ans,'not ',resp
      END
 
   The answer is 5,  not 4
   The answer is 5555555555,  not 4444444444
 
 
         The Fortran standard allows for either commas or blanks
         as separators for numerical list-directed output.
         Character output has no separators.

staff@cadlab.sublink.ORG (Alex Martelli) (05/09/90)

>          Fortran allows both tabulated and free form output. The

...at the whim of the COMPILER, alas!  Fortran-386 by Green Hills,
release 1.8.4, under SCO Unix/386 System V, for this program:
	i4=4
	i5=5
	write(*,*) 'The answer is',i4,'not',i5
	stop
	end
outputs:

The answer is           4 not           5

while many others will indeed approximate a C's printf.  

What a pity that the Fortran standard committee should have chosen
to embark on such ambitious new language design, rather than just
concentrate on these irritating non-portabilities that make it SO
hard to build solid, portable, "sellable" applications in Fortran 77!

(Does Fortran 90, indeed, offer a simple way to emulate a printf() in a
GUARANTEED portable way?  I really hope so, at least).


[MY own opinions - NOT necessarily my employer's!]
-- 
Alex Martelli - CAD.LAB s.p.a., v. Stalingrado 45, Bologna, Italia
Email: (work:) staff@cadlab.sublink.org, (home:) alex@am.sublink.org
Phone: (work:) ++39 (51) 371099, (home:) ++39 (51) 250434; 
Fax: ++39 (51) 366964 (work only; any time of day or night).