I recently took a job in which the primary language of the
development
group is C++. This has not been a terribly happy thing for
me because
while I can code and read C++ decently enough, I do not like
the language
very much. C++ has a lot of good ideas underlying it, but
it's just terribly
implemented. The syntax is god-awful, the rules for
inheritance of code and
data members are convoluted as hell, and the compiler does
things behind
your back that can easily cause fits for even an experienced
programmer.
I much prefer C. As someone said in a discussion post on
Kuro5hin said, "If you
must use the
wrong language for the job, I'd rather see you use C than
C++. It's true
that C gives you enough rope to hang yourself. But so does
C++, and it
also comes with a premade gallows and a book on knot tying."
That said,
though, C ain't perfect either...
Another thing that catalyzed my thinking about the faults of
various
programming languages is that I've been reading
Writing
Compilers and Interpreters (second ed): An Applied Approach
using C++. I've been trying to come up with
a simplified C-esque language I could write a compiler
and/or interpreter
for that would attempt to eliminate some of the more glaring
flaws of C.
What are some of those flaws? Well, just off the top of my
head:
- Assignment vs. comparison. Hasn't this
tripped up many
a novice and even occsionally an experienced programmer? We
need to
differentiate between assignment and equality. Using the
same or similiar
symbols for both operations is a just asking for headaches.
- Pointers. Pointers get programmers in a lot
of trouble.
And not just in obvious ways, either. Ever assigned one
struct to another
that had a string pointer inside? How long did it take you
to realize what
was really going on? (C++ has this problem even worse,
thanks to its
amazingly over-wrought object architecture.)
- Memory managementMalloc() and free() cause a
lot of
trouble, even for experienced programmers. C has the honor
of having its
memory allocation scheme so badly designed that a whole
company (Pure Software)
makes a very comfortable living selling a third-party
library (Purify)
to help us track down our memory leaks. This is ridiculous.
- Keystroke Efficiency On a more general note,
I find that
many programming language these days require the use of the
shift key and
special symbols more often that I'd like. My idea of a good
identifier
is one that you don't have to hit the shift key for.
Parenthesis, curly
brackets, asterisks and ampersands should be infrequently
used characters,
not the mainstays of the language syntax.
How do we address these weaknesses? Well, to quote the Perl
programmer's
motto, "There's more than one way to do it." However, here
are some of
my proposed solutions to the items mentioned above: (Please,
pick on
these and tear 'em up! I'm submitting this precisely so
people will tell
me what's wrong with my ideas...)
- Assignment vs. Comparison. Assignment gets a
new
symbol: "<-", as in "A <- B + C". Read as: "A gets B plus
C." Comparison
continues to use "=". In pratice, "<-" is a real pain in the
ass to type.
So either a macro will need to be made or another symbol
will need to
be substituted. Perhaps ":", in the tradition of Pascal.
- Pointers. Most of the problem with pointers
comes from a
pointer not pointing at what it should, either because it
was never pointed
there in the first place, or because it got re-pointed
(perhaps set
to NULL). So I propose that a pointer can only be set once,
and is
immutable once set. This will get rid of a lot of ugly crap,
not the
least of which is the horrible practice of casting between
different
pointer types. Also, before a pointer is set, it is in a
"non-initialized"
state, and dereferencing a non-initialized pointer will be
prohibited.
I believe both these conditions can be enforced at compile
time. Those
conditions said, however, altering the thing pointed to by a
pointer is
still allowed. Without this functionality, there'd be no
point! (If
you'll pardon the pun. ;])
- Memory mamagement This is the 21st century,
folks. We have
gigahertz CPUs and hundreds or thousands of megabytes of
memory. Almost
no task that a modern PC's main CPU undertakes is hard
realtime critical.
(If someone has such a task, I recommend they not use my
little theoretical
language here.) Garbage collection algorithms have come a
long way and
no longer require unbounded time to operate. We've already
tossed the
bad features of pointers out the door, let's continue in the
spirit of
keeping what we like and having the machine deal with the
ugly stuff and
specify that a well-optimized, bounded-run-time garbage
collector be part
of the language.
- Keystroke Efficiency The first obvious one to
me is to substitute
"[" and "]" for "{" and "}". Assuming an otherwise C-like
syntax, this
change should take all of 30 seconds for C programmers to
get used to.
(What we do about arrays, I don't know - maybe my little toy
lanague here
won't have them.) Function calls can have a new syntax,
funcName:arg1,arg2,
etc... This eliminates having to type parenthesis every time
you want to
call a function, a wrist killer if there ever was one.
Strings will get
Pascal-style '' delimiters, 'like so', though the backslash
notation
for escaping characters can stay. We'll keep ; for the end
of a statement
too, that's actually one I like.
Now, a quickie example of the last point...
Original C:
int main(void)
{
printf("Hello, world!");
exit(0);
}
New style whatever it is:
int main.void
[
printf.'Hello, world!';
exit.0;
]
Try typing these two and see which one feels quicker. I
think the
new function syntax is a real win, anyway.
That's all I have at the moment. So... Questions? Comments?
Additions?
Flaming rants about my shoe-size IQ? ;]