For me, one of the best things to happen to FORTRAN was the introduction of the LOGICAL*1
type.
I quickly discovered that putting IMPLICIT LOGICAL*1 (A-Z)
at the top of every program was a life saver.
Knowing about this one line saved me hours of work debugging new code, where many typos resulted in defining a new variable rather than producing an error message.
The iconic example is:
INTEGER I
INTEGER SUM
SUM = 0
DO 10 I=1,10
10 SUM = SUM + I
PRINT 11, SUM
11 FORMAT (I10)
SUM = 0
DO 20 I=1.100
20 SUM = SUM + I
PRINT 21, SUM
21 FORMAT(I10)
STOP
END
One would expect the output to be:
55 5050
But in fact it is:
55 11
The typo might be obvious to you now, but imagine that the line is written along the top edge of a punch card by a misaligned dot-matrix printer with a bad ribbon.
Then imagine that that one card is buried in a deck of thousands of cards, and rather than being part of an immediately following PRINT
, the error doesn't become apparent until hundreds of lines later.
One could easily spend hours tracking down the typo.
But if we began the program with IMPLICIT LOGICAL*1 (A-Z)
, the compiler would quickly report the problem:
12 | DO 20 I=1.100 | 1 Error: Cannot convert REAL(4) to LOGICAL(1) at (1)
And the difference between a faint blurry comma and a faint blurry period becomes apparent.
But the IMPLICITLOGICAL*1(A,Z)
was only a work-around (albeit a very useful one).
The underlying problem was that the implicit definition of variables created a large potential for hard to detect errors.
I later moved on to "B" and "C", where every identifier had to be explicitly declared, and life was wonderful.
But then even newer languages appeared, and shockingly they had reverted back to implicit definitions.
Having seen the problems with FORTRAN, and their elimination with "B" and "C", why would the designers of the newer languages think that implicit declarations were a good idea?