Too many leaps of faith and too many appeals to authority.
Wirth's quest for one true small language led to an array of languages that only show that no, you can't have too simple of a language, or you will end up with a system that is too complex because of the language. The ones I remember from a very long discussion a decade or so ago:
- the meaningless distinctions between functions and procedures
- the very many iterations on loop constructs (in some of his languages there are three loop constructs with different rules. For example, you can break early from only one of them)
IIRC in Oberon BlackBox the necessity for complexity is just swept under the rug where system modules are allowed operations that are not available to user modules (IIRC it was function overloading and exceptions? I could be wrong).
In many ways Go is following Wirth's path of confusing language complexity, problem complexity and solution complexity. Yes, you can a wonderfully simple language with very few constructs. But if you have to write thousands of lines of boilerplate code to handle a problem, you haven't solved complexity. You've offloaded it onto the programmer.
As for "OMG, Wirth wrote an OS in Oberon, he was onto something"... Menuet OS is written in assembly, fits on a floppy disk, and can boot near-instantly on a 200 Mhz processor [1]. Does this mean we should ditch all the bad complex languages and switch to assembly?
Though I agree: most of present-day software is extremely bloated and inefficient.
As for the distinction between function and procedures, I halfway agree with you, with the caveat that having the compiler enforce that you don't try to use the return value from something that isn't producing one is pretty consistent with the static typing of those languages. If you don't like it nothing stops you from declaring everything to be functions.
The iterations on loop constructs reflects trying to find the set that maximises clarity with the minimum amount of syntax. At the same time the early exit issue is complex - one of Wirth's guiding principles was to strip out things he was not sure had an unambiguously good solution for implementation of and/or that promoted bad practices. At the time of his earlier language designs, the issue of single exit vs. multiple exit was still hotly debated, and while mostly debated in terms of functions, it also matters for things like loops. When I studied CS, we got docked points on exercises if we didn't stick to single exit (which greatly annoyed me). The changes in Wirth languages reflects changes in consensus on those issues.
I don't agree with all of Wirth's choices (or I'd have been an active Oberon user, rather than predominantly use Ruby), but in terms of the principles his languages are designed by his decisions are very much understandable. I wish more language designers had such a clear vision of what they wanted to achieve.
As for Menuet, Menuet is substantially larger (several times the number of lines of code) than the original Oberon in terms of source, so if anything it contributes to the point of just how compact Oberon is.
>Wirth's quest for one true small language led to an array of languages that only show that no, you can't have too simple of a language, or you will end up with a system that is too complex because of the language. The ones I remember from a very long discussion a decade or so ago:
>- the meaningless distinctions between functions and procedures
>- the very many iterations on loop constructs (in some of his languages there are three loop constructs with different rules. For example, you can break early from only one of them)
Arguably the problem here is Wirth didn't go far enough. You can design a simpler version of, say, Modula-3 by unifying statements and expression as in ML, and replacing the multiple iteration constructs with recursion, and guaranteeing tail recursion.
One of the key requirements of Wirth in terms of language construction was chasing languages that were not just simple but that 1. could be implemented simply (e.g. if a feature would significantly complicate the compiler, chances are he'd reject it), 2. where the implementation of a language construct was relatively unambiguously a near-optimal way of implementing that construct (e.g. he'd strip out things that might well be good if he did not feel he knew of a clearly superior way of implementing a feature at the language level), and 3. could be read in a very straight-forward way.
You can make lots of changes that makes for smaller and simpler languages, but Wirth was chasing a very specific set of goals that did not seek to minimise the syntax for the sake of minimising the syntax alone, but to seek a balance between language simplicity, compiler simplicity and a rigidity that forces (his idea of) readability.
His languages makes a lot more sense when evaluated in terms of those goals. Personally I admire his vision and execution a whole lot even though I prefer to use a language (Ruby) that is an utter mess evaluated by Wirth's criteria.
> Arguably the problem here is Wirth didn't go far enough.
The quest for langage simplicity in service of nothing is not actually useful.
There’s an entire class of esoteric langages called turing tarpits, and their entire MO is to be so simple they’re theoretically universal while being practically unusable. Brainfuck is probably the most famous but by no means the best / worst.
1) Ease of learning, which allows the community to grow.
2) Ease of implementation, which in turn allows you to have multiple implementations conforming to the same standard, which makes the language ecosystem more robust by removing implementation-specific bugs.
3) Ease of formal specification.
Obviously Brainfuck and other turing tarpits are esolangs and not meant for industrial use. There is however a golden mean that unites simplicity and pragmatism.
> Obviously Brainfuck and other turing tarpits are esolangs and not meant for industrial use.
You’re contradicting yourself here. Turing tarpits are literally the end point of the quest for simplicity, and are indeed easy to learn, easy to implement, and easy to formally specify.
I believe that it is very instructive for a programmer to spend some time with studying the evolution of the many programming languages created by Wirth, from Algol W and PL/360 to Oberon.
Because all his languages are relatively simple it is feasible to understand why some features are included or not and why they are implemented in a certain way and not in another.
While all his languages are interesting, they also have various shortcomings that make their use difficult in many more complex applications.
The main importance of the languages designed by Wirth is not in what they have been used directly to do, but in their great influence over many other more widely used programming languages.
Frequently, the innovations made popular by Wirth languages had already been introduced much earlier in other programming languages, but nobody was aware of that until Wirth made them well known.
For example, after Hoare introduced the "case" keyword, but with a syntax that was only a minimal improvement over the Algol "switch", Wirth introduced in Pascal (1970) the modern form of the "case" structure, with labeled alternatives (instead of using their ordinal position).
After that, practically all languages have included some variant of the labeled "case" (even when the older "switch" keyword was retained, like in C).
Nevertheless, it appears that neither Hoare nor Wirth nor anyone else was aware that McCarthy had introduced in LISP already at the end of 1958 the special form "select", with a syntax that was practically identical to the Pascal labeled "case", except that the LISP "select" had much fewer restrictions than the Pascal "case", because the labels could be not only constants but also expressions and the "select" could also be used as an expression, not only as a statement, like in Pascal.
There are also other examples like that, e.g. the modules of Modula have been much better known and influential than the modules of XEROX Mesa, which inspired Modula, and so on.
In any case the influence of Wirth over programming languages has been huge, even if many of the ideas propagated by him were not necessarily encountered for the first time in his work.
Wirth's quest for one true small language led to an array of languages that only show that no, you can't have too simple of a language, or you will end up with a system that is too complex because of the language. The ones I remember from a very long discussion a decade or so ago:
- the meaningless distinctions between functions and procedures
- the very many iterations on loop constructs (in some of his languages there are three loop constructs with different rules. For example, you can break early from only one of them)
IIRC in Oberon BlackBox the necessity for complexity is just swept under the rug where system modules are allowed operations that are not available to user modules (IIRC it was function overloading and exceptions? I could be wrong).
In many ways Go is following Wirth's path of confusing language complexity, problem complexity and solution complexity. Yes, you can a wonderfully simple language with very few constructs. But if you have to write thousands of lines of boilerplate code to handle a problem, you haven't solved complexity. You've offloaded it onto the programmer.
As for "OMG, Wirth wrote an OS in Oberon, he was onto something"... Menuet OS is written in assembly, fits on a floppy disk, and can boot near-instantly on a 200 Mhz processor [1]. Does this mean we should ditch all the bad complex languages and switch to assembly?
Though I agree: most of present-day software is extremely bloated and inefficient.
[1] https://en.wikipedia.org/wiki/MenuetOS