I've seen some really poor hobbyist and non-commercial languages. But I'll stay with just the commercial ones for comment, today. Of all the commercial languages I've used to write programs for pay, RPG II is the worst. COBOL comes in 2nd.
I used to have to "toggle in" my programs in binary machine code (memorized as octal or hex) using switches. And I consider machine language (not even assembly) programs far more enjoyable than RPG II.
I still do quite a bit of assembly coding -- there are times where there remains to this day no other alternative. So I enjoy it quite a bit and do not find it the least bit sucky. Quite the opposite. It is on a par with some of the languages I enjoy most of all, in fact. All of the semantics of the core processor is available; there are NO limitations of any kind and the room for exploring your creativity is wide open when using it. So I can't agree with anyone who considers assembly a problem. If they do, then programming is "just a business" to them and nothing more.
If you want to see some truly UGLY syntax for what would otherwise be BEAUTIFUL semantics, take a look at C11's lambda syntax. Then try and write something that is as efficient and clean as this (available as early as in Metaware's High C compiler from the mid 1980's):
iterator primes( int a, int b ) : int;
int main( void ) {
int count= 0;
for p in primes(500, 10000) {
printf( "%d\n", p );
++count;
}
printf( "For a count of %d\n", count );
return 0;
}
Very simple, easy to read, and the primes() iterator just uses yield() to provide successive values. primes() keeps its activation frame on the same stack as main() does -- there is nothing new here and no complicated delegate structures, either. No need to store the results in a vector first, as the for loop is called with each successive value, which can then be destroyed and not kept. Very low memory requirements, very fast, very simple to read and write.
Now try that in C11 without the use of lists, stacks, arrays, etc. Sure, you can use a lambda as the for() loop body and pass that into primes. But look at the syntax required to create the closure for count. Sad thing is, the concepts have long since been worked out very cleanly decades before and much, much better, I think. The approved syntax is rube goldberg by comparison. Sickening how such beauty can be turned into scarred ugliness.
Here is the above in C (with full implementation of primes()) and even then it's not the same thing. But at least it is roughly as general purpose if not nearly as clean:
#include
#include
void * forbody( int p, void * data ) {
printf( "%d\n", p );
++(*(int *)data);
return data;
}
int isqrt( int n ) {
int x, guess;
if ( n <= 2 ) return 1;
x= n - 1;
do {
guess= x;
x= ( guess + n / guess ) >> 1;
} while ( x < guess );
return x*x < n? x : guess;
}
int prime( int n ) {
int q, sqrtn;
if ( n < 1 )
return 0;
if ( n < 4 )
return n;
else if ( (n % 2) == 0 )
return 2;
sqrtn= isqrt( n );
for ( q= 3; q <= sqrtn; q += 2 )
if ( (n % q) == 0 )
return q;
return n;
}
void primes( int a, int b, void * (*f)( int p, void * ), void * data) {
if ( a < 2 )
a= 2;
if ( a == 2 && a <= b ) {
data= f( 2, data );
++a;
}
else if ( (a % 2) == 0 )
++a;
for ( ; a <= b; a += 2 )
if ( prime( a ) == a )
data= f( a, data );
return;
}
int main( void ) {
int count= 0;
primes( 500, 10000, forbody, (void *) &count );
printf( "count=%d\n", count );
return 0;
}