www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - C++ traps that D2 doesn't avoid yet?

reply bearophile <bearophileHUGS lycos.com> writes:
This page lists a lot of C++ traps and pitfalls in a short space. I assume D
has to avoid or render meaningless a quite high percentage of them.
I'd like to list what of them D2 doesn't improve/fix yet, but my limited
knowledge of C++ lets me understand only a certain percentage of such list of
items (probably less than 75%) so probably I am not qualified yet to compare
that with the D situation. Later I may try to write such differential list
anyway...

http://www.johndeacon.net/Cpp/trapsAndPitfalls.asp

The nice thing of that list is that I think most (maybe 80-90%) of those traps
and pitfalls (and several others that aren't listed, like allowing simple
syntactical mistakes like putting a & where a && was requires or vice versa,
etc) can be avoided by a language like D with little or no penalty in running
space and time (and actually D avoids several of them already), but to avoid
some of them you have to pay the price of sometimes having to step away from
C/Java syntax, or probably worse having to assign a different semantics to some
C syntaxes (Walter has explained that this is sometimes dangerous because most
programmers know C/C++/Java and not D, but seeing the huge troubles C++ has
gone to be as much compatible as possible with C I'd say that keeping the
original C semantics when it is known to cause troubles is _always_ bad. In
such situations I prefer a language that acts correctly than one that acts
badly just to be like C, and maybe I don't even like a language that doesn't
use some handy C syntax just because the semantics is now different).

Bye,
bearophile
Nov 05 2008
next sibling parent Walter Bright <newshound1 digitalmars.com> writes:
bearophile wrote:
 or
 probably worse having to assign a different semantics to some C
 syntaxes (Walter has explained that this is sometimes dangerous
 because most programmers know C/C++/Java and not D, but seeing the
 huge troubles C++ has gone to be as much compatible as possible with
 C I'd say that keeping the original C semantics when it is known to
 cause troubles is _always_ bad. In such situations I prefer a
 language that acts correctly than one that acts badly just to be like
 C, and maybe I don't even like a language that doesn't use some handy
 C syntax just because the semantics is now different).
The trouble with this is when translating code. For example, take the md5 algorithm which is published in C, and translate it to D. It has some fairly complex arithmetic expressions in them. Do you know how they work? I don't. I have no idea. I doubt hardly anyone interested in translating them does. This means that if the meaning of an expression *silently* is altered by transliterating them to D, the new md5.d will give wrong results and it will be very difficult for the programmer to figure out where the problem is. This is why when D changes the semantics, it tries to restrict itself to changes that will produce compile time errors if the C is not transliterated correctly. For example, the C-style cast gives an error when it appears in D code, which prompts the user that some changes are necessary.
Nov 05 2008
prev sibling next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
bearophile wrote:
 This page lists a lot of C++ traps and pitfalls in a short space. I
 assume D has to avoid or render meaningless a quite high percentage
 of them. I'd like to list what of them D2 doesn't improve/fix yet,
 but my limited knowledge of C++ lets me understand only a certain
 percentage of such list of items (probably less than 75%) so probably
 I am not qualified yet to compare that with the D situation. Later I
 may try to write such differential list anyway...
 
 http://www.johndeacon.net/Cpp/trapsAndPitfalls.asp
At a glance, D does resolve a lot of them. But preparing a detailed response to his list is many hours of work.
Nov 05 2008
parent reply bearophile <bearophileHUGS lycos.com> writes:
Walter Bright:
 At a glance, D does resolve a lot of them. But preparing a detailed 
 response to his list is many hours of work.
I have removed the most obvious ones and cleaned up the list a little: 1) C++ is officially based on C. C features like name hiding can interfere with C++ features like function overriding. 2) Function name overloading is convenient and good when appropriate; but confusing if misused. Be careful that overloading and name hiding don't interfere. 3) Primitive operands, arguments and returns get converted to their operators' and functions' expectations. 4) The presence of templates means that class member declarations involving a pointer to a template parameter might be interpreted as multiplication if you don't disambiguate with "typename". 5) Because the default for both objects and primitives is to pass to and from functions by copy, copy constructors are called more often than one might first imagine. 6) The special functions will be used more than a sub-guru C++er would imagine. C++ makes copies and temporaries under several circumstances. Special functions have even more reason than usual to avoid side-effects and to be very careful about throwing. (And never throw from a destructor.) 7) C++ doesn't take the attitude that incorrect primitive operand or argument types should be compile errors; it assumes you meant what you wrote and want the operands and arguments to be converted. 8) Although you can start an identifier with an underscore, you shouldn't. Leading underscores are added to identifiers by C++ translators. 9) You might find bizarre things happening if you have an identifier like bitor or compl. They are alternative keyword forms of | and ~. 10) Tidying up columns of numbers with leading zeroes turns them into octal (base 8) numbers. 11) It's not an error to have two character symbols within the single quote marks of a char literal (constant). 12) The encodings for char and wchar_t are not defined. Don't assume ASCII or Unicode. 13) Literal floating-point values (constants) do not have type float; they have type double. 14) Dividing by zero doesn't result in an exception. It results in undefined behavior. You must check your divisors yourself. 15) Because assignment expressions are expressions and evaluate to values, and because values can frequently be converted to bool, accidentally using assignment where you meant comparison will almost always compile and fail silently at run-time 16) The order in which operands are evaluated is not defined. The fact that, for example, addition is defined to be left-associative, doesn't necessarily mean that the operands of the addition operator are evaluated from the left. 17) The operands of logical and and logical or are evaluated from the left; however, there is a new uncertainty: not all the operands need be evaluated at all. 18) Variables can hold values or pointers; and this applies to objects of class type as well as primitives. Be careful you don't assign to a pointer thinking it's a value, or vice-versa. Consider "Hungarian naming". 19) Under assignment, when a pointer to an object is assigned another pointer to an object, they end up pointing at the same object. However, if an object-holding variable (or a reference to an object) is assigned another object, it becomes some kind of copy. 20) The increment (but not the decrement) operator can be applied to bool! It will set it to true whatever it was. 21) The precedence order of some operators including the assignment operators and the conditional (arithmetic if) was changed in ISO C++. 22) Whether you use curly brackets or not, selection and iteration statements control blocks. And the block begins at the opening parenthesis, not at the opening curly bracket (if there is one). 23) Selection and iteration statements should be controlled by boolean expressions, but it is not a compile error to put in numeric expression. 24) Although the (somewhat redundant) parentheses that hold the control logic are mandatory, curly brackets are not. Don't leave traps for maintenance programmers always put the curly brackets in. 25) The = symbol is actually the assignment operator, so it's all too easy to say "if I can assign b to a" rather than "if a is equal to b". In C++, because numeric results can be converted to bool, such mistakes usually compiles, to fail silently later. 26) If you don't put the curly brackets into an "if", it will be difficult to tell which "if" an "else" belongs to, if the "if" is, or ever becomes, nested. 27) The switch statement is really a slightly-tarted-up goto. This hints that maybe the switch should be avoided. 28) The switch statement involves just one block. The sections within are demarcated only with statement labels. You will need break statements after each (including the last for maintainers) section. 29) Accidentally drop one of the colons (:s) of a scope resolution operator, and you might just end up with a labeled statement. 30) A switch gets exponentially more difficult to maintain. One new type to be handled can involve updating many, many switch statements. Contrast this with adding a new class behind a polymorphic type. Prefer object-orientation over switches. 31) Many, many examples of the for statement have i++ to increment the loop counter. If i is an int, it's not really significant, but there's always a chance that it might become an iterator, and then ++i is more efficient and here does just the same as i++. 32) A C++ compiler isn't required to report an error if a value-returning function has no return statement. 33) (-PI <= theta <= PI) is always true, because the first comparison results in true or false which then convert to 0 or 1 which are both less than PI. In languages that don't convert boolean the expression is thankfully a compile error. 34) This is almost an anti-trap since consts are nearly always good. However, if you forget to make your query-only member functions const, then const objects of your class won't be able to accomplish much. 35) Applying delete to a pointer doesn't set it to zero; but you should probably consider doing so. 36) Incorrectly accessing an array of arrays (when simulating a multi-dimensional array) as arr[i, j] instead of arr[i][j] is not a compile error even though it won't do what you probably expect. 37) References create aliases for identifiers. Be careful not to end up doing daft things like self-assignment. Self assignment might go horribly wrong for classes with badly-written copy assignment operators. 38) Do not return via references unless you are absolutely sure that you know exactly what you are doing. (And make sure you know if and how your compiler supports the return value optimization.) 39) Don't try to be tidy by including empty parentheses when initializing object in variables via the default constructor. You will actually declaring parameterless functions instead. 40) Don't think of public as meaning the same for data and function members. Public data members can be accessed; but public member functions can't be called. Public member functions define the signatures of messages that all other objects can send. 41) Unlike, say, Smalltalk, C++ has class-level encapsulation. An object isn't prevented from accessing the private data members of another instance of its class. Apart from the copy constructor and the copy assignment operator, don't allow one instance to access the data of another instance. 42) C++ doesn't enforce the private access category for data members. One day you'll be tempted to make a data member of a base class protected. Resist. Don't do it. From that moment on, the base class becomes unmaintainable. 43) Object instance arguments are passed by value, i.e. by copying. But forget to provide the copy constructor and one will be provided for you. And Finagle's Law says that anytime you do forget, the implicit copy constructor's behavior won't be right. 44) Forgotten parentheses on an argumentless message or call will often compile because a function's address is a valid numeric expression. 45) Const objects can change. While passing out a pointer (or reference) to a data member is hardly a subtle trap, data members can be declared mutable however; so we hope that such data member have been designed to be undetectable from outside their object. 46) Static data members are close to global. Static member function uses are close to calls (rather than messages). Overusing static members takes one away from object-orientation and towards the less useful class-orientation. 47) Never mix up the two initialization syntax schemes of "=" and "()". Try to always use ()-style initialization. Never, ever allow the initialization of an object of class type to involve = and () at the same time. 48) The C memory mechanisms malloc and free still exist in C++, of course. It's not a compile mistake to free() something newed or to delete something malloc()ed; just lethal. 49) It's not a compile error to "delete" (rather than "delete[]") something that was "new []"ed. It's almost certainly a memory problem though. 50) To realize how quickly it could become impossible to decide who takes out the garbage, one only has to recall that the default argument passing and return mechanisms are by-copy; and that the implicit copy constructor does shallow copy. 51) Looking for smart pointers to help with garbage collection and with polymorphic collections, one turns to the library. But the smart pointer one finds there auto_ptr mustn't be used for either of those purposes. 52) Don't pass an auto_ptr to a function by value. The auto_ptr will be copied and the copy will become the owner When the function finishes, the local copied auto_ptr goes out of scope and it will delete what it was pointing at. 53) Almost uniquely among languages today, C++ allows one to store entire objects in variables. This leads to no end of complications; and certainly leads to the special functions being special. 54) A class without constructors may well have implicit constructors. There are only two circumstance when an implicit copy constructor wouldn't be provided; and only a few more where a default constructor wouldn't. And the implicit ones are public. 55) People sometimes try to call one constructor from another. Don't. You can write something that looks like it might just be a call to a constructor but it won't be. Constructors are always declaration statement stuff rather than expression statement stuff. 56) A one-argument constructor will be implicitly used as a conversion function (argument type to class type) unless you say not to with the "explicit" keyword. And constructors with default parameter values might be also be considered single-argument. 57) Another reason not to use the = sign in declaration/initialization is to avoid encouraging the mistaken belief that the copy assignment operator would be used. It wouldn't be. The copy constructor will be used for both = style and () style initialization. 58) The implicit copy constructor effectively does shallow copy it copies pointers but not pointees. 59) Lulled into complacency by constructor chaining, you might imagine that the copy assignment operator automatically chains as well. It doesn't. You will probably want to though. 60) Data members holding objects of class type are default constructed before the constructor's code block runs. Initialize them via the member initialization list instead. 61) If you initialize an object of class type via {} expression lists, almost any change to the class will invalidate such an initialization. 62) The order of initializers in a member initialization list is irrelevant. Don't try, in a member intiailzation list, to initialize one member in terms of another unless you know the initialization order rules. 63) Although destructors can be called explicitly, it is an exotic and probably dangerous thing to do. Be happy with automatic calling of destructors. 64) The implicit destructor is non-polymorphic (non-virtual). Just about everyone, just about all the time must consider whether their destructor should be polymorphic (virtual); and probably conclude that it should be. 65) You might not think you need a destructor, but unless you can prove that your class could never be a base class, you should provide a virtual (not pure virtual) destructor, even it is has an empty code block. 66) Remember that neither the number of arguments nor their position contribute to the "name" of a member function. So an overload of unary +, say, in a derived class would hide a binary + in a base class. 67) Operator overloads are inherited but the implicit copy assignment operator usually hides any base class copy assignment operator. 68) You can't make && or || (or ,) operator overloads work intuitively, so don't provide them. (You can't mimic guaranteed operator evaluation order or lazy evaluation with member functions.) 69) You might be tempted to provide operator bool in order that your objects can easily be tested for validity. But beware that once your objects can be converted to bool, they can also be converted to int. 70) [Well known but] Not only is int converted to long, for example, but long is converted to int, and float is even converted to int. If you're lucky, a friendly compiler will issue a warning. So treat C++ compiler warnings as though they were errors. 71) Inheritance of implementation has not turned out to be the labor-saving device we thought it would be. (Unlike composition, it doesn't function through low-coupling, program-by-contract messages.) 72) While the maintainability of the derived classes goes up because of factoring, the maintainability of the base class rapidly goes down. So be sure your code is stable before you start introducing inheritance of implementation. 73) Given the fragility of base classes, they should always be destined and designed to be base classes. A class should never just slip into becoming a base class. Design your concrete, derived classes so that they could never become base classes. So why don't we ban inheritance? Because there's something more important than implementation to inherit. Public inheritance gives objects extra types; it supports polymorphism. 74) Private data members are present in the instances of derived classes. They just can't be accessed by derived class code (which is a good thing). 75) The class keyword brings private access for the members. But that includes inheritance; and private inheritance is not the object-oriented way. Private inheritance is the (now not very popular) mixin way. 76) Don't be trapped into mentioning base class names any more than you have to. Use the "typedef BaseClass super" trick to avoid it. And don't use any class name as part of a function name. 77) [As mentioned earlier] Beware if you think you're overloading a member function from a base class. A derived class member function with the same name as a base class member function name-hides the base class one. A using declaration can sort this out. 78) Unless you use virtual member functions, C++ doesn't give you polymorphic behavior. By default C++ uses the pointer type to select member functions. That way lies redundant overriding and inconsistent binding. 79) Don't be misled into thinking that there's anything "ghostly" or "not really there" about virtual member functions. Pronounce "virtual" as "polymorphic". (The ghostly ones are the pure virtuals.) 80) It's not a compile error to forget to pass a derived class object by pointer or reference, when the parameter declaration was for a base class object. What will happen is that the derived bits will be "sliced" off as the argument is copied onto the stack. 81) Although making a member function polymorphic (virtual) means that the object selects the member function, it's still the pointer type that selects the access category. If you override a member function in a different access category, a) we hope you've done it to be more restrictive, not less, and b) the type of the pointer chooses the access category determining class. 82) Don't be misled by the unforgivably obscure syntax (= 0) into thinking that pure virtual member functions are some dark and dusty corner that is to be ignored. They are pivotal to good OO. 83) Don't imagine that a class with no code and no data members is worthless. A class with nothing but pure virtual member functions (a pABC) is an excellent and simple type that classes can implement. 84) Don't by misled by some books (or even libraries and frameworks) into thinking it's OK to instantiate base classes. It's almost never a good idea you end up with a class doing three jobs, and two is bad enough. 85) If you disregard the earlier advice to allow one or none of your base classes to have implementation, you will also and always have to consider whether your inheritance should be virtual inheritance. 86) Don't imagine that because the RTTI (run-time type identification) was introduced, you should use it. Treat "What's your class?" as a rude question and use it only once in a blue moon. Overuse of the RTTI probably indicates an architecture that is failing not having enough 1:m association relationships or the 1:m association relationships having the wrong types. 87) It's not an afterthought (I hope) that the type_info object supports one in avoiding mentioning a class by name. Avoid building class names into anything but declarations. And even in declarations avoid concrete class names as types. 88) Putting "using namespace std" makes a very large set of unseen names available to clash in "what on earth's going on" kinds of ways with your identifiers - particularly at some point in the future. 89) There might be more namespaces than you thought in which C++ will look for a function. C++ also searches for a function in the namespaces in which any of a function's arguments of class type are defined. 90) If any function you call (or that it calls, or ...) could throw, you need to be an order of magnitude more careful a programmer than you would otherwise have needed. 91) A derived object catcher that follows a catcher for its base class can never be reached. 92) Although you don't have to catch exception objects by reference, getting into the habit of doing anything else is asking for trouble. See bit slicing. This list isn't complete, there are several things we have discussed in the past that aren't listed there. And then, there are other traps/troubles not listed there because specific of D and probably absent from C++. Bye, bearophile
Nov 06 2008
parent Walter Bright <newshound1 digitalmars.com> writes:
bearophile wrote:
 This list isn't complete, there are several things we have discussed
 in the past that aren't listed there.
For one thing, it doesn't mention concurrency gotchas.
Nov 06 2008
prev sibling next sibling parent reply ore-sama <spam here.lot> writes:
bearophile Wrote:

 This page lists a lot of C++ traps and pitfalls in a short space. I assume D
has to avoid or render meaningless a quite high percentage of them.
 The nice thing of that list is that I think most (maybe 80-90%) of those traps
and pitfalls (and several others that aren't listed, like allowing simple
syntactical mistakes like putting a & where a && was requires or vice versa,
etc) can be avoided by a language like D
 but seeing the huge troubles C++ has gone to be as much compatible as possible
with C I'd say that keeping the original C semantics when it is known to cause
troubles is _always_ bad. In such situations I prefer a language that acts
correctly
Most of these pitfalls are actually features, not bugs and are used massively. Like implicit casts, & instead of &&, assignment instead of comparison etc. These are pitfalls for novice programmers. Why bother? Everything is a pitfall for a novice programmer. You can safely say that every feature is a pitfall because programmer can make mistake in any place. I saw a man writing a program randomly typing something on the keyboard :) And he's not alone. What will be a pitfall for such programmers? ps why there was a need to reinvent identity operator, I wonder? It already was in JavaScript.
Nov 06 2008
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"ore-sama" wrote
 bearophile Wrote:

 This page lists a lot of C++ traps and pitfalls in a short space. I 
 assume D has to avoid or render meaningless a quite high percentage of 
 them.
 The nice thing of that list is that I think most (maybe 80-90%) of those 
 traps and pitfalls (and several others that aren't listed, like allowing 
 simple syntactical mistakes like putting a & where a && was requires or 
 vice versa, etc) can be avoided by a language like D
 but seeing the huge troubles C++ has gone to be as much compatible as 
 possible with C I'd say that keeping the original C semantics when it is 
 known to cause troubles is _always_ bad. In such situations I prefer a 
 language that acts correctly
Most of these pitfalls are actually features, not bugs and are used massively. Like implicit casts, & instead of &&, assignment instead of comparison etc. These are pitfalls for novice programmers. Why bother?
They can be made more difficult to do mistakenly. Even experienced developers fall into some of these traps. I know I occasionally fell into this trap: if(x); x->doSomething(); But no more with D, because it's not allowed. Those kinds of things can be easily prevented, and are common mistakes by all programmers. I appreciate any effort by the compiler to not compile code that can be definitively declared as invalid. It saves me time and bugs, and that is worth a lot. -Steve
Nov 06 2008
next sibling parent reply ore-sama <spam here.lot> writes:
Steven Schveighoffer Wrote:

 I appreciate any effort by the compiler to not compile code that can be 
 definitively declared as invalid.  It saves me time and bugs, and that is 
 worth a lot.
You said "definitely". Your example is meaningful, but this doesn't affect my examples.
Nov 06 2008
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"ore-sama" wrote
 Steven Schveighoffer Wrote:

 I appreciate any effort by the compiler to not compile code that can be
 definitively declared as invalid.  It saves me time and bugs, and that is
 worth a lot.
You said "definitely". Your example is meaningful, but this doesn't affect my examples.
Yes, you are probably right. Those can be valid either way, much more than my example. To be honest though, I more disagree with your assertion that only novice programmers are affected. I sometimes make these types of mistakes, and I definitely don't consider myself a novice ;) -Steve
Nov 06 2008
next sibling parent Walter Bright <newshound1 digitalmars.com> writes:
Steven Schveighoffer wrote:
 To be honest though, I more disagree with your assertion that only novice 
 programmers are affected.  I sometimes make these types of mistakes, and I 
 definitely don't consider myself a novice ;)
The if(e); is illegal in D because back in the 80's, the best programmer in the company came to me asking me why his for loop executed only once: for (i = 0; i < N; i++); ... He had spent all afternoon chasing this problem, first isolating it to the loop and then trying to figure it out. He was sure it was a compiler bug. I stared at it for a while, mystified too, until I saw the ;. There is no advantage to having the language accept such code, and even if the programmer wrote it on purpose, it *looks* like a bug. Code that looks right should be right, and code that looks wrong should be wrong.
Nov 06 2008
prev sibling parent reply Janderson <ask me.com> writes:
Steven Schveighoffer wrote:

 To be honest though, I more disagree with your assertion that only 
novice programmers are affected. I sometimes make these types of mistakes, and I definitely don't consider myself a novice ;)
 -Steve
A good point. We seem to have a lot of super programmers who don't make simple mistakes ever and know C++ back to front. That's Great! For myself, after programming in C++ for 7 years (and other languages before that) I still find myself making coding typo's and discovering new things about C++. Keeping an open mind is key to getting better. I bet even Bjarne Stroustrup himself does not know all the pitfalls he left in the language. A couple of quotes to put names to: "Anyone who has never made a mistake has never tried anything new." "...it's essential to keep an open mind, and to be willing--better yet, eager--to try new things." "The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it." -Joel
Nov 08 2008
next sibling parent reply ore-sama <spam here.lot> writes:
Janderson Wrote:

 We seem to have a lot of super programmers who don't make simple 
 mistakes ever and know C++ back to front.  That's Great!
Who knows C++? I know C, C# and javascript.
 For myself, after programming in C++ for 7 years (and other languages 
 before that) I still find myself making coding typo's and discovering 
 new things about C++.  Keeping an open mind is key to getting better.
Yeah, C++ is a continuous discovery, may be because of this C++ pros can't get used to if statement syntax? I thought, fingers know syntax, not brain... well, it's C++ after all :3
Nov 09 2008
parent Janderson <ask me.com> writes:
ore-sama wrote:
 Janderson Wrote:
 
 We seem to have a lot of super programmers who don't make simple 
 mistakes ever and know C++ back to front.  That's Great!
Who knows C++? I know C, C# and javascript.
I see then this kinda makes sense from where your coming from. C# has a load of restrictions that help detect possible gotchas that you don't get with C++. They could be removed to allow for more "expressive" code but then you'd have C++. For example, trying to change the size of an array your iterating over will flag an error in C#.
 
 For myself, after programming in C++ for 7 years (and other languages 
 before that) I still find myself making coding typo's and discovering 
 new things about C++.  Keeping an open mind is key to getting better.
Yeah, C++ is a continuous discovery, may be because of this C++ pros can't get used to if statement syntax? I thought, fingers know syntax, not brain... well, it's C++ after all :3
Nov 09 2008
prev sibling parent Walter Bright <newshound1 digitalmars.com> writes:
Janderson wrote:
 "The trouble with having an open mind, of course, is that people will 
 insist on coming along and trying to put things in it."
"An open mind is an empty mind." -- Mark Stroberg
Nov 09 2008
prev sibling next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Steven Schveighoffer wrote:
 Even experienced developers fall into some of these traps.  I know I 
 occasionally fell into this trap:
 
 if(x);
   x->doSomething();
 
 But no more with D, because it's not allowed.  Those kinds of things can be 
 easily prevented, and are common mistakes by all programmers.
Here's another fun one: printf("%d\n", 8l); What does that print?
Nov 06 2008
next sibling parent reply BCS <ao pathlink.com> writes:
Reply to Walter,

 Steven Schveighoffer wrote:
 
 Even experienced developers fall into some of these traps.  I know I
 occasionally fell into this trap:
 
 if(x);
 x->doSomething();
 But no more with D, because it's not allowed.  Those kinds of things
 can be easily prevented, and are common mistakes by all programmers.
 
Here's another fun one: printf("%d\n", 8l); What does that print?
8
Nov 06 2008
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"BCS" wrote
 Reply to Walter,

 Steven Schveighoffer wrote:

 Even experienced developers fall into some of these traps.  I know I
 occasionally fell into this trap:

 if(x);
 x->doSomething();
 But no more with D, because it's not allowed.  Those kinds of things
 can be easily prevented, and are common mistakes by all programmers.
Here's another fun one: printf("%d\n", 8l); What does that print?
8
On little endian systems, yes. On big endian it would print 0. -Steve
Nov 06 2008
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
BCS wrote:
 Reply to Walter,
 
 Steven Schveighoffer wrote:

 Even experienced developers fall into some of these traps.  I know I
 occasionally fell into this trap:

 if(x);
 x->doSomething();
 But no more with D, because it's not allowed.  Those kinds of things
 can be easily prevented, and are common mistakes by all programmers.
Here's another fun one: printf("%d\n", 8l); What does that print?
8
If I hadn't said it was a trap, I bet you'd have said "81".
Nov 06 2008
parent reply "Jarrett Billingsley" <jarrett.billingsley gmail.com> writes:
On Thu, Nov 6, 2008 at 5:07 PM, Walter Bright
<newshound1 digitalmars.com> wrote:
 BCS wrote:
 Reply to Walter,

 Steven Schveighoffer wrote:

 Even experienced developers fall into some of these traps.  I know I
 occasionally fell into this trap:

 if(x);
 x->doSomething();
 But no more with D, because it's not allowed.  Those kinds of things
 can be easily prevented, and are common mistakes by all programmers.
Here's another fun one: printf("%d\n", 8l); What does that print?
8
If I hadn't said it was a trap, I bet you'd have said "81".
I wouldn't've, because I use a font that actually distinguishes things 1, I, l, and | properly. <_<
Nov 06 2008
next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Jarrett Billingsley wrote:
 On Thu, Nov 6, 2008 at 5:07 PM, Walter Bright
 <newshound1 digitalmars.com> wrote:
 BCS wrote:
 Reply to Walter,

 Steven Schveighoffer wrote:

 Even experienced developers fall into some of these traps.  I know I
 occasionally fell into this trap:

 if(x);
 x->doSomething();
 But no more with D, because it's not allowed.  Those kinds of things
 can be easily prevented, and are common mistakes by all programmers.
Here's another fun one: printf("%d\n", 8l); What does that print?
8
If I hadn't said it was a trap, I bet you'd have said "81".
I wouldn't've, because I use a font that actually distinguishes things 1, I, l, and | properly. <_<
0 and O is another fun one. In any case, 8l is legal C, but illegal D.
Nov 06 2008
next sibling parent reply "Bill Baxter" <wbaxter gmail.com> writes:
On Fri, Nov 7, 2008 at 7:37 AM, Walter Bright
<newshound1 digitalmars.com> wrote:
 Jarrett Billingsley wrote:
 On Thu, Nov 6, 2008 at 5:07 PM, Walter Bright
 <newshound1 digitalmars.com> wrote:
 BCS wrote:
 Reply to Walter,

 Steven Schveighoffer wrote:

 Even experienced developers fall into some of these traps.  I know I
 occasionally fell into this trap:

 if(x);
 x->doSomething();
 But no more with D, because it's not allowed.  Those kinds of things
 can be easily prevented, and are common mistakes by all programmers.
Here's another fun one: printf("%d\n", 8l); What does that print?
8
If I hadn't said it was a trap, I bet you'd have said "81".
I wouldn't've, because I use a font that actually distinguishes things 1, I, l, and | properly. <_<
0 and O is another fun one. In any case, 8l is legal C, but illegal D.
Threre are various good programmer fonts out there today that are designed to make the 1 l | and 0 O distinctions clear. I use the Proggy fonts. http://www.proggyfonts.com/index.php?menu=download These days I'd say if you're not using one of these fonts for programming you're being an extremely silly person. --bb
Nov 06 2008
next sibling parent reply Lars Kyllingstad <public kyllingen.NOSPAMnet> writes:
Bill Baxter wrote:
 On Fri, Nov 7, 2008 at 7:37 AM, Walter Bright
 <newshound1 digitalmars.com> wrote:
 Jarrett Billingsley wrote:
 On Thu, Nov 6, 2008 at 5:07 PM, Walter Bright
 <newshound1 digitalmars.com> wrote:
 BCS wrote:
 Reply to Walter,

 Steven Schveighoffer wrote:

 Even experienced developers fall into some of these traps.  I know I
 occasionally fell into this trap:

 if(x);
 x->doSomething();
 But no more with D, because it's not allowed.  Those kinds of things
 can be easily prevented, and are common mistakes by all programmers.
Here's another fun one: printf("%d\n", 8l); What does that print?
8
If I hadn't said it was a trap, I bet you'd have said "81".
I wouldn't've, because I use a font that actually distinguishes things 1, I, l, and | properly. <_<
0 and O is another fun one. In any case, 8l is legal C, but illegal D.
Threre are various good programmer fonts out there today that are designed to make the 1 l | and 0 O distinctions clear. I use the Proggy fonts. http://www.proggyfonts.com/index.php?menu=download These days I'd say if you're not using one of these fonts for programming you're being an extremely silly person. --bb
I use and recommend the DejaVu Sans Mono font. With this font there is no chance of confusing those troublesome characters, and it's very easy on the eyes. Also, the DejaVu fonts are available in the repositories of many (most?) Linux distributions. http://dejavu.sourceforge.net/ -Lars
Nov 07 2008
parent Mike Parker <aldacron gmail.com> writes:
Lars Kyllingstad wrote:
 Bill Baxter wrote:
 On Fri, Nov 7, 2008 at 7:37 AM, Walter Bright
 <newshound1 digitalmars.com> wrote:
 Jarrett Billingsley wrote:
 On Thu, Nov 6, 2008 at 5:07 PM, Walter Bright
 <newshound1 digitalmars.com> wrote:
 BCS wrote:
 Reply to Walter,

 Steven Schveighoffer wrote:

 Even experienced developers fall into some of these traps.  I 
 know I
 occasionally fell into this trap:

 if(x);
 x->doSomething();
 But no more with D, because it's not allowed.  Those kinds of 
 things
 can be easily prevented, and are common mistakes by all 
 programmers.
Here's another fun one: printf("%d\n", 8l); What does that print?
8
If I hadn't said it was a trap, I bet you'd have said "81".
I wouldn't've, because I use a font that actually distinguishes things 1, I, l, and | properly. <_<
0 and O is another fun one. In any case, 8l is legal C, but illegal D.
Threre are various good programmer fonts out there today that are designed to make the 1 l | and 0 O distinctions clear. I use the Proggy fonts. http://www.proggyfonts.com/index.php?menu=download These days I'd say if you're not using one of these fonts for programming you're being an extremely silly person. --bb
I use and recommend the DejaVu Sans Mono font. With this font there is no chance of confusing those troublesome characters, and it's very easy on the eyes. Also, the DejaVu fonts are available in the repositories of many (most?) Linux distributions. http://dejavu.sourceforge.net/ -Lars
I was surprised to learn I already have several versions of Deja Vu installed (on Windows). I've configured all of my text editors and even Thunderbird to use it now. What a difference! Thanks for pointing it out.
Nov 07 2008
prev sibling parent Walter Bright <newshound1 digitalmars.com> writes:
Bill Baxter wrote:
 These days I'd say if you're not using one of these fonts for
 programming you're being an extremely silly person.
That's great, but one doesn't always have control over the fonts.
Nov 07 2008
prev sibling next sibling parent reply "Jarrett Billingsley" <jarrett.billingsley gmail.com> writes:
On Thu, Nov 6, 2008 at 7:02 PM, Bill Baxter <wbaxter gmail.com> wrote:
 Threre are various good programmer fonts out there today that are
 designed to make the 1 l | and 0 O distinctions clear.
 I use the Proggy fonts.  http://www.proggyfonts.com/index.php?menu=download

 These days I'd say if you're not using one of these fonts for
 programming you're being an extremely silly person.
ProggyCleanSZ, thankyouverymuch. Code doesn't look like code unless it's in that font ;)
Nov 06 2008
parent bearophile <bearophileHUGS lycos.com> writes:
Jarrett Billingsley:
 ProggyCleanSZ, thankyouverymuch.  Code doesn't look like code unless
 it's in that font ;)
I use this (it's free) and I'm very happy of it, but note it requires a bigger size than Proggy, so if you want to program with a little font this isn't good: http://www.levien.com/type/myfonts/inconsolata.html Bye, bearophile
Nov 06 2008
prev sibling parent Don <nospam nospam.com> writes:
Walter Bright wrote:
 Jarrett Billingsley wrote:
 On Thu, Nov 6, 2008 at 5:07 PM, Walter Bright
 <newshound1 digitalmars.com> wrote:
 BCS wrote:
 Reply to Walter,

 Steven Schveighoffer wrote:

 Even experienced developers fall into some of these traps.  I know I
 occasionally fell into this trap:

 if(x);
 x->doSomething();
 But no more with D, because it's not allowed.  Those kinds of things
 can be easily prevented, and are common mistakes by all programmers.
Here's another fun one: printf("%d\n", 8l); What does that print?
8
If I hadn't said it was a trap, I bet you'd have said "81".
I wouldn't've, because I use a font that actually distinguishes things 1, I, l, and | properly. <_<
0 and O is another fun one. In any case, 8l is legal C, but illegal D.
In CompSci1 we had use some ridiculous Mac editor where 0 and O were 100% identical, I,l, | and 1 also. It was an incredible source of bugs. We had to write a parser/emulator for some stupid imaginary asm language they'd invented, where O01 was output register 1. Plus, whitespace was significant, but it wasn't a monospaced font... It was like the whitespace programming language.
Nov 07 2008
prev sibling parent reply Derek Parnell <derek psych.ward> writes:
On Thu, 6 Nov 2008 17:14:13 -0500, Jarrett Billingsley wrote:

 On Thu, Nov 6, 2008 at 5:07 PM, Walter Bright
 <newshound1 digitalmars.com> wrote:
 BCS wrote:
 Reply to Walter,

 Steven Schveighoffer wrote:

 Even experienced developers fall into some of these traps.  I know I
 occasionally fell into this trap:

 if(x);
 x->doSomething();
 But no more with D, because it's not allowed.  Those kinds of things
 can be easily prevented, and are common mistakes by all programmers.
Here's another fun one: printf("%d\n", 8l); What does that print?
8
If I hadn't said it was a trap, I bet you'd have said "81".
I wouldn't've, because I use a font that actually distinguishes things 1, I, l, and | properly. <_<
Same here. I thought the 'trap' was using %d with a *long* value. -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
Nov 07 2008
parent "Nick Sabalausky" <a a.a> writes:
"Derek Parnell" <derek psych.ward> wrote in message 
news:16rwvaqsxxzdx.hzsh3le743yv$.dlg 40tude.net...
 On Thu, 6 Nov 2008 17:14:13 -0500, Jarrett Billingsley wrote:

 On Thu, Nov 6, 2008 at 5:07 PM, Walter Bright
 <newshound1 digitalmars.com> wrote:
 BCS wrote:
 Reply to Walter,

 Steven Schveighoffer wrote:

 Even experienced developers fall into some of these traps.  I know I
 occasionally fell into this trap:

 if(x);
 x->doSomething();
 But no more with D, because it's not allowed.  Those kinds of things
 can be easily prevented, and are common mistakes by all programmers.
Here's another fun one: printf("%d\n", 8l); What does that print?
8
If I hadn't said it was a trap, I bet you'd have said "81".
I wouldn't've, because I use a font that actually distinguishes things 1, I, l, and | properly. <_<
Same here. I thought the 'trap' was using %d with a *long* value.
In my newsgroup client, the lower-case 'L' renders as a straight vertical line with no serif or anything else. I can't remember ever seeing a (non-oddball) font where the "one" digit looked like that, so I instinctively saw it as "8L" and thought the intended gotcha was a mismatched number of bits causing a zero on a system of the wrong endianness. That said, I do still like D's requirement that the "L" suffix be capitalized.
Nov 07 2008
prev sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Thu, 06 Nov 2008 23:34:55 +0300, Walter Bright  
<newshound1 digitalmars.com> wrote:

 Steven Schveighoffer wrote:
 Even experienced developers fall into some of these traps.  I know I  
 occasionally fell into this trap:
  if(x);
   x->doSomething();
  But no more with D, because it's not allowed.  Those kinds of things  
 can be easily prevented, and are common mistakes by all programmers.
Here's another fun one: printf("%d\n", 8l); What does that print?
Yay, it is hardly distiguishable even at 500% zoom (Courier New)!
Nov 06 2008
prev sibling parent bearophile <bearophileHUGS lycos.com> writes:
Steven Schveighoffer:
 Even experienced developers fall into some of these traps.  I know I 
 occasionally fell into this trap:
 if(x);
   x->doSomething();
 But no more with D, because it's not allowed.  Those kinds of things can be 
 easily prevented, and are common mistakes by all programmers.
In Delight it's also quite difficult to fall in that trap: if x: x->doSomething() Many variants of that syntax are all disallowed: if x x->doSomething() if x: x->doSomething() if x x->doSomething() etc. So instead of making the language more confusing, it actually has the opposite effect. Bye, bearophile
Nov 06 2008
prev sibling parent bearophile <bearophileHUGS lycos.com> writes:
ore-sama:
 These are pitfalls for novice programmers. Why bother?<
I want D to be a little more novice-friendly than C++. After 8 hours of coding, when I'm tired, I'm a novice myself, and I can appreciate any help the compiler can offer. Bye, bearophile
Nov 06 2008
prev sibling parent reply ore-sama <spam here.lot> writes:
bearophile Wrote:

 After 8 hours of coding, when I'm tired, I'm a novice myself, and I can
appreciate any help the compiler can offer.
 
Can tired programmer think about business process? It tends to be more complex than syntax and usually if tired programmer writes compilable code, this code is wrong (not because of syntax errors, but because of logical errors in business process).
Nov 07 2008
parent reply bearophile <bearophileHUGS lycos.com> writes:
ore-sama:
 Can tired programmer think about business process?
I can answer you that I use the first hours to think more and the later hours to program more. But what I've just said can't help you see why it's so important for the compiler to help avoid as many bugs as possible. I can't explain such essential concept in few lines here, so I suggest you to keep programming and reading, eventually you will probably get it. Later, bearophile
Nov 07 2008
parent reply ore-sama <spam here.lot> writes:
bearophile Wrote:

 But what I've just said can't help you see why it's so important for the
compiler to help avoid as many bugs as possible. I can't explain such essential
concept in few lines here, so I suggest you to keep programming and reading,
eventually you will probably get it.
 
it's clearly understandable that we don't need bugs. My point is to not let compiler prevent programmer from writing expressive code. If you force programmer to write a lot of text to make compiler happy, this in turn can cause bugs.
Nov 07 2008
next sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
ore-sama escribió:
 bearophile Wrote:
 
 But what I've just said can't help you see why it's so important for the
compiler to help avoid as many bugs as possible. I can't explain such essential
concept in few lines here, so I suggest you to keep programming and reading,
eventually you will probably get it.
it's clearly understandable that we don't need bugs. My point is to not let compiler prevent programmer from writing expressive code. If you force programmer to write a lot of text to make compiler happy, this in turn can cause bugs.
if(x); doSomething Cool, you can express this: test something, and do nothing if true. Do you really need that expressiveness? Another one: the Eclipse Java compiler would tell if you might get a NullPointerException since at the beginning of a method you assign some variable to null, then you might change it to something non-null in some path, but you might not realize that you didn't make sure to set it to something non-null in all paths. So there goes Eclipse and tells you: in this specific line, that variable might be null. Do you want to be able to express "I probably have a bug here"?
Nov 07 2008
parent reply Walter Bright <newshound1 digitalmars.com> writes:
Ary Borenszweig wrote:
 Do you want to be able to express "I probably have a bug here"?
Even if the code is correct, if it looks like a bug, it will cause problems by repeatedly being flagged by others doing a code review.
Nov 07 2008
parent Derek Parnell <derek psych.ward> writes:
On Fri, 07 Nov 2008 07:34:26 -0800, Walter Bright wrote:

 Ary Borenszweig wrote:
 Do you want to be able to express "I probably have a bug here"?
Even if the code is correct, if it looks like a bug, it will cause problems by repeatedly being flagged by others doing a code review.
Yes, that is one more item in the "cost of maintenance". My mantra for many, many years now has been that programming languages exist to serve people rather than serve computers, and their greatest service is to reduce the cost of maintenance. Initial coding is a once-off price and after that the (long) time following we must pay the piper (like the 2nd law of thermodynamics insomuch as everything decays over time unless energy is added to stop it decaying) There are many things in the D programming langauge that helps us reduce maintenance costs, but more can still be done. -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
Nov 07 2008
prev sibling parent reply Janderson <ask me.com> writes:
ore-sama wrote:
 bearophile Wrote:

 But what I've just said can't help you see why it's so important for 
the compiler to help avoid as many bugs as possible. I can't explain such essential concept in few lines here, so I suggest you to keep programming and reading, eventually you will probably get it.

 it's clearly understandable that we don't need bugs. My point is to 
not let compiler prevent programmer from writing expressive code. If you force programmer to write a lot of text to make compiler happy, this in turn can cause bugs. Writing extra code to tell the compiler what you really mean is not necessarily a bad thing. Think about where you actually spend most of your time. If you are working on a small project, maybe you spend more of your time typing out the code. I think this is why scripting languages are loved for getting some done fast but grow unwieldy as the program gets larger. For me I can code something up pretty fast once I know what I want. How it interacts with the rest of the system is the difficult part. Particularly as a game programmer (I imagine its the same for other factions). I spend most of my time debugging and integrating with other peoples code. It's more difficult to spot a bug that someone else wrote. Lets take game AI for instance. The team can do their best to plan out a good AI for a character however when you hit the run button the AI appears to take on a life of its own. Why does the character decide to pick this target over this other target? Why does the character go left instead of right in this particular situation? Why does it only happen in release? I don't want spend hours tracking down the issue only to find its (for example) - an un-initialized variable or - a change introduced by Joe which changed how a particular class was designed to work. Note: unit tests are great here to enforce things continue to work the same way. Just a general question to everyone. Do you sometimes take conscious notes of what you spend your time doing? Then try to figure out ways to improve on it? I have found that there's things I didn't expect that I was spending time on. Even simple things like: - adding commonly used code fragments to visuals assists intellisense - using programs like distCC or incredibuild if your build is slow - not reinventing the wheel - Cheats and macros to improve debugging time. - Always fixing a bug and making sure it can't be repeated without at least a highly visible warning. - Making classes invariant so they can't be used in a wrong way ... go a long way to improving productivity. -Joel
Nov 09 2008
next sibling parent reply ore-sama <spam here.lot> writes:
Janderson Wrote:

 I spend most of my time debugging and integrating with other 
 peoples code.  It's more difficult to spot a bug that someone else wrote.
Millions of lines by novice programmers? I heard. Nothing will save you. :3
 however when you hit the run button the AI 
 appears to take on a life of its own.
Souldn't it do so?
Nov 09 2008
parent reply Janderson <ask me.com> writes:
ore-sama wrote:
 Janderson Wrote:
 
 I spend most of my time debugging and integrating with other 
 peoples code.  It's more difficult to spot a bug that someone else wrote.
Millions of lines by novice programmers? I heard. Nothing will save you. :3
:) Everyone who is better then me is an expert everyone who is below me is a novice. One day everyone but me will be a novice :)
 
 however when you hit the run button the AI 
 appears to take on a life of its own.
Souldn't it do so?
:) The point was that AI can be very complex when you add all the bits and pieces together. In a game you want the AI to look intelligent but also make the game fun. Sometimes these to ideals don't meet. -Joel
Nov 09 2008
parent "Chris R. Miller" <lordsauronthegreat gmail.com> writes:
Janderson wrote:
 ore-sama wrote:
 Janderson Wrote:

 I spend most of my time debugging and integrating with other peoples
 code.  It's more difficult to spot a bug that someone else wrote.
Millions of lines by novice programmers? I heard. Nothing will save you. :3
:) Everyone who is better then me is an expert everyone who is below me is a novice. One day everyone but me will be a novice :)
 however when you hit the run button the AI appears to take on a life
 of its own.
Souldn't it do so?
:) The point was that AI can be very complex when you add all the bits and pieces together. In a game you want the AI to look intelligent but also make the game fun. Sometimes these to ideals don't meet.
I smell a disappointed GR:AW player.
Nov 09 2008
prev sibling parent Walter Bright <newshound1 digitalmars.com> writes:
Janderson wrote:
 however when you hit the run button the AI appears to take on a life of its
own.
Please tell me you don't work for Cyberdyne Systems!
Nov 09 2008