Top Mud Sites Forum Return to TopMudSites.com
Go Back   Top Mud Sites Forum > Mud Development and Administration > MUD Coding
Click here to Register


This is a discussion on "Which is preferred?" in the Top Mud Sites MUD Coding forum :

Hey all. I've been interested in teaching myself how to code for awhile now and well, I went and downloaded Cygwin on my comp. I'm also told I need to dl a codebase after that, which will probably be some sort of ROM. Now, my question is this: I want to go out and buy the much-needed coding book. But...what exactly is preferred? C? C+? C++? In terms of wanting to learn to code and possibly write up some snippets for mud's one day, which is suggested?...



You are currently viewing our boards as a guest which gives you limited access to view most discussions and access our other features. By joining our free community you will have access to post topics, communicate privately with other members (PM), respond to polls, upload content and access many other special features. Registration is fast, simple and absolutely free so please, join our MUD community today!

If you have any problems with the registration process or your account login, please contact us.

If you are a registered member of the old TMS forums, please click here
Reply
 
LinkBack Thread Tools
Old 01-24-2003, 01:14 PM   #1
Vesper
Member
 
Vesper's Avatar
 
Join Date: Apr 2002
Posts: 66
Vesper is on a distinguished road
Send a message via AIM to Vesper
Exclamation

Hey all.

I've been interested in teaching myself how to code for awhile now and well, I went and downloaded Cygwin on my comp. I'm also told I need to dl a codebase after that, which will probably be some sort of ROM.

Now, my question is this: I want to go out and buy the much-needed coding book. But...what exactly is preferred?

C? C+? C++? In terms of wanting to learn to code and possibly write up some snippets for mud's one day, which is suggested?
Vesper is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 01-24-2003, 02:04 PM   #2
Yui Unifex
Senior Member
 
Join Date: Apr 2002
Location: Florida
Posts: 323
Yui Unifex is on a distinguished road
Send a message via ICQ to Yui Unifex Send a message via AIM to Yui Unifex
Question

Most existing mud codebases have been created using C. So C++ isn't going to help you much if you want to distribute snippets, because some codebases require conversion to be compiled with a C++ compiler. The newer codebases that I see people working on are almost universally written in C++, Java, or a language with greater abstraction possibilities than C.

If you just wish to modify an existing codebase, for example ROM, a book on C would most likely be your best bet.

btw, "C+" doesn't exist =).
Yui Unifex is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 01-25-2003, 02:49 AM   #3
Vesper
Member
 
Vesper's Avatar
 
Join Date: Apr 2002
Posts: 66
Vesper is on a distinguished road
Send a message via AIM to Vesper
Question

Ahhh...thank you. *grins* And you're right, of course, it doesn't exist, heh...I believe it was "C#" I was trying to think of...

So, that brings up a question of trends: Will the use of "C" eventually fade out...in favor of the newer "C++"...or does the more recent language not really apply to the MUD world?
Vesper is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 01-25-2003, 09:18 AM   #4
Yui Unifex
Senior Member
 
Join Date: Apr 2002
Location: Florida
Posts: 323
Yui Unifex is on a distinguished road
Send a message via ICQ to Yui Unifex Send a message via AIM to Yui Unifex
Question

I can only speculate, but I believe existing codebases are going to continue on with C. Most of the newer codebases that I see in development are done in C++, with some in Java and other languages. So it then becomes a question of whether or not the newer codebases will surpass the older ones, and I lack the clairvoyance to know that =). But C++ codebases will definately become more common I predict.

It is probably a good idea for you to start with C anyway, because C++ is very similar and will even compile most C code. There are also several C codebases to use as a reference point (although you should be careful about learning habits from them, as they are rather poorly designed). C is also much less complex than C++, so there are fewer areas to get confused about when you're starting out.
Yui Unifex is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 01-27-2003, 05:29 AM   #5
Ingham
 
Posts: n/a
C++ is not more complex then C imho. However, because it is an object-orientated programming language, it is definitely allot more abstract and harder to grasp because of it. Still though, if you try the basic of C first, C++ will be a piece of cake because some possibilities in C look quite alike objects in C++ (structs anyone?)

As for which language will fade out, neither of them I believe. C is being used as the standard language for Unix and Unix-like operating systems and C++ is more or less a "standard" language used for various reasons/applications. I don't know about speed differences among C and C++, but both are definitely faster then Java, because Java is basically a souped up scripting language instead of a programming language.

As for compilers, which can be tricky to find, look around on the net for Borland C++ Builder version 3.1. It's good, easy and not all that complicated. DOS based though, so be prepared to work in a 25x40 res with 32 diff colours if you want to use it. It's quite easy to use, does the job, even though it is not so much very legal to find and download.
 
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 01-27-2003, 07:06 AM   #6
KaVir
Legend
 
KaVir's Avatar
 
Join Date: Apr 2002
Name: Richard
Location: München
Home MUD: God Wars II
Posts: 1,782
KaVir will become famous soon enoughKaVir will become famous soon enough
Quote:
Originally Posted by
C++ is not more complex then C imho.
C is a relatively simple language (although it still requires a lot of time and effort to learn to use it effectively), while C++ adds a significant amount of complexity.

Quote:
Originally Posted by
However, because it is an object-orientated programming language,
C++ is not an Object Oriented programming language. It is a multi-paradigm programming language that supports OO, as well as other styles of programming. It requires a lot more effort to write OO software in C.

Quote:
Originally Posted by
Still though, if you try the basic of C first, C++ will be a piece of cake
Not true - I have encountered several people who had only learned C++, and they all did extremely poorly when it came to C interview questions (particularly with things like strings).

Regarding which language to learn: If you're only interested in learning so that you can write mud snippets, then I would agree with Unifex and suggest C. In fact I use several (of my own) C snippets in my own C++ codebase - I just encapsulate them in a namespace - even though they were originally designed to work on muds written in C.
KaVir is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 02-22-2003, 02:23 PM   #7
angelbob
Member
 
Join Date: Feb 2003
Location: Bay Area, CA, USA
Posts: 39
angelbob is on a distinguished road
If you're just learning a first language, C is a much better choice than C++. The poster who said that C++ isn't more complex than C has obviously never had to tackle virtual inheritance, virtual functions with multiple inheritance, problems with dynamic casting and typecasts changing pointer values, operator overloading...

C++ takes C as a starting point and adds a huge amount of new stuff. It's more complex. Seriously. It contains all of C as a (small) subset. How can it *not* be more complex?

You can get away with using fewer of the complicated, nasty C++ features if you only use your own code. But if you ever plan to have another coder on your MUD (you do, right?) you'll have to deal with them. And while everybody seems to agree that C++ is a combination of okay stuff and gross, horrible hacks, nobody seems to agree about which is which. So he'll be using some stuff you consider to be gross, horrible hacks.

I believe that C is the clean part of C++, and almost all of the rest is made of gross, horrible hacks :-)
angelbob is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 03-10-2003, 05:45 PM   #8
Lindahl
New Member
 
Join Date: Feb 2003
Location: California, US
Posts: 5
Lindahl is on a distinguished road
angelbob-

Which would you consider cleaner?
----------------------------------------
class IntObject
{
IntObject &operator +=(int val)
{_val += val; return *this;}

operator int( )
{return _val;}

int _val;
};

IntObject i;
int v = i += 3;
-------------------------------
Or?

struct IntObject
{int _val;};

IntObject *PlusEqual( IntObject *i, int val)
{i->_val += val;}

int Value( IntObject *i)
{return i->_val;}

IntObject i;
int v = Value(PlusEqual(&i, 3));
----------------------------------

To me, the C++ version (first version) is a lot cleaner and more intuitive.

I'd have to say that the design details of a program determine which language produces cleaner code (mainly whether the problem is more naturally described as objects (C++), or proceedures ©).

In the case of a MUD, the design is CLEARLY object-oriented (Server, Connection, Player, Character, Object, Room, Area). Thus, using a language that has object-oriented capabilities would most likely produce the cleanest code.

I'm guessing that you confused the cleanliness of a piece of code with complexity of a language.
Lindahl is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 03-11-2003, 06:31 PM   #9
angelbob
Member
 
Join Date: Feb 2003
Location: Bay Area, CA, USA
Posts: 39
angelbob is on a distinguished road
First, I note that you're using a complex structure where you should be using an int. Passing a pointer to a structure with a single int makes for ugly C, passing a reference to a structure with an int makes for ugly C++, and passing an int around is pretty clean -- and identical in either language. But I'd say both are quite ugly, and both are about equally ugly, but it's very slightly more obvious what the C version is doing.

Second, by talking about how MUDs are an obvious place to use object-oriented programming I'm assuming you're talking about the objects themselves (like, "physical" in-game objects). I'm with the Skotos folks on this -- data inheritance is appropriate, code inheritance not so much so. Code inheritance is the only kind that C++ provides.

Third, if you're talking about inheritance in the "physical" in-game objects, then you're talking about doing it dynamically if you have any OLC facilities. Any modern MUD does. Unless you recompile on the fly (like DGD does -- I'm actually serious, although C++ isn't a good language for this, nor is C), you're going to have to build your own stuff. So you're back to implementing all your own data inheritance.

I agree that there are a couple of specific instances where C++'s version of OO is cleaner than doing the same thing in C. User interface code (windowing and whatnot) is the only place I've seen where it's consistently true. And yet GTK+, the windowing toolkit for GNOME, uses C instead of C++. Why? Because C++ is incompatible between compilers, doesn't link object code between multiple compilers, has the usual fragile base class problems and can't inherit and runtime. The fully inheritance-based solution used by GTK+ is done in C and built out of macros. Unlike the C++ solution, it links to a variety of languages, allows implementation of new widgets in a variety of languages, doesn't require RTTI (which doesn't link between different C++ compilers) and works quite happily if you add new stuff at runtime.

Fourth: your C solution above is attempting to do operator overloading in C. That's its primary problem. You can do what you're doing relatively cleanly in C, but you can't make it look like C++. Why would you want it to look like C++?
angelbob is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 03-11-2003, 06:50 PM   #10
angelbob
Member
 
Join Date: Feb 2003
Location: Bay Area, CA, USA
Posts: 39
angelbob is on a distinguished road
Here, lemme make it clearer what I mean about the "using a complex structure instead of an int" and "make it look like C++" bits.

Your example could be less trivial -- vectors and matrices are the cleanest example I know of in C++, and the best example of why operator overloading might not suck. Every other example that I know of is thoroughly horrible, and I absolutely include "cin" and "cout" in that. I mean, c'mon, they're using bit-shift operators for input and output. How clean and intuitive is *that*?

It's hard in C and ugly in C++ to pass big complex structures around as though they were regular builtin data types. That's pretty much what you're doing above. You can do the same with matrices and define addition, multiplication and (with some stretching) things like inner products, inversion and solving. Of course, nobody but you will ever guess your operators on the first try for anything except addition and multiplication, and they'll need to check your documentation to see if you're doing real matrix multiplication or just going element-by-element.

So instead of something big and nasty and C-like like this:

Matrix *A,*B,*C;

A = MatrixInit(7,7);
MatrixFileLoad(A, "mydatafile.dat");
B = MatrixInit(7,9);
MatrixFileLoad(B,"myotherdata.dat");
C = MatrixInit(7,9);
MatrixMultiply(C, A, B);

You can instead have something smaller and C++-y like this:

Matrix A(7,7), B(7,9);

A.FileLoad("mydatafile.dat");
B.FileLoad("myotherdata.dat");
C = A * B;

Cleaner, smaller, and not much slower if you do it right. The bit of slowness added is because you'll be copying C after that matrix multiply with its copy constructor. You could avoid even that if your compiler is really clever (it's not -- check the code if you use GCC, or the execution time if you use VC++), and the stack space hit doesn't matter in this day and age, at least for MUDs. I used to work for Palm, I notice these things. Anyway.

I'll mention in passing that the library implementing this stuff will be much nastier in C++ than in C. But you could point out that you only write the library once and you write code with it many times. You'd be right. Of course, you maintain the library and deal with bugfixes constantly, and the C++ version does a lot more under the covers. For instance, if you had a bug in the copy constructor or one of the operators in the C++ version (for instance -- does A *= B work? Maybe...) you'll have a much nastier time tracking them down and finding all the functions that are called. I'd say a good debugger would help you, but GDB and VC++ both have serious issues with a lot of very standard C++, let alone godawful things like most proprietary Unix debuggers.

You can say "but I'd write the library right' or "but I'd debug and test it well". You'd probably be right. Good for you. Now, are you the only one working on your project? I've seen a lot of very bad C++ with very hard-to-find bugs. Much more so even than C, especially if I can use a tool like Purify on both.
angelbob is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 03-11-2003, 06:52 PM   #11
enigma@zebedee
Member
 
Join Date: Mar 2003
Posts: 70
enigma@zebedee is on a distinguished road
If planning to code on an LP Mud (or any older mud) then I recommend C as C++ and C# both have significent differences. A lot depends on the mud you want to code on though - I recommend finding and playing the mud before you decide to code for it. Once you know that then the admin there will be able to tell you what language they are using.

Certainly on Zeb we don't let people become coders until they have played the game (the usual rule being at least one character to legend level) and we feel that they are ready for the responsibility.

As a side note C# is basically microsofts bastard cross-breading of C++ and Java. It has some nice features but I don't see it being used much for muds in the immediate future - although I am using it a lot at work.
enigma@zebedee is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 03-12-2003, 10:47 AM   #12
Yui Unifex
Senior Member
 
Join Date: Apr 2002
Location: Florida
Posts: 323
Yui Unifex is on a distinguished road
Send a message via ICQ to Yui Unifex Send a message via AIM to Yui Unifex
Question

Quote:
Originally Posted by (angelbob @ foo)
First, I note that you're using a complex structure where you should be using an int.
I think that much is obvious, but if there were added functionality I'm not so sure that this would be a great idea. If the IntObject were something like CheckedIntObject, which checked assigned values against a valid range and threw an exception when something went out of bounds, it would be a great deal more intuitive and easily extendable with C++ -- after all, it would react exactly like an int, save for the operations one specifies, which makes it easy to typedef and modify if some logic changes.

Quote:
Originally Posted by (angelbob @ bar)
Second, by talking about how MUDs are an obvious place to use object-oriented programming I'm assuming you're talking about the objects themselves (like, "physical" in-game objects). I'm with the Skotos folks on this -- data inheritance is appropriate, code inheritance not so much so. Code inheritance is the only kind that C++ provides.
The objects he mentioned were "Server, Connection, Player, Character, Object, Room, Area". Three of those are not physical objects (Server, Connection, and Player, I think), and depending on the design, physical transformations between the other three may not exist. So data inheritence in that sense is useless because the types do not share data. Since you've stated that you're talking about in-game objects, inheriting data is as easy as writing a copy constructor. I don't think that something so simple needs specific language support. But C will have just as many problems as C++ here -- do you do deep or shallow 'inheritance', and what functions provide it? With C++ you can do deep copying automatically in the copy constructor; this is something that would take one extra step in C, never mind the fact that you'd lose pass-by-value semantics due to the lack of a destructor. IMO, "string" objects are very clearly superior to char * memory pointers because of this.

Quote:
Originally Posted by (angelbob @ baz)
Fourth: your C solution above is attempting to do operator overloading in C. That's its primary problem. You can do what you're doing relatively cleanly in C, but you can't make it look like C++.
Correct -- you would lose functionality because it can't look like C++:
[code] typedef mytype int;
void dosomething (mytype &m) { m = 5; }[/quote]
When that typedef is changed to IntObject (or something more functional, like my above CheckedIntObject), you would have to go back and insert functions to perform all of the assignments.

Quote:
Originally Posted by (angelbob @ foo)
Your example could be less trivial -- vectors and matrices are the cleanest example I know of in C++, and the best example of why operator overloading might not suck.
Not just this, but for templated functions that depend on certain operations working across the board with user-defined as well as built-in types, operator overloading is essential. STL algorithms work on all sorts of types because of this, and it's another thing that C can't achieve.

Quote:
Originally Posted by (angelbob @ bar)
Of course, nobody but you will ever guess your operators on the first try for anything except addition and multiplication, and they'll need to check your documentation to see if you're doing real matrix multiplication or just going element-by-element.
I don't think they'd need to guess -- you would simply overload operator* to handle both matrix and scalar multiplication, so the operations would flow as they do in mathematics; the operations would be type dependant just as they are in the problem domain.
Yui Unifex is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 03-13-2003, 12:43 PM   #13
angelbob
Member
 
Join Date: Feb 2003
Location: Bay Area, CA, USA
Posts: 39
angelbob is on a distinguished road
(Quotes here are from Yui Unifex)

Quote:
Originally Posted by
If the IntObject were something like CheckedIntObject, which checked assigned values against a valid range and threw an exception when something went out of bounds, it would be a great deal more intuitive and easily extendable with C++ -- after all, it would react exactly like an int, save for the operations one specifies, which makes it easy to typedef and modify if some logic changes.
This is true, and I've seen some impressive similar stuff done with using pointers for transparent reference counting. It's pretty nifty as long as no bug ever exists in it (hint -- check every implementation of pointers for refcounting that you use... When reassigning, do they increment the new reference count BEFORE decrementing the old one?).
Of course, if a bug ever happens that doesn't crash your code, you have to debug it. I'm a big fan of knowing when functions are called. C++ experts can generally tell you the order of function calls in, say, this:

C *= myType(9,4,"bob")

It definitely gets hard to follow, though, especially if (in the example above) you haven't defined your own *= operator and C++ has to wing it. It will, in fact, do so, but the choices it makes for this and for typecasting aren't always intuitive, and a lot of stuff (like typecasting) happens silently in conditions that are just weird.

That doesn't address your point, though. Your point is that C++ will fake a builtin data type and make it call arbitrary other functions silently to an extent that C won't.
Yep. You're right. And it's a massive debugging headache that it'll do so.
Perl does this "right", too. Perl is the only language I know with a worse reputation for syntactic and semantic cleanliness than C++. Coincidence?

Quote:
Originally Posted by
The objects he mentioned were "Server, Connection, Player, Character, Object, Room, Area". Three of those are not physical objects
Fair enough. I'd argue that not much inheritance is appropriate for Server, Connection and Player objects -- there usually aren't very many kinds of them. But you're right, they're not physical.

Quote:
Originally Posted by
Since you've stated that you're talking about in-game objects, inheriting data is as easy as writing a copy constructor.
Well, sort of. That doesn't change them if the parent changes, which is my favorite use for data inheritance -- a tree of archetype objects. Skotos' ur-objects are an example of this. Anyway, back to C++.

Quote:
Originally Posted by
But C will have just as many problems as C++ here
Yes. Either one will have to build its own inheritance, effectively. It's just that the C++ people will yell at you for not using the built-in language inheritance and then stonewall when you ask "so what do I do about inheriting at runtime?" :-)

But seriously -- true. I still argue that C++'s extra complexity isn't generally worth the benefit in any environment with more than one coder. When you say that C and C++ break down to the same thing for a given problem, I argue that that supports my argument. They wind up using essentially the same methods to deal with the problem, but C++ has all the extra nastiness you're not using at the moment.

But somebody else on the project may be, and it's allowed to mess you up.

Quote:
Originally Posted by
With C++ you can do deep copying automatically in the copy constructor; this is something that would take one extra step in C, never mind the fact that you'd lose pass-by-value semantics due to the lack of a destructor.
Actually you'd just need an explicit function call rather than implicit one, or a function that copies and passes it back (which is the same thing, basically). But you're right, it wouldn't happen automatically, which can definitely be irritating at times.

Quote:
Originally Posted by
IMO, "string" objects are very clearly superior to char * memory pointers because of this.
I won't argue with you over this one. String should probably have been built into C long ago. Of course, it should also have been built into C++ (or at least the standard library) long ago, and that hasn't happened either.

Quote:
Originally Posted by
Correct -- you would lose functionality because it can't look like C++:
Code Sample
typedef mytype int;
void dosomething (mytype &m) { m = 5; }
Clever. By calling this "lose functionality" you skip over the fact that it's just syntactic sugar. Nonetheless: it's just syntactic sugar. C++ used to be implemented with a preprocessor over C, and you know, it wasn't even a very complicated preprocessor. Big, but not complicated.

Quote:
Originally Posted by
When that typedef is changed to IntObject (or something more functional, like my above CheckedIntObject), you would have to go back and insert functions to perform all of the assignments.
And to get the speed of an unchecked int you'd have to add an extra function call for unchecked assignments and go through the headache of remembering which you're using. Plus, you can detect errors if you get a problem in a function call. How do you detect an error in the middle of "equals"?

Quote:
Originally Posted by
(...I said something about vectors and matrices...)
Not just this, but for templated functions that depend on certain operations working across the board with user-defined as well as built-in types, operator overloading is essential. STL algorithms work on all sorts of types because of this, and it's another thing that C can't achieve.
That's true. That's another thing C can't achieve. Looking at the implementation of templates, I frequently sigh in relief that C can't "achieve" that. While this is probably relatively clean with your "checked int" example (when's the last time you genuinely used one of those, BTW?), I'd argue that it's fundamentally backwards to do the same thing with vectors, matrices, or anything where using "+" or "*" is a stretch for the operator involved. It makes for clever, small code (and massive binary size since you're using templates) but you're fundamentally applying very different concepts to a different set of objects using the same syntax. Urgh.

Quote:
Originally Posted by
I don't think they'd need to guess -- you would simply overload operator* to handle both matrix and scalar multiplication, so the operations would flow as they do in mathematics; the operations would be type dependant just as they are in the problem domain.
That's only true in cases where the problem domain is well-defined and well-documented, and already defines + and * unambiguously. There are two ways to multiply a pair of 4x4 matrices -- only one is written as multiplication by actual mathematicians, though they don't actually bother to put a star. In fact, if they *do* put a star it frequently means they're talking about inner product, which is a very different operation.

But for most things, it's a lot less obvious what + or * represent. Using operator overloading for math is reasonably clean. The vast majority of the time it's not used for math.

For instance, have you noticed that cin and cout use the bit-shift operators? Eeeeeeewwwww! And that's just in the standard library! You could argue that it sorta makes sense ("look, they're little arrows. Kinda. And arrows mean input and output. Kinda. And we didn't allow overriding the actual arrow, plus it doesn't come in reverse flavor."). But if you did, I'd laugh at you.

I've found that's a better example of the way people choose and overload operators in the real world, which is why I don't touch other people's C++ code any more. There's one exception, but Tom's even pickier than I am about this stuff and he rewrites everything three times to get a clean design.
angelbob is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 03-13-2003, 01:40 PM   #14
Yui Unifex
Senior Member
 
Join Date: Apr 2002
Location: Florida
Posts: 323
Yui Unifex is on a distinguished road
Send a message via ICQ to Yui Unifex Send a message via AIM to Yui Unifex
Question

Quote:
Originally Posted by (angelbob @ foo)
That doesn't address your point, though. Your point is that C++ will fake a builtin data type and make it call arbitrary other functions silently to an extent that C won't.
Yep. You're right. And it's a massive debugging headache that it'll do so.
I don't seem to have any troubles with it. gdb treats user-defined operators the same as other functions. (more on this below)

Quote:
Originally Posted by (angelbob @ bar)
Well, sort of. That doesn't change them if the parent changes, which is my favorite use for data inheritance -- a tree of archetype objects. Skotos' ur-objects are an example of this.
Not sure what you mean here. In code, copy constructors cascade parent copy constructors down the line. If it's in-game data that's dealt with via an encapsulated datatype, the copy constructor should handle copying it.

Quote:
Originally Posted by (angelbob @ baz)
Actually you'd just need an explicit function call rather than implicit one, or a function that copies and passes it back (which is the same thing, basically).
Right -- it's an extra step in userspace.

Quote:
Originally Posted by (Yui Unifex @ foo)
Correct -- you would lose functionality because it can't look like C++:
Code Sample
typedef mytype int;
void dosomething (mytype &m) { m = 5; }
Quote:
Originally Posted by (angelbob @ foo)
Clever. By calling this "lose functionality" you skip over the fact that it's just syntactic sugar. Nonetheless: it's just syntactic sugar.
No, it's a legitimate concern. I can write a library of code using these templates (supposing for the moment that C had templates) and never have to worry about the user being able use it with built-in types as well as user-define types. This bit of "syntactic sugar" is very important in reducing the amount of duplicated code and thus errors.

Quote:
Originally Posted by (Yui Unifex @ bar)
When that typedef is changed to IntObject (or something more functional, like my above CheckedIntObject), you would have to go back and insert functions to perform all of the assignments.
Quote:
Originally Posted by (angelbob @ bar)
And to get the speed of an unchecked int you'd have to add an extra function call for unchecked assignments and go through the headache of remembering which you're using.
I'm sorry? To get the speed of an unchecked int you would use an unchecked int as the template argument. The "headache of remembering what you're using" can be easily alleviated by a quick dosage of glancing up at your variable declarations =).

Quote:
Originally Posted by (angelbob @ baz)
How do you detect an error in the middle of "equals"?
Use a debugger =). (From above) gdb allows debugging of operator=() just as it does an equals() function. So long as one remembers that operators can be overloaded and assert their assumptions, everything should be fine.

Quote:
Originally Posted by (angelbob @ foo)
I'd argue that it's fundamentally backwards to do the same thing with vectors, matrices, or anything where using "+" or "*" is a stretch for the operator involved.
Oh indeed -- if the operation is not clear then they should be renamed to alleviate this problem. This applies to both overloaded operators and function names, of course =).

Quote:
Originally Posted by (angelbob @ bar)
While this is probably relatively clean with your "checked int" example (when's the last time you genuinely used one of those, BTW?)
Just recently, that's why it popped in my mind =). I was just writing a spacial system module where my coordinate-types are templated. However I was having a problem with my movement setting my coordinates out of the bounds of the node in which I was currently located. A quick CheckedFloat object thrown into the template for my coord (which normally uses regular floats) and I was able to find the problem in a few minutes.

Quote:
Originally Posted by (angelbob @ baz)
There are two ways to multiply a pair of 4x4 matrices -- only one is written as multiplication by actual mathematicians, though they don't actually bother to put a star. In fact, if they *do* put a star it frequently means they're talking about inner product, which is a very different operation.
IMO, it should match the way the problem domain works as closely as possible. If it's not possible to match the problem domain, then making up an operator is as you say, likely to cause pain. But this isn't a problem with operator overloading, this is a problem of the discipline of the coder. To argue that C++ or even Perl facilitates undisciplined coding is disingenious because one could easily apply those arguments as reasoning for why everybody should use VB.

Quote:
Originally Posted by (angelbob @ foo)
But for most things, it's a lot less obvious what + or * represent. Using operator overloading for math is reasonably clean. The vast majority of the time it's not used for math.
You don't have to use it for operations you don't embrace =). If someone on your project uses it against your will then that's an issue that you two need to handle, not a programming language designer. A document on coding standards is important for large projects, and if it's a point of ire for developers then things should be clarified in this document, rather than spoiling the broth by restricting the entire language. This is a big complaint I have about Java.

Quote:
Originally Posted by (angelbob @ bar)
For instance, have you noticed that cin and cout use the bit-shift operators? Eeeeeeewwwww!
<grins> The methods I've seen for doing that kind of output have been:
+ operator (Supported by C++)
& operator (VB)
. operator (PHP)
<< operator (C++)

What operator or method (if it's not using operators) would you suggest be used for stream input?
Yui Unifex is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 03-13-2003, 05:18 PM   #15
angelbob
Member
 
Join Date: Feb 2003
Location: Bay Area, CA, USA
Posts: 39
angelbob is on a distinguished road
angelbob:
Quote:
Originally Posted by
Your point is that C++ will fake a builtin data type and make it call arbitrary other functions silently to an extent that C won't. Yep. You're right. And it's a massive debugging headache that it'll do so.
Yui:
Quote:
Originally Posted by
I don't seem to have any troubles with it. gdb treats user-defined operators the same as other functions. (more on this below)
How often do you debug other people's code?

angelbob:
Quote:
Originally Posted by
Well, sort of. That doesn't change them if the parent changes, which is my favorite use for data inheritance -- a tree of archetype objects. Skotos' ur-objects are an example of this.
Yui:
Quote:
Originally Posted by
Not sure what you mean here.
Knock yourself out:
http://www.skotos.net/articles/TTnT_60.shtml

angelbob:
Quote:
Originally Posted by
Actually you'd just need an explicit function call rather than implicit one, or a function that copies and passes it back (which is the same thing, basically).
Yui:
Quote:
Originally Posted by
Right -- it's an extra step in userspace.
Yup. And yours is still an extra step, just invisible at the language level. I tend not to call that "user space" because I'm used to "user space" meaning "not kernel space".

Yui:
Quote:
Originally Posted by
Correct -- you would lose functionality because it can't look like C++:
Code Sample
typedef mytype int;
void dosomething (mytype &m) { m = 5; }
angelbob:
Quote:
Originally Posted by
Clever. By calling this "lose functionality" you skip over the fact that it's just syntactic sugar. Nonetheless: it's just syntactic sugar.
Yui:
Quote:
Originally Posted by
No, it's a legitimate concern. I can write a library of code using these templates (supposing for the moment that C had templates) and never have to worry about the user being able use it with built-in types as well as user-define types. This bit of "syntactic sugar" is very important in reducing the amount of duplicated code and thus errors.
In general I semi-agree with you. You can do this with void pointers but it's ugly. It works, but it's ugly. It's also far smaller (in the final binary size) since it doesn't duplicate all the code. It's also more portable since you don't have to worry about template instantiation concerns. And it tends to run faster since you have a smaller amount of code in cache. Plus it doesn't require the extra symbol space that templates do -- you'll note that VC++ generates constant extra errors in STL because the symbols are too long. But you're right, it's uglier, especially if you like angle-brackets.
Templates, though, are a syntactic answer to a semantic problem. Plus they have all the problems I mention in the previous paragraph. And I don't particularly like angle brackets more than stars, just personally :-)

angelbob:
Quote:
Originally Posted by
How do you detect an error in the middle of "equals"?
Yui:
Quote:
Originally Posted by
Use a debugger =).
So you're not in favor of detecting errors at runtime, then? Operator overloading precludes handling an error if it's returned (because it can't be returned). If your function ever needs to return an error (*cough* stream output *cough*) then there's no good way to deal with this.

There are exceptions, but the way C++ handles those is just *evil*. I'm not saying they can't be done right, but C++ certainly doesn't. They're hard to bolt onto a language after the fact, and C++ barely even tries.

angelbob:
Quote:
Originally Posted by
I'd argue that it's fundamentally backwards to do the same thing with vectors, matrices, or anything where using "+" or "*" is a stretch for the operator involved.
Yui:
Quote:
Originally Posted by
Oh indeed -- if the operation is not clear then they should be renamed to alleviate this problem. This applies to both overloaded operators and function names, of course =).
Any operator which you can't do in C to a builtin data type has no clear operator name. So operator overloading, which only allows you to use the builtin operator names, has no clear way to name it. What's the correct operator to mean "inner product" for a matrix? How about "outer product"? For a vector, how about "cross product"? I've seen all of these as "*", incidentally. It's probably the best match for all of them. See why I don't trust "*" to be one specific thing?

Yui:
Quote:
Originally Posted by
IMO, it should match the way the problem domain works as closely as possible. If it's not possible to match the problem domain, then making up an operator is as you say, likely to cause pain. But this isn't a problem with operator overloading, this is a problem of the discipline of the coder.
So you're saying that using operator overloading for any problem domain that the operator doesn't perfectly match is a lack of coder discipline? But we'll get back to cin and cout in a minute.

Yui:
Quote:
Originally Posted by
You don't have to use it for operations you don't embrace =). If someone on your project uses it against your will then that's an issue that you two need to handle, not a programming language designer.
The fact that it's possible to affect these things in ways that are invisible means that I have to look through all new submitted code before I can trust using it -- it's not obvious, looking at a declaration, what code is being called. It's not enough for me to set guidelines, there has to be a way to check it. One way to check it is for a function call to be syntactically obvious, so I can say "oh! a function is being called here."

Quote:
Originally Posted by
if it's a point of ire for developers then things should be clarified in this document, rather than spoiling the broth by restricting the entire language. This is a big complaint I have about Java.
No two developers agree what parts of C++ are an abomination. You use operator overloading and templates, two of my favorite whipping boys. Incidentally, if I were to restrict the use of templates in one of my C++ projects (I don't have any in C++, but let's pretend) then there would be folks like you complaining about that since I'd be "spoiling the broth" on that as well. Where do you draw the line?

I draw the line by saying "no C++". That means I never have to deal with a developer saying "yeah, you have to use templates and overloaded operators, but only on the stuff in my module."

angelbob:
Quote:
Originally Posted by
For instance, have you noticed that cin and cout use the bit-shift operators? Eeeeeeewwwww!
Yui:
Quote:
Originally Posted by
<grins> The methods I've seen for doing that kind of output have been:
+ operator (Supported by C++)
& operator (VB)
. operator (PHP)
<< operator (C++)

What operator or method (if it's not using operators) would you suggest be used for stream input?
None. There is no operator that matches the problem domain so there should be no operator overloading for it. Remember when you said that an operator that doesn't match the problem domain should be renamed?
angelbob is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 03-13-2003, 08:31 PM   #16
Yui Unifex
Senior Member
 
Join Date: Apr 2002
Location: Florida
Posts: 323
Yui Unifex is on a distinguished road
Send a message via ICQ to Yui Unifex Send a message via AIM to Yui Unifex
Question

Quote:
Originally Posted by (angelbob @ foo)
How often do you debug other people's code?
Quite often. Now what does that have to do with anything? Or are you telling me that since other people do bad things, we should automatically take away all things that have the possibility of being bad?

Quote:
Originally Posted by (angelbob @ bar)
[on data inheritence]
Quote:
Originally Posted by (Shannon Appelcline @ bar)
Data Inheritance n.
1. Object Oriented Programming. A function that bases the data of a child object upon one or more parent objects. 2. Online Gaming. The technique of building specific objects, such as daggers, that include the characteristics of more general objects, such as bladed weapons.
How could a language possibly add support for ths? This is basically constructing a type from the data of its parent types. But for a language to add support for this, they would have to know how this construction is handled! I think the existing functionality is more than adequate to handle something so simple.

Quote:
Originally Posted by (angelbob @ baz)
Yup. And yours is still an extra step, just invisible at the language level.
It's quite visible at the language level. But not the user of that library's level. I'm not sure about you, but I use the objects in libraries far more often than I write them, so the 'extra' step ends up paying for itself the moment I use it more than once.

Quote:
Originally Posted by (angelbob @ foo)
In general I semi-agree with you. You can do this with void pointers but it's ugly.
Nope, you can't even do this with void pointers. You would still have to overload an operator. And how would the function know which type to cast as to perform the operation?

Quote:
Originally Posted by (angelbob @ bar)
It's also far smaller (in the final binary size) since it doesn't duplicate all the code. [snip point addressed below] And it tends to run faster since you have a smaller amount of code in cache. Plus it doesn't require the extra symbol space that templates do -- you'll note that VC++ generates constant extra errors in STL because the symbols are too long.
If I have a performance problem, I'll profile. Debugging symbols add far more to my binary size than templates do, and I usually keep those in for safe measure. Maybe when we're talking about performance problems will these points be valid.

Quote:
Originally Posted by (angelbob @ baz)
It's also more portable since you don't have to worry about template instantiation concerns.
So when I use a compiler that doesn't support the standard formalized *5 years ago* I'll worry about this ;). Until then, unless I'm writing code for ancient SCO machines, I'll continue to use the feature that's been in every compiler I've ever used across dozens of platforms.

Quote:
Originally Posted by (angelbob @ foo)
So you're not in favor of detecting errors at runtime, then? Operator overloading precludes handling an error if it's returned (because it can't be returned). If your function ever needs to return an error (*cough* stream output *cough*) then there's no good way to deal with this.
Coupling the error system to the *return type* of the function is stupid. What do you do if you have a legitimate return type but an error condition may also be raised? Exceptions are the answer. And even if you don't like C++'s implementation of them, they work very well for the vast majority of people that don't bother with what is almost always an insignificant performance issue.

Quote:
Originally Posted by (angelbob @ bar)
Any operator which you can't do in C to a builtin data type has no clear operator name.
No, you even gave an example of a user-defined data type that had a clear operator name in that of operator* for multiply. Your later attempting to show how people overload this for inner and outer product only shows that these people wrote bad code, not that overloading operator* is bad in all cases. Of course you don't trust operator* to be one specific thing, but I've seen factorial() functions that compute the sum rather than the factorial. Therefore using your logic, we should all never use functions, or any abstraction at all. See where the argument falls apart? Overloading operators are no different than any other kind of abstraction, excepting the bizarre stigma you've attached to them.

Quote:
Originally Posted by (Yui Unifex @ baz)
IMO, it should match the way the problem domain works as closely as possible. If it's not possible to match the problem domain, then making up an operator is as you say, likely to cause pain. But this isn't a problem with operator overloading, this is a problem of the discipline of the coder.
Quote:
Originally Posted by (angelbob @ baz)
So you're saying that using operator overloading for any problem domain that the operator doesn't perfectly match is a lack of coder discipline? But we'll get back to cin and cout in a minute.
Yes. But you don't seem to understand that cin/cout, and even plain function calls don't match the problem domain for input/output streaming. It has no defined domain like mathematics does. Therefore they're fully justified in coming up with operators to make it more conveniant to use. Just like the mathematicians of old came up with special characters -- operators shall we say -- to represent certain operations. Going against the problem domain is a lack of coder discipline; tackling an undefined domain and making it more managable is a sign of the opposite.

Quote:
Originally Posted by (angelbob @ foo)
...it's not obvious, looking at a declaration, what code is being called
This is what 'abstraction' is all about! It's not obvious, looking at a function declaration, what code is being called. But any programmer knows that he needs to make an assumption that the name of the function conveys this necessary information. Likewise, when a programmer is working with a class he needs to make an assumption that the type of class *and* the operator being used conveys this necessary information. If it does not, then the operation or the class needs to be renamed. This is a very simple concept.

Quote:
Originally Posted by (angelbob @ bar)
No two developers agree what parts of C++ are an abomination.
No two developers agree on how many spaces to indent -- or even if spaces should be used at all in place of tabs -- but that's no excuse for avoiding coming up with coding standards for it on a large project.

Quote:
Originally Posted by (angelbob @ baz)
Incidentally, if I were to restrict the use of templates in one of my C++ projects (I don't have any in C++, but let's pretend) then there would be folks like you complaining about that since I'd be "spoiling the broth" on that as well. Where do you draw the line?
Umm. Let's see here:
1) I say that restricting a feature from an entire language because some can do wrong with it is "spoiling the broth".
2) You say that restricting a feature from your own project because some can do wrong with it would have people like me claiming that it is "spoiling the broth".

Do you see the fallacy now? There's a staggering difference in scale between a *language design* and your own project's guidelines. You are free to do whatever you'd like in your own project. But the moment that you step out of your bounds and claim that since you have never seen a great use of something, then mandate that it is useless for everybody else is the moment that I cry foul.

Quote:
Originally Posted by (Yui Unifex @ bar)
What operator or method (if it's not using operators) would you suggest be used for stream input?
Quote:
Originally Posted by (angelbob @ bar)
None. There is no operator that matches the problem domain so there should be no operator overloading for it.
reply.output(poster.name());
reply.output(", you're saying we should not use operator overloading for output streaming?\n");
reply.output("Well, ");
reply.output(poster.name());
reply.output(", I guess we disagree.\n");
Yui Unifex is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 03-17-2003, 06:04 PM   #17
angelbob
Member
 
Join Date: Feb 2003
Location: Bay Area, CA, USA
Posts: 39
angelbob is on a distinguished road
angelbob:
Quote:
Originally Posted by
How often do you debug other people's code?
Yui:
Quote:
Originally Posted by
Quite often. Now what does that have to do with anything? Or are you telling me that since other people do bad things, we should automatically take away all things that have the possibility of being bad?
Roughly, yes. For instance: I believe that goto's existence in C is an artifact of when the language was designed, and that we'd all be happier without it. Do you believe that goto-less languages should all add it since somebody might use it well at some point?

Yui:
Quote:
Originally Posted by
(...Data Inheritance...)How could a language possibly add support for ths? This is basically constructing a type from the data of its parent types. But for a language to add support for this, they would have to know how this construction is handled! I think the existing functionality is more than adequate to handle something so simple.
I wasn't suggesting that C++ should do it, just that MUD inheritance in "physical" MUD objects is almost always data inheritance, and only more rarely code inheritance. Thus, I was suggesting that C++'s language support for code inheritance wasn't any great shakes for the MUD environment specifically. There was a point much earlier that a previous poster made claiming that inheritance was very well suited to the MUD environment.

So I'm saying: here's what the MUD environment seems to particularly call for. I don't feel it's a good match for C++'s inheritance. I feel that C++'s inheritance is not a good match for this specific problem.

Clear?

And incidentally, yes, you *can* add language support for it, but the only languages where that would be appropriate are languages for pretty specific applications. MUD scripting languages, for instance.

angelbob:
Quote:
Originally Posted by
In general I semi-agree with you. You can do this with void pointers but it's ugly.
Yui:
Quote:
Originally Posted by
Nope, you can't even do this with void pointers. You would still have to overload an operator. And how would the function know which type to cast as to perform the operation?
You can't overload the operator in C, no. We still disagree about whether operator overloading is a good thing (surprise, surprise). You can call a function to get the same result, though.

Yui:
Quote:
Originally Posted by
If I have a performance problem, I'll profile.
True. Most of the performance points I brought up are minor details.

Quote:
Originally Posted by
So when I use a compiler that doesn't support the standard formalized *5 years ago* I'll worry about this . Until then, unless I'm writing code for ancient SCO machines, I'll continue to use the feature that's been in every compiler I've ever used across dozens of platforms.
Compilers I've used that don't support "standard" template instantiation: g++ on Linux, SGI's C++ compiler on SGIs, HP's C++ compiler on HP/UX, Sun's C++ compiler on SunOS4 and Solaris. Time during which they haven't supported this: each within the last 5 years. Perhaps they've all been fully fixed since then to fully support it. Would you put money on that? I wouldn't, especially since template specs are actually a *lot* older than 5 years.

Compilers I've used that support namespaces, also a long-standing standard, fully and completely: Um... VC++, maybe? I know there are bugs, but mostly, I think. That haven't: Metrowerks (didn't test templates so I didn't list it above), G++ (fixed now?), SGI C++ compiler, HP C++ compiler, SunOS4 C++ compiler. Didn't test Solaris.

Do you know how long it took them to come up with a "standard" Ada compiler after the language was spec'd? Green Hills makes about the only one in existence, and they certainly aren't the only people who've tried, or the only people that want the Department of Defense contracts involved. Standardizing doesn't make it so.

Yui:
Quote:
Originally Posted by
Coupling the error system to the *return type* of the function is stupid. What do you do if you have a legitimate return type but an error condition may also be raised? Exceptions are the answer. And even if you don't like C++'s implementation of them, they work very well for the vast majority of people that don't bother with what is almost always an insignificant performance issue.
Actually, I don't much care about the performance issue, though it certainly looks significant compared to normal function call overhead. I care about the questionable semantics C++ has for most of this stuff, and the fact that it was bolted on poorly as an afterthought.

I'm aware that they're slow to use, but mainly I'm bothered by the fact that they're *hard* to use, at least correctly and without ugly corner cases.

Yui:
Quote:
Originally Posted by
(...) you even gave an example of a user-defined data type that had a clear operator name in that of operator* for multiply. Your later attempting to show how people overload this for inner and outer product only shows that these people wrote bad code, not that overloading operator* is bad in all cases. Of course you don't trust operator* to be one specific thing, but I've seen factorial() functions that compute the sum rather than the factorial. Therefore using your logic, we should all never use functions, or any abstraction at all.
The difference is that there are operations which are named incorrectly, and there are operations that are impossible to name correctly. Multiplication can be named incorrectly -- you can name something you need to do with a name that means something else -- by calling inner produce "*" for instance. But then, if you need to do inner product and you don't call it "*", what do you call it? There IS NO correct operator name.

You could make it a function call instead. But then what happened to all your arguments that operator overloading is better than function calls for that kind of thing?

Yui:
Quote:
Originally Posted by
But you don't seem to understand that cin/cout, and even plain function calls don't match the problem domain for input/output streaming. It has no defined domain like mathematics does. Therefore they're fully justified in coming up with operators to make it more conveniant to use. Just like the mathematicians of old came up with special characters -- operators shall we say -- to represent certain operations. Going against the problem domain is a lack of coder discipline; tackling an undefined domain and making it more managable is a sign of the opposite.
But unfortunately, the symbols you have to work with all have defined meanings in other domains, and in *common* other domains. Function names are usually chosen to avoid other common meanings, and because text is very expressive it's reasonable to avoid most other common meanings. If you choose function names arbitrarily ("I call this operation frobzorgle") then it's not very helpful. But if you call it something misleading ("I choose to call my inner product function 'addition'") it's even worse. Like your factorial example above.

If you overload an operator like bit-shift that has a defined meaning in a related domain, you're being worse than arbitrary. You're being specifically misleading.

Or to put it another way:

cout << "Half the sum is " << sum << 2 << " or at least I hope so.\n";

Can you fix this with parens? Sure. But you're being confusing. The operator is bit-shift and text output in the same expression regardless of how many parentheses you add to it. It's the same problem as using + for string concatenation -- it's inherently confusing when stuck next to + for integer arithmetic. So choosing one of a number of existing symbols with existing meanings (like operators) rather than a richer vocabulary (like words, used for function names) is guaranteeing that you have a lot of unrelated baggage attached to any name you give an operation unless that operation already matches the symbol you're using. As you point out, there is no symbol that matches cin/cout -- they could have used xor (^) or function call with dereference (->) or any of many other operators -- and those would have been confusing, too.

angelbob:
Quote:
Originally Posted by
...it's not obvious, looking at a declaration, what code is being called
Yui:
Quote:
Originally Posted by
This is what 'abstraction' is all about! It's not obvious, looking at a function declaration, what code is being called. (...) Likewise, when a programmer is working with a class he needs to make an assumption that the type of class *and* the operator being used conveys this necessary information. If it does not, then the operation or the class needs to be renamed. This is a very simple concept.
One with a very "interesting" execution, but yes. As I argue above, I believe that operator overloading gives a misleading name to almost every operation. If the only available function names were "add", "subtract", "list_reverse" and "dereference" I'd make the same argument about them. I'd argue that if you wanted to sort a linked list and call it "list_reverse" that it would be misleading, even though I don't think "subtract" or "dereference" is a better match for that concept.

So you're saying "but what better matches are there?" and I'm saying "choosing a small fixed number of names with existing different meanings is foolish."

If I were going to write a list reversal function I probably *would* call it list_reverse. I'd still say that a language feature that made you choose from those possible names, even if it were very convenient, would be basically misguided. And that's basically what operator overloading makes you do.

angelbob:
Quote:
Originally Posted by
No two developers agree what parts of C++ are an abomination.
Yui:
Quote:
Originally Posted by
No two developers agree on how many spaces to indent -- or even if spaces should be used at all in place of tabs -- but that's no excuse for avoiding coming up with coding standards for it on a large project.
No two developers agree on how to make Perl work cleanly -- and as a result, they never use it on big multiperson projects, or they do it so that it exists only in little chunks that can't touch each other, or anything else. There are exceptions, and they tend to be ugly. (Incidentally -- I *like* perl, don't get me wrong, and I use it frequently, but I still wouldn't build a MUD in it).

So when the original poster (remember when we had a topic?) asked "C, or C++?" I said "C". You're right, having a standard will help to prevent whatever subset of C++ you don't like from getting into the project. In practice it rarely works that way since you wind up having to rewrite submissions from people that didn't read the standards, but we'll pretend it always works. Fine.

Still, I believe that operator overloading is essentially wrongheaded, and that it should be avoided. I believe that a fine way to avoid it is to use a language that doesn't support it. If there was a variant dialect of C++ that added only features that you hated, would you declare that your project didn't use them, or would you just use the compiler that enforced the set of features you used?

Would you police your project standard by using a tool that did so for you, or would you say "well, I shouldn't discriminate against the language" and use the compiler that didn't?

I have a guess which one you'd do. And I *know* which one I do.

Yui:
Quote:
Originally Posted by
Umm. Let's see here:
1) I say that restricting a feature from an entire language because some can do wrong with it is "spoiling the broth".
2) You say that restricting a feature from your own project because some can do wrong with it would have people like me claiming that it is "spoiling the broth".

Do you see the fallacy now? There's a staggering difference in scale between a *language design* and your own project's guidelines. You are free to do whatever you'd like in your own project. But the moment that you step out of your bounds and claim that since you have never seen a great use of something, then mandate that it is useless for everybody else is the moment that I cry foul.
The question in the original post was "C or C++". I chose C. You're welcome to say I'm being pigheaded and unreasonable by doing my MUD projects in C (old ones -- my new one is in LPC, which also doesn't have operator overloading).

So when I say "you should use C on your project. I do. Here are the features you avoid other people using, and some reasons I dislike them", you say I'm spoiling the broth. Of course, you also claim I'm altering the design of C++ by using C, but I'll ignore that for the moment, shall I?

Quote:
Originally Posted by
reply.output(poster.name());
reply.output(", you're saying we should not use operator overloading for output streaming?\n");
reply.output("Well, ");
reply.output(poster.name());
reply.output(", I guess we disagree.\n");
cout << poster.name() << ", I am indeed.\n";
cout << "While I agree that your way works better for "
<< output_code.bold() << output_code.color("green")
<< "some" << output_code.unbold()
<< output_code.color("white");
cout << " things, I think there are others that help to";
cout << " counterbalance them.\n";

printf("Right-side formatting, for instance. And tables.\n");
printf("So, %s, I do say that. And yes, %s, we DO "
"disagree.", poster_name(), poster_name());
angelbob is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 03-17-2003, 08:27 PM   #18
Yui Unifex
Senior Member
 
Join Date: Apr 2002
Location: Florida
Posts: 323
Yui Unifex is on a distinguished road
Send a message via ICQ to Yui Unifex Send a message via AIM to Yui Unifex
Question

Quote:
Originally Posted by (angelbob @ foo)
For instance: I believe that goto's existence in C is an artifact of when the language was designed, and that we'd all be happier without it. Do you believe that goto-less languages should all add it since somebody might use it well at some point?
Actually, I was going to bring up this point myself =). I do think that goto-less languages should put it on their todo list. Despite Djikstra's warnings on the harmfulness of goto, Knuth has shown that it can be used to create elegant algorithms. Steve McConnell, author of Code Complete, has an excerpt from his book on the subject here that goes much further in-depth than I could.

Quote:
Originally Posted by (Yui Unifex @ bar)
Nope, you can't even do this with void pointers. You would still have to overload an operator. And how would the function know which type to cast as to perform the operation?
Quote:
Originally Posted by (angelbob @ bar)
...You can call a function to get the same result, though.
But my point was that with this code:
[code] typedef mytype int;
void dosomething (mytype &m) { m = 5; }[/quote]
You would have to go back and insert function calls if you later decided to use a user-defined type. This drastically reduces the genericity of the code. Even though the result may be the same, you have to jump through a lot more hoops to bring it about.

Quote:
Originally Posted by (angelbob @ baz)
Compilers I've used that don't support "standard" template instantiation: g++ on Linux, SGI's C++ compiler on SGIs, HP's C++ compiler on HP/UX, Sun's C++ compiler on SunOS4 and Solaris.
I don't know about all of those compilers, but for a few (like g++ and VC++), the only unsupported important operation is 'export', which would require a restructuring of both C and C++ compilation methods. But you were concerned about 'template instantiation concerns', which is portable across all systems I've come across. If that weren't portable, those systems wouldn't be able to support the STL, a great deal of the C++ Standard Library, which would cause even more problems. The lack of export, while unfortunate, does not mean that most valid C++ template code is unportable, however.

Yes, g++ 3.x supports namespaces. Can't say for the other compilers, as I haven't used them recently.

Quote:
Originally Posted by (angelbob @ foo)
So you're not in favor of detecting errors at runtime, then? Operator overloading precludes handling an error if it's returned (because it can't be returned). If your function ever needs to return an error (*cough* stream output *cough*) then there's no good way to deal with this.
Quote:
Originally Posted by (Yui Unifex @ foo)
Coupling the error system to the *return type* of the function is stupid. What do you do if you have a legitimate return type but an error condition may also be raised? Exceptions are the answer. And even if you don't like C++'s implementation of them, they work very well for the vast majority of people that don't bother with what is almost always an insignificant performance issue.
Quote:
Originally Posted by (angelbob @ foo)
[on exceptions]Actually, I don't much care about the performance issue, though it certainly looks significant compared to normal function call overhead. I care about the questionable semantics C++ has for most of this stuff, and the fact that it was bolted on poorly as an afterthought.
Wait, I thought operator overloading precluded handling an error was what concerned you? Regardless of how you think C++ exceptions are implemented, that statement is false.

Quote:
Originally Posted by (angelbob @ bar)
The difference is that there are operations which are named incorrectly, and there are operations that are impossible to name correctly. Multiplication can be named incorrectly -- you can name something you need to do with a name that means something else -- by calling inner produce "*" for instance. But then, if you need to do inner product and you don't call it "*", what do you call it? There IS NO correct operator name.
I agree, if there is not a valid operator for the operation, one should not overload an operator for it. Exceptions to this statement are when there are no valid functions either, as in input/output streaming, and when the operator is similar to what one has come to expect, as in overloading operator[] with a char * for an array index.

Quote:
Originally Posted by (angelbob @ baz)
You could make it a function call instead. But then what happened to all your arguments that operator overloading is better than function calls for that kind of thing?
No, I never said that operator overloading was better than making function calls in all cases. I said that it is better when it meets a certain criteria, defined above. I do agree that inner product should be implemented as a function call. But I also think that multiplication (scalar and matrix) should be implemented as overloaded operators because it is far more intuitive and easy to genericize than the alternative.

Quote:
Originally Posted by (angelbob @ foo)
If you overload an operator like bit-shift that has a defined meaning in a related domain, you're being worse than arbitrary. You're being specifically misleading.
I agree. But I don't think that the domain of bit-shifting is at all related to that of input and output. Or rather, it is at least as related as the original bit-shift operator and the relational > and <. Because of the finite amount of symbols in the western alphabet, nearly every operator has different meanings in different contexts. Is that # for number or # for sharp? ^ for XOR or ^ for raising to the power of or ^ to denote superscript? As you can see, just because it's possible to use the same operator on another object doesn't mean overloading that operator for a different object is necessarily bad. Especially when it has such advantages over the alternatives [more below].

Quote:
Originally Posted by (angelbob @ foo)
printf("Right-side formatting, for instance. And tables.\n");
printf("So, %s, I do say that. And yes, %s, we DO disagree.", poster_name(), poster_name());
Ah, but you've stumbled upon one of the major shortcomings of format strings. Namely, they cannot handle user-defined types. If poster_name() returns a 'string' object or something else, you would have to go back and insert convertors into every one of your output methods to convert it to the right type. Whereas with the cin/cout method, I simply change the return-type of my operation, and I'm done.

There are several libraries that solve the attribute problem by overloading operator<< so that one may use format-strings just as you do for printf(). These are immune to the problems I mentioned, though, because one should not insert the actual data using these formatters.

Quote:
Originally Posted by (angelbob @ bar)
If I were going to write a list reversal function I probably *would* call it list_reverse. I'd still say that a language feature that made you choose from those possible names, even if it were very convenient, would be basically misguided. And that's basically what operator overloading makes you do.
No, operator overloading does not "make you" choose an operator when a function name would be more appropriate. All it does is add more choice so that you can pick the best option available. Positing that an optional feature restricts choice more than languages that don't have such a thing is ridiculous.

Quote:
Originally Posted by (angelbob @ baz)
If there was a variant dialect of C++ that added only features that you hated, would you declare that your project didn't use them, or would you just use the compiler that enforced the set of features you used?
I would be hard-pressed to say that I hated a particular feature, granted that it was really a feature (case insensitivity comes to mind). Anything that adds to my programmer's toolbox and increases the expressiveness of my code can only bring good, IMO. I think it's incredibly difficult to assert that a feature is always bad. Even case insensitivity has its uses =).

Quote:
Originally Posted by (angelbob @ foo)
So when I say "you should use C on your project. I do. Here are the features you avoid other people using, and some reasons I dislike them", you say I'm spoiling the broth.
No, not at all. I said that if one were to assert that operator overloading was always bad (You said that they, along with templates, were an abomination: "No two developers agree what parts of C++ are an abomination. You use operator overloading and templates, two of my favorite whipping boys". But you also said that it was clean for math operations: "Using operator overloading for math is reasonably clean"), that it would ruin it for those of us that find the feature useful. I think it's perfectly alright, encouraged even, to actively advocate why one likes / dislike certain things, so long as one realizes that there may be untold uses for certain things.

Quote:
Originally Posted by (angelbob @ bar)
Of course, you also claim I'm altering the design of C++ by using C...
No. Where did I claim this? I said that a language designer need not be concerned if there are potential abuses for otherwise useful features (that is, they should not be too concerned -- they should of course try to minimize the chances and impact of abuse).
Yui Unifex is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 03-18-2003, 02:43 PM   #19
shadowfyr
Senior Member
 
Join Date: Oct 2002
Posts: 291
shadowfyr will become famous soon enough
Quote:
Originally Posted by
Roughly, yes. For instance: I believe that goto's existence in C is an artifact of when the language was designed, and that we'd all be happier without it. Do you believe that goto-less languages should all add it since somebody might use it well at some point?
How about a case like this (sorry, but I am better at VB than the rest):

sub Dostuff(MyArray)
...
Some code
...
for a = 1 to 10
for b = 1 to 10
if MyArray[a,b] = -1 then
exit ? Ooops how the %$^$ do we break out of both loops?
end if
next
next
...
More code
...
end sub

Two ways to fix this:
1. Place the loop in its own sub and use 'exit sub' in the loop instead (only how do we then return the right value??.
2. Recode the whole thing to not use for-next.

Both methods of which are imho silly. However if you could add one bloody goto.

Quote:
Originally Posted by
cout << "Half the sum is " << sum << 2 << " or at least I hope so.\n";

Can you fix this with parens? Sure. But you're being confusing. The operator is bit-shift and text output in the same expression regardless of how many parentheses you add to it. It's the same problem as using + for string concatenation -- it's inherently confusing when stuck next to + for integer arithmetic. So choosing one of a number of existing symbols with existing meanings (like operators) rather than a richer vocabulary (like words, used for function names) is guaranteeing that you have a lot of unrelated baggage attached to any name you give an operation unless that operation already matches the symbol you're using. As you point out, there is no symbol that matches cin/cout -- they could have used xor (^) or function call with dereference (->) or any of many other operators -- and those would have been confusing, too.
Yes. This in VBScript, where you can't explicitly type cast anything, results in fun stuff like a = b + c returning a concatenated string instead of a number some times, because if b or c are marked internally as strings at that moment the engine 'guesses' at which operation you intended. Usually it gets it right, but in some cases it royally screws up. Unfortunately it is easier to read + than:

a = concat("Hello ", b);
a = concat(a, " how are you? - ");
a = concat(a, c);

Though it is less ambiguous to use concat. The same of course goes for using & and getting concat instead of AND. My advice would be try using VBScript to code something that requires a lot of this kind of dual use syntax and see how much more fun it is when the language doesn't even know what 'type' a variable is, until you do something to it. MS design philosophy - "It can always get worse, so lets see how we can make it so." lol

NOTE: Pure VB is also prone to this kind of guessing some times, which is why you should shoot anyone that doesn't correctly type cast their variables in it, to avoid having them breed even more morons. Though it is a good idea to be careful that you don't kill the ones that intentionally defined non-typed variant class variables for a good reason. Had MS used a keyword instead of just making non-typed variables default to variant this would of course not been necessary, but since no one seems to want to take Basic and manhandle it out of the hands of MS so it could be fixed...
shadowfyr is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 03-21-2003, 09:59 AM   #20
Kastagaar
Member
 
Join Date: Apr 2002
Location: Hampshire, UK
Posts: 117
Kastagaar is on a distinguished road
Send a message via Yahoo to Kastagaar
Quote:
Originally Posted by
cout << "Half the sum is " << sum << 2 << " or at least I hope so.\n";
Nope, that's double the sum.

Which just goes to show two things:

a) Good programming practices eliminate the majority of "This Is Evil" code snippets. For example, above, you 1) introduce a "magic number", 2. 2) Have more than one side-effect on the same line (you're performing output, and maths) instead of logically separating your code. 3) deliberately using unclear (well, less clear than "sum/2") logic. Two of these three points would have removed the error.

b) One should check at least three times when trying to be a smartarse

Bottom line: I have to wonder what sort of weight should be given to the argument "Feature X is bad. As an example, I give Bad Code Y". Because it can usually (and certainly in the cases of operator overloading and templates) be stated equally as "Feature X is good. As an example, I give Good Code Z".

Kas.
Kastagaar is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 03-26-2003, 02:59 PM   #21
angelbob
Member
 
Join Date: Feb 2003
Location: Bay Area, CA, USA
Posts: 39
angelbob is on a distinguished road
Your argument (Yui) that every feature is a good feature because it improves the expressivity of the language is interesting. Are you a massive fan of Perl for large projects for that reason?

My problem with C++ in practice has been that the average quality of code I've seen is terrible, even compared to similar projects in C. And the code I'm talking about is actually at professional software companies I've worked at. By "terrible" I mean "prone to crash/deadlock and hard to debug". The problems have been that different people use different subsets of the language, nobody knows the whole language, and you have to debug the code of people that use a different subset of the language than you do.

In a programming project that you control, you get to be the autocrat and spend a lot of time tearing misused or "wrong" (i.e. forbidden) features out of code other people submitted. As in a professional software environment, nobody reads the coding standards and nobody follows them, so you still have to go in and fix the results afterward.

Fair enough.

Goto is a fine example of the same principle. There are specific examples where it's basically acceptable. Palm (the company) used it for about the same purpose you list above, though with a couple more restrictions. Nonetheless, the vast majority of C code I've seen using "goto" is quite bad. Overall, its existence has done far more harm than good for the maintainability of the code I've seen in my professional career. In my private code I don't work on C++ projects with other people so it's a non-issue.

I'd like to again draw attention to the phrase I used above, the one that goes "nobody knows the whole language". C is a pretty snappy little language, and a clever fellow can figure out the whole thing and know the vast majority of the subtleties (what does "++bob++" do if "bob" is an integer? Is it legal? Which has higher precedence?) within a couple of years of regular use.

I've interviewed with a guy who was on the C++ ANSI standards committee. I've worked professionally in C++ for several years, and I've worked with many people who use it very regularly. I've built C++ parsing code, code to produce it from a template, debugged massive systems and worked under about four different template libraries in it at three different major companies. What I have never done, though, is to meet somebody with a very firm grasp of all the current standard language subtleties and how they work together.

By contrast, I've probably met about six people who could say that for C and who actually keep up with all the latest ANSI standards. Perl, like, C++, seems to have no full-on experts. It's simply too big, too varied and too weird.

Like you say, we could just rule out big chunks of the language and be an expert on the rest. If you believe that will work, you've worked on very different projects with very different people than I have. At least at the companies I've worked at and on the OSS projects I've worked on, you can't get people to follow the project's coding standards without constant and painful enforcement.

Though I suppose, if you had any significant number of contributors, you could just reduce your whole role to "constant and painful enforcement". That's what I've been doing primarily on my project lately -- and I'm using a simpler, cleaner language than C++.
angelbob is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 03-26-2003, 05:13 PM   #22
Yui Unifex
Senior Member
 
Join Date: Apr 2002
Location: Florida
Posts: 323
Yui Unifex is on a distinguished road
Send a message via ICQ to Yui Unifex Send a message via AIM to Yui Unifex
Question

Quote:
Originally Posted by (angelbob @ foo)
Your argument (Yui) that every feature is a good feature because it improves the expressivity of the language is interesting. Are you a massive fan of Perl for large projects for that reason?
I don't believe that every feature is good because some features are 'forced', or are mutually exclusive with other features. Case insensitivity is an example I gave of one such feature that has advantages at some times, and disadvantages at others. If there's a large project, knowing how to take advantage of Perl's features gives me an edge over someone who does not know how to take advantage of those features. So if the large project is something like a system administration front-end that is heavy on the regular expression parsing (see the Cobalt RaQ's backend system), Perl would indeed be a good choice. If the large project is very performance intensive, then Perl would probably not be. It's all about choosing the right tool for the job; I will never blindly advocate that one language is the best for all purposes.

Quote:
Originally Posted by (angelbob @ bar)
My problem with C++ in practice has been that the average quality of code I've seen is terrible, even compared to similar projects in C. And the code I'm talking about is actually at professional software companies I've worked at.
This is a fair judgement. My experiences have been mixed: I've had to debug C programs written to control PLC-enabled conveyor systems while talking to an Informix database. Problem ended up being a bug in the linked list structure that the previous programmer (now long gone) had rolled. In my business (basically an employed software consultant), I get to talk to a *lot* of software development houses, and I almost always end up wondering how in the world these people stay afloat with their limited knowledge. I would not be so quick to trust their code with any language.

Quote:
Originally Posted by (angelbob @ baz)
As in a professional software environment, nobody reads the coding standards and nobody follows them...
If you're having problems with people not reading and following coding standards in a professional environment, something's not right. This is one of the easier things for the coders to grasp; all they need to do is consult a list.

Quote:
Originally Posted by (angelbob @ foo)
Overall, its existence has done far more harm than good for the maintainability of the code I've seen in my professional career.
Just to make sure that you're not arguing for this: Language designers, to an extent, should not be responsible for these problems. They arise mostly from user-error; to remove it would be like removing 'dd' from unix systems because it's possible to destroy the hard drive with it. There are certain things they could do to reduce the desirability of goto, such as using named breaks to take care of the issues that shadowfyr raised, and these are things that language designers rightly should be concerned with.

Quote:
Originally Posted by (angelbob @ bar)
What I have never done, though, is to meet somebody with a very firm grasp of all the current standard language subtleties and how they work together.
As languages get higher and higher level, and people are able to express more and more constructs in them, it will indeed be difficult for programmers to learn the subtleties of an entire language. But I don't see this as a bad thing; if one absolutely requires that there be no subtleties at all, one should then use a language with no subtleties. But if one wants to make use of higher-level features such as closures and polymorphism, one will have to accept this complexity. Complexity at the language level here leads to simplicity at the algorithmic level. The right tool for the job is what should be chosen. We don't communicate with grunts and gestures, even though they would be totally unambiguous, with absolutely no side-effects, than the higher-level languages that we all speak.

Quote:
Originally Posted by (angelbob @ baz)
Like you say, we could just rule out big chunks of the language and be an expert on the rest. If you believe that will work, you've worked on very different projects with very different people than I have.
Yes, I do believe that will work. This is what humanity has been spiraling towards ever since the concept of 'specialization' has been discovered. To understand the complexities of nature one has used abstraction and specialization. I see nothing wrong with it, and if today's generation of programmers can't handle it (but they can ;)), then the next generation will replace them. Designing to the least-common-denominator is a sure-fire way to encourage mediocrity rather than excellence.

Quote:
Originally Posted by (angelbob @ foo)
...and I'm using a simpler, cleaner language than C++.
However you may define 'cleaner', it has already been shown (and gone uncontested) that C++ is cleaner than C in some cases. It would be more correct to say, "I'm using a simpler language that is cleaner than C++ in some cases". Remember that absolutes are absolutely horrid things; their scope is so grand that they are nearly impossible to prove, but they are ridiculously simple to disprove.
Yui Unifex is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 03-26-2003, 08:29 PM   #23
angelbob
Member
 
Join Date: Feb 2003
Location: Bay Area, CA, USA
Posts: 39
angelbob is on a distinguished road
Yui:
Quote:
Originally Posted by
I don't believe that every feature is good because some features are 'forced', or are mutually exclusive with other features.
Sure, but what about features that are just hard to read, even when they're easy to write? I mention Perl specifically because it gets such a reputation as a write-only language. It gets this reputation because of things like its regular expression syntax (very difficult to read, and very small subtleties can change the meaning a *lot*) and the fact that a tremendously wide variety of inputs can parse to *something*.

One reason I'll call a language "clean" is if no two valid inputs in the language look very similar to each other. That is to say, if any two valid inputs in the language are reasonably easy to disambiguate from each other, especially two inputs which are basically dissimilar.
And by "disambiguate", I mean only if you're reading it. A parser, of course, won't have much trouble either way.

Quote:
Originally Posted by
If there's a large project, knowing how to take advantage of Perl's features gives me an edge over someone who does not know how to take advantage of those features.
If you're *writing*, as opposed to reading or modifying, I agree with this statement.

Quote:
Originally Posted by
If the large project is very performance intensive, then Perl would probably not be.
Actually, Perl's remarkably fast. It's not quite up with static compiled languages like C or Pascal, and certainly not Fortran. On the other hand, it compares very favorably to anything interpreted and most things that are compiled.
That's mainly because they have a really good optimizer, though, and the fact that the whole language is designed with that in mind.
Anyway. Sorry. Off-topic.

Quote:
Originally Posted by
I get to talk to a *lot* of software development houses, and I almost always end up wondering how in the world these people stay afloat with their limited knowledge. I would not be so quick to trust their code with any language.
Because good people are extremely rare. Software houses that employ a very small number of very good people will essentially never go out of business. They will also very, very rarely get really big. Most markets require a lot of customer service, and a lot of very large software to be built. Therefore, any approach that requires a very high average level of brilliance, or that allows brilliant people to be easily sabotaged by idiots they're working with, won't grow to fill the niche. It will instead be overtaken by a small army of strongly competent fellows who are, collectively, more brilliant than the five incredibly savvy guys at the other company.

That's just one of the many reasons that languages that allow good modularity are so popular.

Quote:
Originally Posted by
If you're having problems with people not reading and following coding standards in a professional environment, something's not right. This is one of the easier things for the coders to grasp; all they need to do is consult a list.
And you're successfully making coders do that, even though no two can agree on a good coding standard, how? The only correct answer is "enforcement". The only common answer is "optimism". Where have you worked, that you haven't had problems with this? My experience with free projects is that carefully-written, carefully-posted and carefully-followed coding standards are all well and good, but free contributors simply will not follow them unless you enforce rigidly.

The same is essentially true at a professional software house, and nobody wants their job to be enforcing coding standards. Well, okay, John did, but we laid him off and he left for Norway. It's a shame, he was good at it.


Quote:
Originally Posted by
angelbob:
Overall, its existence has done far more harm than good for the maintainability of the code I've seen in my professional career.

Yui:
Just to make sure that you're not arguing for this: Language designers, to an extent, should not be responsible for these problems. They arise mostly from user-error; to remove it would be like removing 'dd' from unix systems because it's possible to destroy the hard drive with it.
Very much like that, yes. Ever notice how on modern Linux systems, root logins come configured by default to alias "rm" to "rm -i"? So instead of deleting files automatically, it'll ask to make sure you typed what you meant.

One could imagine a similar scenario where "dd" was aliased to always prompt when you used it on a hardware device (rather than just a file), so it would make you specifically say "yes" before doing something potentially stupid. The DOS "Format" command already does/did that.

I consider all of those to be basically good things. Should language designers avoid easily-abusable features in favor of features that tend to produce better code on average? Absolutely. Unquestionably. Should they remove features (like pointers) that can sabotage other people's work silently and without them specifically opting into it? Where possible, yes. Pointers specifically are a great example of a feature which can't be removed without a speed hit. I still try to use languages without them, where possible and appropriate.

Would any given lanuage be better if we added a bunch of new features? Maybe. CommonLISP plus pointers, for instance, or Java plus pointers, would be a step back. SML plus pointers would be an abomination -- like C++, it would have sabotaged its greatest asset, though for different reasons.

"Sabotaged its greatest asset?" Yeah. Being object-oriented is C++'s greatest asset. That means a real type system. The basis of data protection in a type system (private, protected, static, etc) is enforcement. Private fields aren't private as long as C++ has pointers.

Anyway. Sorry. That's a different anti-C++ tirade, and it's not like C has a real type system either -- it just doesn't pretend to.

Yui:
Quote:
Originally Posted by
As languages get higher and higher level, and people are able to express more and more constructs in them, it will indeed be difficult for programmers to learn the subtleties of an entire language.
Thank you. This is a very concise restatement of what I said earlier about "hard to debug" and "other people's code".
Incidentally, there *are* new languages that focus on having fewer features rather than more, and some of them are very much improved by it. SCHEME is easily embeddable because of it. SML/NJ is possible because of it -- full static type analysis is essentially impossible on most imperative programming languages, and you wouldn't want it anyway. Java is cleaner because of it, having removed some nastiness that C++ added.

Quote:
Originally Posted by
But I don't see this as a bad thing; if one absolutely requires that there be no subtleties at all, one should then use a language with no subtleties. But if one wants to make use of higher-level features such as closures and polymorphism, one will have to accept this complexity.
Sort of. You're saying here "to use closure and polymorphism, you must use a language with enough subtleties that nobody will properly understand the language". My counterexamples are Scheme, CommonLISP, Dylan and SML (for closures) and CommonLISP, Dylan, SML, LPC, SmallTalk (for polymorphism). Note that there are a decent number of languages even in the intersection of the two.

Beyond a certain number of simultaneous features, you're right, you have to have a language that's too complicated to understand. Speaking of which, if C++ has closures then we mean two very different things by "closures" or C++ has added a feature I'm not familiar with. I'm used to closures requiring lambda functions or something like them.

Quote:
Originally Posted by
Complexity at the language level here leads to simplicity at the algorithmic level. The right tool for the job is what should be chosen. We don't communicate with grunts and gestures, even though they would be totally unambiguous, with absolutely no side-effects, than the higher-level languages that we all speak.
Actually, grunts have no established meaning and are entirely ambiguous. And complexity at the language level adds to simplicity at the algorithmic level only if you can match a language primitive with the task at hand. Near-misses on language primitives are usually as bad as not having anything at all (such as using code inheritance for physical MUD objects, as we discussed earlier, or using C++ inheritance for a system with dynamic inheritance).

For common structures (such as lists and hash tables), though, I agree -- complexity at the language level leads to simplicity at the algorithmic level. Though the stuff we were discussing earlier was all simplicity at the syntactic level, which I consider to be a separate issue.

More specifically, complexity at the standard library level tends to lead to simplicity at the algorithmic level. Complexity at the language level tends to lead to simplicity at the syntactic level.

Quote:
Originally Posted by
angelbob:
Like you say, we could just rule out big chunks of the language and be an expert on the rest. If you believe that will work, you've worked on very different projects with very different people than I have.

Yui:
Yes, I do believe that will work. This is what humanity has been spiraling towards ever since the concept of 'specialization' has been discovered. To understand the complexities of nature one has used abstraction and specialization.
So you feel that the potter's wheel was designed to allow more variation than shaping clay with your hands? Nope. *Less*. There are *fewer* shapes that can be manufactured with a potter's wheel, and those shapes can be created with less effort for each one. By *restricting* the expressiveness of the medium, the total labor can be reduced.
Specialization *restricts* the vocabulary of an individual, and even of a socity -- you see practically nobody that works in clay/glass hybrid objects because those are considered separate specializations so there's little overlap. That wasn't always true.

But by restricting the expressiveness of the media involved, we get everything with less labor. Old fabrics, done by hand on a loom made of strings and a rock were more complex than the most impressive stuff we can do on our big modern computer-controlled looms -- and yet our modern stuff produces it at a tiny fraction of the cost, so we're wearing simpler fabrics and not worrying about it.

By *restricting* expressiveness, we've reduced total labor.

And in the same way, the fact that I use C means I'll never have to debug a code submission that requires me to understand all the stuff that can go wrong with C++ code templates. I've saved myself a couple of months of my life that way, and I'm happy about it.

Quote:
Originally Posted by
I see nothing wrong with it, and if today's generation of programmers can't handle it (but they can ), then the next generation will replace them. Designing to the least-common-denominator is a sure-fire way to encourage mediocrity rather than excellence.
Yup. Garbage collection is argued against for the same reason -- it doesn't require you to track everything, and so it'll be overrun by higher-performance languages where you have to track all the allocations by your lonesome. The results are better, even if they're more error-prone and require more intelligent programmers.

And Perl, Python and Java overtake C and C++ while we stand in denial, because there are fifty times more people who can be perfectly adequate programmers than can be brilliant programmers, and fifty adequate guys is worth at least two brilliant guys. More on some problems. Only two? Sure. But that's still twice what the brilliant guy can do.

Of course, you could also make sure that the language the only-adequate people use is sufficiently "expressive", and then none of them can debug it. Lamentably, that's why something as awful as Visual Basic is also overtaking C and C++.

Quote:
Originally Posted by
angelbob:
...and I'm using a simpler, cleaner language than C++.

Yui:
However you may define 'cleaner', it has already been shown (and gone uncontested) that C++ is cleaner than C in some cases. It would be more correct to say, "I'm using a simpler language that is cleaner than C++ in some cases". Remember that absolutes are absolutely horrid things; their scope is so grand that they are nearly impossible to prove, but they are ridiculously simple to disprove.
Well, except absolutes like "A and B implies A", or "not not not A implies not A", and absolutes like "this car is painted red". Which would prove your point nicely if it didn't also disprove your point.

But yes, C++ is cleaner for some specific things. The things you proved it was cleaner for were specific C++ language features (C sucks for operator overloading, I'll grant you), and ones that I feel still shouldn't be used. But in the same way that APL or Fortran absolutely rocks if you need to take the inverse transpose of the product of a 9x7 with a 7x15 matrix, C++ rocks for operator overloading.

Incidentally, APL is another long-forgotten example of a write-only language in a very specific domain. It does array processing (thus the name). It has operators for, like, everything you can do to an array. But since nobody remembers what the operators do when they read them, it doesn't matter -- the code's simply not maintainable. Rather like the way some parts of the Perl regexp system work, or some of the finer points of C++ RTTI and typecasting stuff.
angelbob is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 03-26-2003, 08:33 PM   #24
karlan
Member
 
Join Date: Apr 2002
Location: Brisbane Australia
Posts: 74
karlan is on a distinguished road
Unhappy

A lot of the arguments being used seem to me to be more about how people use it. If a company has standards that people should be using they should use it. Ihave worked for a couple of companies with different coding standards, and when people have followed the standard it is often simple to maintain/modify other peoples code, the exceptions to this were the "prima donna" programmers who felt they were indispensible and so didn't have to follow the standards, and they produced hard to understand, and difficult to follow code. This is not a problem with the language but with the programmer.

If nothing else a little bit of concise commenting can simplify maintenace a whole lot.

just my 2c
karlan is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 03-27-2003, 05:01 PM   #25
angelbob
Member
 
Join Date: Feb 2003
Location: Bay Area, CA, USA
Posts: 39
angelbob is on a distinguished road
Karlan:
Quote:
Originally Posted by
A lot of the arguments being used seem to me to be more about how people use it.
Well, yes. Assembly language can be used quite well, commented well, macros added, et cetera. Nonetheless, if somebody was to ask me "should people use C or assembly?" I would immediately answer "C, if possible".

Even though assembly is capable of things that C is not. Even though using C instead of assembly is compensating for programmers being less brilliant rather than making them work for their good code. Even though the maximum quality of the code is less than for assembly. Even though the arguments for using C are all about how people use assembly, not whether it can be done well.

Despite all of those things, I'd still recommend C over assembly. Ditto for C++. And the Future Crew, who did wonderful demos in assembly language, can laugh at me all they like.
angelbob is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 03-27-2003, 08:16 PM   #26
karlan
Member
 
Join Date: Apr 2002
Location: Brisbane Australia
Posts: 74
karlan is on a distinguished road
Are you saying you feel C++ is a step forwards or backwards from C?
karlan is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 03-27-2003, 08:30 PM   #27
Yui Unifex
Senior Member
 
Join Date: Apr 2002
Location: Florida
Posts: 323
Yui Unifex is on a distinguished road
Send a message via ICQ to Yui Unifex Send a message via AIM to Yui Unifex
Quote:
Originally Posted by (angelbob @ foo)
Sure, but what about features that are just hard to read, even when they're easy to write?
Yes, even those features.

Quote:
Originally Posted by (Yui Unifex @ bar)
If there's a large project, knowing how to take advantage of Perl's features gives me an edge over someone who does not know how to take advantage of those features.
Quote:
Originally Posted by (angelbob @ bar)
If you're *writing*, as opposed to reading or modifying, I agree with this statement.
What? Given that almost all projects spend most of their lifetime in the maintenance stage, I obviously wouldn't know how to take advantage of Perl's features if I couldn't read or modify it. I was able to extend the Cobalt RaQ's Perl administration application with little difficulty, and I've barely written 200 lines of Perl. Either I'm a genius or the program was easy to modify, and I don't think it's the former.

Quote:
Originally Posted by (Yui Unifex @ baz)
If you're having problems with people not reading and following coding standards in a professional environment, something's not right. This is one of the easier things for the coders to grasp; all they need to do is consult a list.
Quote:
Originally Posted by (angelbob @ baz)
And you're successfully making coders do that, even though no two can agree on a good coding standard, how? The only correct answer is "enforcement". The only common answer is "optimism". Where have you worked, that you haven't had problems with this?
To go against the style of the project is both unprofessional and sloppy, no matter how poor the style of the original project is. If you think your style is better than the one being used, hash it out with the project manager. I should not have to mentally switch between X number of styles when I go to maintain the code in the project. If your coleagues have problems with this, I do suggest "enforcement". But honestly, most people I've worked with don't need to be told about something so basic. It's only the interns and prima donnas (as karlan mentioned) that seem to have problems with it.

Quote:
Originally Posted by (angelbob @ Assets!)
"Sabotaged its greatest asset?" Yeah. Being object-oriented is C++'s greatest asset. That means a real type system. The basis of data protection in a type system (private, protected, static, etc) is enforcement. Private fields aren't private as long as C++ has pointers.
First of all, C++ is a multi-paradigm language, and this is its greatest asset, IMO. Its type system is "real"; it's called "strong typing". If you have to cast something, you'll very often get undefined behavior. And no, pointers do not have anything to do with the privacy of a field, because only the class can decide whether to allow a pointer to a private field to exist. This is the exact same with Java and references. This sabotage is completely non-existant.

Quote:
Originally Posted by (angelbob @ foo)
Actually, grunts have no established meaning and are entirely ambiguous.
*grunt* now means "pizza". Now grunts have established meaning and we can continue with our regularly scheduled programming. Honestly, no language has an established meaning other than what the users of that language assign to it. To get back to the point, if one were to have complete simplicity with absolutely no abstraction nor any "subtleties", that is the linguistic equivalent of assembly. But to everyone's chagrin, we now use languages that can express higher levels of abstraction: C has more than asm, C++ has more than C, Python more than C++, Common LISP more than Python.

Quote:
Originally Posted by (angelbob @ bar)
And complexity at the language level adds to simplicity at the algorithmic level only if you can match a language primitive with the task at hand.
No. A language primitive need only match a neighboring part of the construction of the task to increase simplicity at the algorithmic level.

Quote:
Originally Posted by (Yui Unifex @ baz)
Yes, I do believe that will work. This is what humanity has been spiraling towards ever since the concept of 'specialization' has been discovered. To understand the complexities of nature one has used abstraction and specialization.
Quote:
Originally Posted by (angelbob @ baz)
So you feel that the potter's wheel was designed to allow more variation than shaping clay with your hands? Nope. *Less*. There are *fewer* shapes that can be manufactured with a potter's wheel, and those shapes can be created with less effort for each one. By *restricting* the expressiveness of the medium, the total labor can be reduced.
By using a wheel a potter is not restricting what he can create! Using a wheel does not preclude the potter from shaping with his hands once the general shape has been achieved. It is just a tool; the equivalent of a subset of a language, not the language itself.

Quote:
Originally Posted by (angelbob @ foo)
Specialization *restricts* the vocabulary of an individual, and even of a socity.
Not even close. Name one speciality that *restricts* your vocabulary rather than merely drilling down into the complexity of a subject.

The most ironic thing is that these are all arguments for why C++ should be encouraged:
Quote:
Originally Posted by (angelbob @ bar)
Old fabrics, done by hand on a loom made of strings and a rock were more complex than the most impressive stuff we can do on our big modern computer-controlled looms -- and yet our modern stuff produces it at a tiny fraction of the cost, so we're wearing simpler fabrics and not worrying about it.
The modern textile factory is vastly more complex than the looms of old. It has higher-level constructs (machines, assembly-line) as a whole, even if the role of the individual is lessened in the Big Picture. So I agree with your argument here. C++ in some cases will allow you to produce stuff at a tiny fraction of the cost, because there are more higher-level constructs that one can make use of.

Quote:
Originally Posted by (Yui Unifex @ baz)
Designing to the least-common-denominator is a sure-fire way to encourage mediocrity rather than excellence.
Quote:
Originally Posted by (angelbob @ baz)
Garbage collection is argued against for the same reason -- it doesn't require you to track everything, and so it'll be overrun by higher-performance languages where you have to track all the allocations by your lonesome.
You've completely missed the point. If garbage collection were an *optional* feature, it could be used in cases where it was beneficial and avoided where it was not. Designing to the least-common-denominator is only an argument against garbage collection when that feature is forced upon the users. You should understand by now that I am arguing the exact opposite of this.

Quote:
Originally Posted by (angelbob @ foo)
But yes, C++ is cleaner for some specific things.
*cheers*

To enumerate the covered advantages of C++ (vs. C) in our debate:
1) When you want generic code such that a user of your library can call functions with both user-defined and built-in types.
2) When you want to change the return value of a function used in I/O without having to go back and change all users of that return value.
3) When you want an error-handling system that is not coupled to the return type of functions.
4) When you want natural math operations with user-defined types.
5) When you don't want to write Yet Another Linked List, or Yet Another String Handling System.
6) When you want to use strings with pass-by-value semantics.

And for C:
1) When you don't want to deal with other people doing something you don't understand or don't like.

(Edit: Added 'or don't like' to C's advantage.)
Yui Unifex is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 03-28-2003, 12:12 AM   #28
Lindahl
New Member
 
Join Date: Feb 2003
Location: California, US
Posts: 5
Lindahl is on a distinguished road
7) When you want error-proof typecasting (polymorphism).
8) When you want error-proof deallocation of internal data of a type (avoid memory leaks that are a pain to find!!!.

And many more, I don't want to sit here all day.
Lindahl is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 03-28-2003, 03:05 PM   #29
angelbob
Member
 
Join Date: Feb 2003
Location: Bay Area, CA, USA
Posts: 39
angelbob is on a distinguished road
Karlan:
Quote:
Originally Posted by
Are you saying you feel C++ is a step forwards or backwards from C?
I'm arguing it's backwards. Yui is arguing that it's forwards. That's our basic disagreement.

His argument is: C plus more features must be better than C. My argument: C plus features that are frequently misused is generally worse than C.

Beyond that, we're just hashing through whether C++'s features are generally a good or bad thing. His argument: the potential upside is greater since you don't have to use bad stuff, or use stuff badly. My argument: this stuff is generally used badly.

There's a lot more detail, but you can read through at your leisure, this stuff's probably on the 'net forever.
angelbob is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Old 03-28-2003, 04:18 PM   #30
angelbob
Member
 
Join Date: Feb 2003
Location: Bay Area, CA, USA
Posts: 39
angelbob is on a distinguished road
Quote:
Originally Posted by
angelbob:
Sure, but what about features that are just hard to read, even when they're easy to write?

Yui:
Yes, even those features.
As you say, most projects spend the vast majority of their time and effort in the maintenance stages. Features that are hard to read are a fine example of wasting effort -- how many times do you read code compared to how often you write it?
With that said: sure, whatever.

Quote:
Originally Posted by
Yui:
If there's a large project, knowing how to take advantage of Perl's features gives me an edge over someone who does not know how to take advantage of those features.
This is from an earlier message. Incidentally, you understand that if any such person as you mention (that can't take advantage of those features) is on your project that they can't debug what you just wrote, right?

For instance, I've had a bug where typecasting from one C++ type to another (legally, within the heirarchy, from a parent to a child class, yes) changed the numerical value of the pointer. So the literal value of the pointer was different than if you typecast to a void pointer in between. This is a fine example of a case where the "feature" is so "interesting" that even most people who use it don't know how to debug it.
I was lucky -- I distrust C++, so every feature that I use, I understand down to the bitwise level. The other people at the place I worked had to have it extensively explained to them how multiple inheritance might mean that a typecast changes the numerical value of the pointer being typecast. That's because it's not documented anywhere in any of the standard language books. I'm sure it's *somewhere*, but not anywhere that a regular programmer could find it, particularly not from the "symptoms" (apparent data corruption) that it causes.

C++ has a lot of rough edges like that. You could say, "don't use multiple inheritance", which is one answer. I think that's a shame since I like OO -- I just don't think that C++ is much of an OO language.

Quote:
Originally Posted by
What? Given that almost all projects spend most of their lifetime in the maintenance stage, I obviously wouldn't know how to take advantage of Perl's features if I couldn't read or modify it.
This kinda contradicts your statement, earlier in the same message, that you're in favor even of features that are easy to write but hard to read or modify.

Quote:
Originally Posted by
To go against the style of the project is both unprofessional and sloppy, no matter how poor the style of the original project is. If you think your style is better than the one being used, hash it out with the project manager.
A good project manager will never change a project's coding style, simply because of the amount of legacy code involved. In a corporation, justifying the massive time and expense of changing all the old code is basically impossible. I wish it weren't.

Quote:
Originally Posted by
But honestly, most people I've worked with don't need to be told about something so basic. It's only the interns and prima donnas (as karlan mentioned) that seem to have problems with it.
Then you've worked with a good (or academic, or tractable, or pedantic) crowd. My experience at NOW Solutions, Palm and Broadcom, plus Carnegie Mellon before that, strongly contradict this. Palm was better for awhile, if only because we had a guy that was good at enforcing this stuff.

The problem doesn't tend to be people wilfully ignoring the standard. It's that the standard isn't usually very complete , programmers don't fully know the language (as we agreed, that's pandemic in C++), and they don't fully remember the project coding guidelines and aren't going to go dig them up before writing more code.

It's not maliciousness, just negligence.

And I could eventually rule out all the bits of C++ that are nasty ("don't use operator overloading for things without established mathematical domains; don't use function inlining, even automatically and without the keyword, for large functions that are called more than once; don't use templates except for basic data structures, and preferably not then; don't use RTTI for anything that will EVER need to be portable; don't use any compiler other than the one I use -- they don't link against each other; etc, etc, etc). But nobody would follow it. Why? They wouldn't remember, or wouldn't agree, or wouldn't check before coding, or wouldn't realize that the standard covered that.

And they'd agree with you -- if the language has a feature, why not use it? Answer: because they're not good enough to fully debug what they submit within the context of the full project, and I don't want to debug stuff I don't fully understand (like large-scale template stuff or relatively subtle RTTI bugs). Since they can't debug what they submit, and I can't debug what they submit, they shouldn't submit it.

You ever try to tell somebody that? It doesn't work. You have to go in and rewrite it or tear it out later when it doesn't work. The hybrid code you get this way is beyond hideous.

Quote:
Originally Posted by
First of all, C++ is a multi-paradigm language, and this is its greatest asset, IMO. Its type system is "real"; it's called "strong typing".
Supporters of the language call C++'s type system that, yes. If you believe that C++ guantees privacy to private members, let me give you a nasty little example:

class myclass {
private:
int bob;
int sam;
public:
void playwithbobandsam(void);
}

/* Nasty code: */
myclass victim;

((int*)victim)[0] = 7; /* Set bob to 7 */
((int*)victim)[1] = 9; /* Set sam to 9 */

Where's your strong typing now? Destroyed by pointers. And the fact that C++ still typecasts wontonly and without being asked (yes, just like C) means that strong typing doesn't buy you much in practice. Languages with serious type systems (CommonLISP/CLOS, Smalltalk, Dylan) or runtime type systems (Perl, Python, CommonLISP/CLOS, Dylan, LPC) both tend to do better in this respect since they don't have a static type system that can be easily messed with.

You could say above that what I did to myclass isn't guaranteed to work. Actually, it is if you know that myclass isn't virtual because C++ makes a lot of the bit-layout stuff part of the standard. Crazy, huh?

Quote:
Originally Posted by
And no, pointers do not have anything to do with the privacy of a field, because only the class can decide whether to allow a pointer to a private field to exist.
Heh :-) Well, other than the example above, maybe.

Quote:
Originally Posted by
This is the exact same with Java and references. This sabotage is completely non-existant.
Nope. You can't do math on Java references, so the example above doesn't work. Ditto for Perl, Python, LPC and other pointer-free languages.

Quote:
Originally Posted by
angelbob:
Specialization *restricts* the vocabulary of an individual, and even of a socity.

Yui:
Not even close. Name one speciality that *restricts* your vocabulary rather than merely drilling down into the complexity of a subject.
I already did with the "ceramic and glass" thing in the original message, but I'll continue, shall I?

In assembly or (on some platforms) C/C++, you can take a pointer to a chunk of physical memory and directly write to it, as with the video memory. More "abstract" languages (Jave, Perl, Python, CommonLISP, Eiffel, Haskell, Dylan, LPC, SML/NJ, etc) won't let you do this. Your vocabulary is restricted from it.

Linguists begin by restricting a language to the spoken parts. Can they still talk about the other bits? Well, not to other linguists. Non-linguists don't tackle it because the linguists already are. Linguists don't tackle it because they claim it's not linguistics.

So you're saying that, because a specialty doesn't remove words from the language, it restricts nothing. I argue that because it causes certain areas of human experience to no longer be usefully expressable, it does. We're again back to the same argument as with C and C++ (yay, we're still on topic!. You argue that adding words to a language can never reduce expressiveness. I argue that reducing the comprehension of the language, no matter how many words you have, will still reduce useful expressiveness.

Let's say that we have a (natural) language which is English plus Swahili, the full union of the two. Both are complex, and both have a pretty substantial vocabulary. An average speaker is now *less* likely to understand another average speaker, and will be far more likely to need a dictionary to accomplish anything. Speech is now more difficult, comprehension rarer and the whole thing is less effort.

But between two fully omniscient speakers (which you agree are effectively impossible as the language grows more complex), it'll be a truly impressively expressive language.

Yup. Useless, but very expressive.

Now substitute writing code for speaking, and maintaining and debugging for reading.

Quote:
Originally Posted by
angelbob:
But yes, C++ is cleaner for some specific things.

Yui:
*cheers*

To enumerate the covered advantages of C++ (vs. C) in our debate:
[... Yui lists a number of features ...]

And for C:
1) When you don't want to deal with other people doing something you don't understand or don't like.
To list the advantages of English-plus-Swahili over English:

1) New verb forms
2) New vocabulary for all sorts of things, especially those found in tropical climates
3) More expressive ways to swear, to congratulate and to wish good cheer
4) More words for use in songs and poetry, with correspondingly greater expressiveness there
[etc]

And of English over Swahili-plus-English:
1) When you don't want to deal with other people saying something you don't understand or don't like.


See the parallel?

You continue to argue that language designers shouldn't avoid features just because they can be misused, or are usually misused (see "goto", above). But you're ignoring the fact that a very broad language with a vast array of features is harder to comprehend, harder to debug and harder for other people to get up to speed on or contribute to.

You're welcome to say that that's a problem with my coding style (actually, the coding style of my former professors and coworkers, I don't start projects in C++). Or that the people that would otherwise be extra developers are just too stupid (mediocrity versus brilliance, as you say).

But you know what? I've found that in a pretty simple language, mediocre programmers produce decent, maintainable stuff that does what it's supposed to. In C++, my experience is that they produce absolute horrors.

So should geniuses use C++ and mediocrities stick to Visual Basic? Maybe. But then the geniuses had better get used to never working on a project too large for four people.
angelbob is offline  
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Reply



Thread Tools


Which is preferred? - Similar Threads
Thread Thread Starter Forum Replies Last Post
Preferred Role Playing Level enigma@zebedee Advertising for Players 27 04-23-2003 07:01 AM

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On

All times are GMT -4. The time now is 12:56 AM.


Powered by vBulletin® Version 3.6.7
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO 3.0.0
Style based on a design by Essilor
Copyright Top Mud Sites.com 2007