Now all we need is to condense the output of the steam engine into water and give it to a horse who will help pull the car. That way you'll surely be 100% efficient!
> To say "we can create such big ideas" makes it sound like the universe > is something that wasn't around until we thought of it as some great idea.
The universe was around, but the big ideas are ours and ours alone, and did not exist before we thought of them (despite what the Platonists say). I never claimed to have created the universe, and neither would I ever think of myself as insignificant just because I don't know how to create one yet.
> I think the parent poster's point is that we still have no real > inkling about the true nature of these "big ideas."
People who think of those "big ideas" certainly have a pretty good inkling about their true nature. Just because you can't understand them, you shouldn't assume that nobody can. Such defeatist thinking is what stops scientific progress dead cold. Never EVER say that we can't know something until you at least try. And if you try and fail, you shouldn't assume that everyone in the world is going to be equally unsuccessful until you have objective, uncontrovertible, and absolutely clear proof to the contrary.
> Similarly, your pride at being able to "travel so far" is seen as a source of > frustration to someone who feels that we've barely left the realm of our home > planet when there is an infinite area yet to explore.
Again, just because we haven't traveled to the stars yet, doesn't mean we can't. I can't travel to the bottom of the ocean either, but it's not because it's impossible. I just don't have enough money to build an appropriate ship. It is very important to distinguish between "I can't" and "I can, but don't have the means". It's the same as with knowledge, you can never achieve anything if you give up before really trying. And if you don't have the means to try, that's no cause for despair either. Sure I don't own a starship, but that doesn't make me insignificant. Similarly, not owning a yacht doesn't make me any more personally insignificant than the rich man who does.
> The only thing most Slashdotters are sitting astride is an office chair
Man, you really have no imagination. Your life must be pretty dull. You need to read more science fiction!
> That's 52 times the distance between the sun and the earth - makes me feel very very small...
I could never understand such abjectly pitiful thinking. Why would anyone feel small while looking at big things? I always feel big and powerful for being able to imagine big things like the solar system. It truly makes one appreciate being human, when we can create such big ideas, travel so far, and sit astride a light year looking down at it like a plaything.
To my programmer's mind the problem seems to be in the game rather than in the politics. If people don't want to wade through hundreds of boring hours of leveling up before they are allowed to do anything interesting, the logical solution is to fix the game so that they wouldn't have to. When will MMOG writers figure out that nobody wants to kill rats for a living?
So they say Apple has to respect their intellectual property. It is curious, since in most business contracts, when one party pays up, the other gets something valuable in return. What does Apple get from paying? They have thought up the interface themseleves, and Creative's only claim on it is that they have thought of it first. If Apple has never seen Creative's patent, what exactly would they be paying for? Creative did no work for them and gave them nothing of value and yet Apple has to pay up anyway? Usually this is called "extortion". In the modern times we call it the "patent system".
> So basically you take issue to features and paradigms Ruby people espouse? > IE: that it is ok to take several well defined interfaces and then mix them > creating an interface that is defined nowhere to acheive whatever capability you need.
I don't think you are doing what you think you are doing. I just looked at some Ruby tutorials, and to my untrained eye those mixins are nothing more than multiple inheritance. I wasn't able to figure out what the difference was, but you definitely have to define a class to mixin (Ruby calls them Modules, but I see no reason to differentiate them from classes. It must be a terminology thing. In C++ these things would be classes), and the syntax for mixing is the same as specifying a base class in C++. The tutorial mentions that there are "problems" with multiple inheritance that this supposedly avoids, but fails to mention any of them.
The capability to "extend" the class is basically the same thing as defining a derivative class and creating it with a copy constructor. Ruby seems to be simply replacing the vtable for the class with that of the new class with the extensions. I shudder to think that an object I gave some function can suddenly become a totally different object, as if I gave it a lamb and got back a wolf. I don't know how you can stand debugging such astounding transformations. If you can, you must be one hell of a wizard; I would never allow such unclean things in my code.
Since this discussion is suddenly all about Ruby, I guess I should look at it a bit closer. I've looked at http://www.rubycentral.com/book/index.html for examples and explanations. Feel free to suggest others if you disagree with my conclusions.
The language doesn't seem all that different from C++ in substance. All the OO capabilities are there, and aside from the quaint notation the code looks pretty much like it would when translated to C++. It is as if the designer really hated C++ and decided to do everything as differently as possible. That must be the justification, since I found no features that I would classify as improvements over C++.
There is even the ironic requirement of using C to extend the language, which is truly a laughable point considering the C++ can be extended using C++ just fine.
When I look at those examples, the words that come to mind are "sloppy", "wobbly", "tacky", and a few other unprintable adjectives. To a C++ person the lack of structure in the code is acutely painful. (From what you've said, that might be what you find so appealing) I'm not sure exactly what is creating that impression, the feeling of a pile of logs where one expects a building, but this problem alone is enough to instill a permanent deep aversion to the language in my mind.
> It is sort of funny you mention Martin Fowler: he really likes Ruby.
I don't base my opinions on the opinions of others. If Kernigan and Ritchie themselves proclaimed C to be evil and Ruby to be the pinnacle of quality, I would simply shrug, mutter something about how misguided they are, sigh and go back to coding. In C++, of course.
> It is possible to pretty easily determine whena nd where things are being > mixed so you can determine: in code where the interfaces are being mixed. > And at run time you can determine what interfaces are being mixed.
Maybe your programs just aren't that big. uSTL is ~12kl and it is downright tiny. My C++ projects routinely exceed 50kl in size and I've worked with ones as large as several million lines. There is more than enough complexity in them to worry about without intentionally introducing interface inconsistencies like the ones you're describing.
> If I want to iterate over all of the attack capabilities my creature has I > do have access to all of the modules (IE: capabilities) that have been > mixed in. I can then determine which of those are attacks and do whatever I want.
> Should I really have to design an interface for the creature that > specifically states the creature can possibly have this > capability? Why not just attach it to him at runtime?
But you are designing an interface when you do this. When you "attach" a capability, you are merging that capability's interface with the interface of the creature. You would do exactly the same thing in C++ as your Ruby "mixin", like this:
class CLaserBeamShooter { public:
void ShootBeam (Point2d target); };
class CSuperDuperCreature : public CCreature, CLaserBeamShooter { };
CSuperDuperCreature c; c.ShootBeam (pt);
This is not a very good idea though. When you talk about capabilities that can be gained or lost at runtime, you are confusing "is-a" relationship denoted by inheritance with a "has-a" relationship implemented with member objects. A better way of defining a creature with different capability types would be:
This way you get the important ability to enumerate all possible attacks this creature can currently do. This list could be used to create the "Attack" menu in your game UI or to allow random attack selection by the creature AI. I bet you can't think of a way to do that with your design!;)
You may want to read Martin Fowler's book called "Refactoring". It offers many examples of class design methods like this.
> The creature can just have a little code that checks for a capability and uses it.
This should be the first warning sign that something is wrong with the design. Objects don't check for capabilities. They either have them or they don't. If you need to check for it, it shouldn't be a part of the interface; it should be a plugin. That way the object can treat all of them identically and after writing that generic code you will never have to touch it again no matter how many new plugins (capabilities) you may have in the future.
> What if somewhere deep in your program and just on occasion you > really want an instance of an object (just one instance) to have different capabilities?
Then you need another class to specify the interface for that object. It doesn't matter if you only have one instance of it. If instance A of class C does something different from all the other instances of C, then A is not an instance of C. A derived class of C can have additional capabilities and be instatiated as A. Really now, typing up a derived class with one extra method is no more difficult than whatever it is you have to do to modify A in your dynamic language.
This is more of a philosophical issue. Your "special" instance is no longer the same as all the other instances. It is a different "kind" of object, which in OO programming necessarily means that it is an instance of a different class.
> He has *NO* interface that tell him anything about laser beams > OR attacking. Yet the laser can still be attached to him and he > can still have that capability to attack with no specification > of it. Why is that SO terrible?
Because you are violating the programmer's expectations for working with objects of that class. When an object's behavior does not conform to expectations
> It complains when I do things to the Object that it doesn't think I should be doing.
I'm still not quite clear what you are doing here. You have made thingee a reference to a FooBar object; then you call some member function on thingee that FooBar doesn't have. What will happen then? Will you get a runtime error or what?
In C++ the analogy would be:
auto_ptr<Shape> thingy = new Circle; thingy->Draw(); thingy = new Rectangle; thingy->Draw();
Using the textbook Shape example, I can point thingy to things that have a particular interface, defined by the Shape class. It makes perfect sense to point thingy to a Circle object or a Rectangle object, but it certainly makes no sense to point it to a MyBankAccount object, and the compiler will helpfully point this out to me. In a dynamically typed language you would not get an error until you ran the program and got to the point of invoking some Shape method, which MyBankAccount doesn't have. In most cases this will work exactly like that, but what if MyBankAccount has a Draw method that withDraws all your money? Your dynamic language will say "Hmm, this looks like a duck right here. Let's see if it walks like one." calling the Draw method anyway without any error. The Draw method drains your bank account as it is supposed to and the computer things everything is just fine. Then, eventually, a few months after you have released the product, some irate user starts calling in death threats.
> I insist that my language let me do just absolutely CRAZY stuff like invoke ANY method on an object.
Exactly! And, in following up the above example, how can you be sure that a method that looks like a duck walks like a duck? With static typing I explicitly define what interfaces an object supports, and I explicitly specify what interface I intend to use by declaring the pointer I intend to call members through. I do that because I know what interfaces I have implemented on my objects. I know I can call rect->Draw() because I know that Draw() exists and that it will draw the rectangle. When I call some other object's sdfrtu->Draw(), how do I know what sdfrtu does in there?
> Sure we start off with a pretty good spec on most projects, but clients > and their ideas will always differ from what is written on the spec doc.
Yes, but just because you can call a different method on an object, doesn't mean that method would suddenly spring into existence. If you were calling thingy->Draw() and the client suddenly decides you should be doing thingy->ResizeAndDraw() instead, you can't just change the call and expect everything to work! You'll still have to go and implement ResizeAndDraw() on all your shapes before anything happens. That's if you remember, that is. A dynamic language will let you implement Circle::ResizeAndDraw and stop there. After all, the client only wants to do it to circles for now. A static language would force you to recognize that you have just altered an interface and that thingy->ResizeAndDraw() might not be always valid any more.
And instead of waiting until the user hits some weird special case when thingy is a Rectangle, the compiler can tell me now that here's a potential problem, so I can properly alter Shape to contain ResizeAndDraw. If I decide that there is no obvious default action (like calling Resize() followed by Draw()), I can make the call pure virtual, which will help me ensure that all derived classes have it implemented too.
A dynamic language might let you get away with postponing this work, but you will have to do it eventually. Worse, some green-behind-the-ears intern will be eventually asked to debug some inexplicable problem the user is having. Will he know how to fix it properly? And how long will he curse you for not having done it properly in the first place? And how much will your relationship with that client suffer as a result of this totally preventable bug?
To me, the truly astounding thing is that there actually are people in the world who click on these ads. It is absolutely mind-boggling that anyone would voluntarily call a telemarketer!
> I don't need to put a big huge sign on my identifier saying "LOOK AT ME, I AM A STRING!".
That is an argument against full Hungarian notation, not against static typing:)
Let me try rephrasing the question one more time: how can you manage to not think about the type of the identifier? When I think of variables, I think primarily of the type rather than the name. For example, here's a class I designed a couple of hours ago (just the data fields, for clarity):
My thoughts went something like this: "ok, I need an int for the classid, another int for the parentid, a string for the name, a string naming the library it's in, and a list of interfaces it exposes." When I think "m_Id", I automatically think "integer", and I would be curious to discover how you would think of it in some "typeless" way. You see, what it is makes a big difference: if it is an integer, searching is quite inexpensive and I won't worry about doing it often (this is in a compiler-type application, which spends about 40% of its time looking stuff up). If it were a string or a GUID, I'd be more concerned with performance and might add a separate index or a hash table to avoid doing hundreds of string comparisons during a search, I would also have second thoughts about using it as a key for parent class lookup, probably switching to using something else for that purpose. Similarly, I'm choosing to store strings in the object rather than in a separate stringtable to make the lookup code cleaner. This decision implies that I would want to try implementing the db reader such that it will load records on demand (with readahead through a sliding buffer, allowing me to reuse already existing async loading code) instead of reading it all in at once as I would have had to do with a stringtable.
Then I'd type them in in the order I thought of them and give a quick visual check for alignment. string and vector are both pointer-grain, and so is the vtable ptr. The classids are 4 bytes (fixed-size type because it will be directly written to a binary file), and so should be grouped together to avoid padding on 64bit platforms. I happened to think of them together already, so no reordering was necessary. No problems visible in memory, so I might stop here. Later, when writing serialization routines I realize that the interfaces vector (which is a list of 4 byte ids) should precede the string for optimal packing (vector may end on 4-grain, while I may later want to align to 8-grain if I later decide to write some 8byte int, so starting a 1-grain string in there would save space), so I quickly jump to the header and switch them (reading memory sequentially gives the best cache utilization because the read cache will prefetch stuff that way, and declaring them in order will generally cause the memory block allocated by the containers to be contiguous)
The above thought process obviously takes a lot less time than the explanation. I can usually complete all of the above considerations well before I finish typing the class in. It's not because I'm an assembly wizard. It's because I always think of these things whenever I create a new class, and have been doing it for many many years. Practice and habit make them automatic and I hardly notice I'm doing it.
> So instead of ALWAYS having to specify a type I just check the type when it matters.
How do you avoid stupid errors where you mistype the variable name and end up passing to a function something completely different from what you intended? In C++, the compiler will stop and say, "Whoa! That function works with integers, are you sure you want to give it a Window object?
His example in C++ is not all that larger than the lisp version, and mostly concerns syntactic necessities rather than real code. I would omit the copy constructor (because the compiler can write one by itself) and put the inlines on one line, indented to a common point, to make the real code stand out.
Also, as you pointed out, it is a functional programming example. That is another big difference between us: I really hate functional programming. Lisp to me is the language of gray-haired academics who have never seen the real world. (This view is corroborated by the fact that there really are no useful Lisp programs in the world. Pretty much all the open source code you'll see on SourceForge or elsewhere on the net is either in C, C++, or Java.) It's not so much the language syntax, but the way of thinking of processes as functional trasformations instead of instruction sequences. Since the latter is what the CPU really does, the former seems totally absurd to me. At one time I was trying out STL predicate algorithms for a while, and while they work fine for containers of integers, they fail horribly for any complex processing involving object containers. They also frequently fail to expand to the loops they represent, creating bloat and inefficiencies. So I finally rewrote everything with iterative syntax. The clarity of the code improved dramatically and so did code size and performance. Needless to say I don't use them any more.
I see the same problem as a plague to mathematics in general. The insistence on describing every system as a function increases complexity beyond all reason. It is this insistence that makes the Shrodinger equation totally useless in describing molecular interactions. If physicists started thinking iteratively and locally instead of creating giant global system equations they would no doubt come up with their GUT much faster and avoid ridiculous things like quantum mechanics.
> I would also recommend: For a Java/C++vs. Lisp comparison.
I'd have to see the C++ code to critique. A cursory look over the Lisp version suggest that a nearly direct translation to C++ would be possible.
> And for another programmers take on it where he tries the same thing: C++ hackers take
Invalid link.
> Also see another PG article: Succinctness is Power
Not necessarily. Just because you have to type less, doesn't mean the code is easier to write. Writing APL code can be pretty damn hard, and it is the most succinct language in existence;) Readability is also a pretty big factor, as APL demonstrates with flair. To a procedural programmer like me, C++ is far more readable than Lisp and always will be.
> So in my IO bound world I use the most productive and powerful languages I > can convince my team to use without secretly wanting to murder me.
Convincing your team to switch languages is an entirely different issue from which language you yourself want to use. When on a team, you use the language the team is familiar with. It is counterproductive to use a team of Java programmers to write a C++ application. If you want to do that, you hire a team of C++ programmers. In general you would choose the language before choosing the team.
> That said is there REALLY a reason for every programmer to understand pointers?
Is there a reason for every programmer to understand that memory can be addressed? That's what pointers are all about. An address in memory. You understand pointers when you understand how your data is stored in memory, and I would argue that there are few things more important for a programmer to know.
> Do you really have to know assembly on up? Is that important for every programmer to know?
Yes. So he would know how much things cost. These days programmers raised on Java are becoming totally ignorant about the cost of what they do. It is because of them that we have obese obscenities like OpenOffice, which tak
> What does not change is that you still have to know and use pointers > and all of the syntax required to deal with them in C++. After a time > it becomes second nature. And with a little experience in a debugger > you can quickly track down most pointer related mischief.
The people who complain about pointers are the same ones who don't know how to properly do memory management. I haven't had any "pointer related mischief" in years. Just as thinking about object ownership helps you avoid allocation problems, it will also rid you of all "pointer problems". I think that people are afraid of pointers only because they heard all those horror stories from bad C programmers.
> However, you will still be writing more code in C++ or Java than > you will in a more expressive and concise language.
You better support that with an example!:) Remember that in C++ you also need to get the appropriate library for your task. If you write everything from scratch, then of course you'll end up doing more work. In your intepreted language you probably have everything already bundled in and have no choice in what constructs you use, whether they are good or bad. The bundled functionality makes that language because it is not possible to natively reimplement them. In C++ it is always possible and is frequently done in order to create better APIs. In Java, you're pretty much stuck with what you have forever and ever.
> I wrote code in C long enough to know that even if you are one of the > best C or C++ programmers in the world you are still at a disadvantage > when compared to a great programmer that knows their way around a > language like Lisp or Ruby.
Now, don't go lumping C with C++ here! They are worlds apart. While what you say is almost certainly true for C, it is blatantly false for C++. Once you have objects, the syntax of their creation is of limited importance.
> The argument is that statically typed languages like C, C++, Java, and C# take more lines of code
That argument I could never understand. When would you ever be in a situation that you wouldn't know the type of your variables? And how, may I ask, will the maintainers of your code know what's in them if you don't tell them what's in them? Sounds like a recipe for obfuscated code to me.
Of course, I'm not talking about object polymorphism here, which works just fine in C++, thank you.
> The truth of the matter is that most classes of programs can be written in more powerful languages.
I would agree entirely. There is, after all, no more powerful language than C++!;) [better start defining your terms and giving examples, or how else can I refute your vacuous arguments?]
> So is your defense of C++ a personal bias or do you really think that C++ is more productive.
Both. Naturally I'm biased, since I know it so well, but I have also never seen any examples to the contrary. I am also immediately prejudiced against all those "great" new languages; they all claim to be such an improvement over C++, but such claims usually come from not understanding C++. Before you create a fancy new language, you better define clearly what the problem is with the one we already have. Garbage collection is a fine example of a solution to the wrong problem; instead of educating the programmer, change the language, solving one problem while creating a host of others. If you don't understand C++, you are only liable to reinvent it. Badly.
Do you love a challenge? Do you like speedrunning? Are you totally bored by your Sims game? Try the speed sims method! Put eight people in one house and build just one bathroom. Then set the game speed to two, turn on free will, and try to get them all to work in a decent state. I guarantee you'll be sweating in no time at all.
> The biggest problem I have is that C++ is just not > required for many types of programs.
That's a problem indeed; a problem with your thinking, that is. You are thinking that C++ is some heavyweight monster that is only suitable for big problems, while nothing could be farther from the truth. C++ is the lightest language you can use, with the smallest possible footprint. You could go smaller only with C or assembly, neither of which is suitable for anything larger than a small utility program.
When I think of the enormous VMs required for interpreted languages like Java, I certainly might say that such bloat is "not required" for some small application, and rewrite it in C++. It is guaranteed to be smaller, and quite possibly faster (an I/O-bound program will be slow in any language).
> Even being one of the best few C++ coders you would be more > efficient if you were as proficient in some more dynamic language.
I disagree. Anything your dynamic language provides is just as easily doable in C++. The difference is that interpreted languages usually have everything and the kitchen sink built in, while with C++ you have to select an appropriate library for your task. With the right library, C++ will do just as well or better than any all-powerful-language.
I know you'll be mentioning garbage collection next, so I'll explain why I don't need it. While I have no real problem with its concept, I do have a problem with the unfortunate mentality it promotes. GC programmers don't think about ownership and allocate memory too often. In my code, for example, you won't find any memory allocation. At all. You could grep for 'new' or 'delete' all day long and never find one. That's because a good C++ programmer will make use of STL containers for heap management. Those are for permanent storage of various kinds. For short-life objects we use our own GC, called the stack. For heap memory objects, it is extremely important to think about who owns them and how long they will live. In Java the mentality is to just pass around pointers wherever they are needed, reference counting them or whatever, without any thought for such things. That's why there are so many leaky Java programs. In C++ you have to do it the right way -- define an owning object for every allocated block and describe exactly how and when it is allocated and freed. Because it is the right way, I would undoubtedly do it the same way in any language, GCd or not.
> I think Java is a mess. Ditto for C++. To much baggage in both
Just because C++ has baggage, doesn't mean you need to use it. Yes, it is quite possible to use C++ in the same way as C. That's what most C programmers do when they switch. They continue to think in functions rather than in objects, refuse to learn about proper design, and complain endlessly how the compiler "does things behind their back". Lacking knowledge about class and template design, they generate slow and bloated code and blame their incompetence on the langauge. Then they go back to C, but, having gotten used to some C++ features, now starting to manually do all those things the C++ compiler used to do for them (like those hand-coded vtables in the kernel modules, for instance) and bragging about being real, macho, cycle-counting programmers.
> There are a LOT of languages out there other than C.
Heresy! There are NO languages out there other than C++:) Seriously, to a hardcore C++ programmer like myself there really are no other general purpose languages. I would use a specialized language for some tasks, of course; Javascript is essential for webpages, SQL is irreplaceable for queries, and shell scripts are very useful for administration work. However, for any serious project there is simply no substitute for C++, and every time I've tried to implement something in another language (notably Perl), I ended up recoding it in C++ as soon as any really complicated task came up. The best language is the one you know well, so it is much better to have perfect knowledge of C++ then to know a dozen languages poorly.
> And technically automatically interpreting a line without a brace as a > terminated statement (IE: with the semicolon) can be just as bad as > programmers that can't find a block of code.
I didn't say I always did that, only that it takes a few distracting seconds to switch to another interpretation style, just as it takes some time to switch between speaking human languages. I interpret a line without a brace as a terminated statement in my code because that is what I usually have. No, not ifs, of course, but I do have a few terminated for loops around. I can't remember using a free block recently, but there are occasional uses for them to manage object lifetime.
> The best argument I have seen is for condensing code. > It does save a line or two here and there if you really need it.
Saving lines is a good idea whether you need it or not. The more of the code the programmer can see on the screen, the faster he will see its control flow. If a function is so large to require scrolling, he'd have to go back and forth many times. This is particularly bad in C, where all the variables are declared in the beginning of the function. If I had to pick the worst style problem C encourages, this would be it. I hope that all compilers will eventually support declaring variables at the time of use, like gcc now does.
> With 1280x1024 being a relatively common display resolution used by > developers these days I don't think it is such a big deal to have > an extra line for the braces
You just wait a few years, son, and check your eyes again. I work on a 100x30 console (the real console, not an xterm), and that's about as small a font as I can comfortably read all day long. As you can imagine, this is one of the reasons the code I write is as concise as I can make it without losing clarity. In most cases clarity is gained rather than lost.
> No, you don't. In C and languages derived from it, the > compiler couldn't care less about indentation.
We format code for people, not for the compiler. If I were writing code just for the compiler, I could put everything in one line, delete all whitespace, and name all my variables x42. If you did that while writing code for your employer, you'd be fired immediately.
> whereas these two snippets will produce different results > even though the indentation is the same:
Every programmer's editor is perfectly capable of autoindenting the code for you. Even my ancient vi can do it. In such an editor it takes some effort to screw up indentation, and that effort would have made your mistakes obvious if you tried to type in your examples.
> Using indentation to look for code blocks is courting disaster
You look for blocks in order to separate the code into logical units, not to find bugs in it. Debugging and reading are rather different tasks in spite of being inseparably related.
Re:Question for all the coders out there..
on
How to Write Comments
·
· Score: 2, Insightful
> I am an old school coder > Why do people put the opening bracket on the same line as the conditional?
You must not be very "old school" if you don't know the answer. The cuddled braces are the original K&R indentation style; they are what C was supposed to look like.
Another answer is that there are two different ways to look for blocks. I look at indentation as a clue to the new block and when I see a brace on a line by itself I immediately interpret it as:
if (x); { }
This is especially true when I can't see the end of the line. Obviously, it doesn't take long to switch mental gears, but it is inconvenient. No, I am not going to switch to this style. You have to indent the code anyway and since the indentation change already says "new block", the brace is redundant, and therefore should not be emphasized. I might also point out that the braces are only required for multiline blocks anyway, so looking for indentations is a skill every C programmer needs, wherever he places the braces.
People who put braces on separate lines look for the opening brace itself to signal the start of the block and panic when they see indentation level change without it. It is really just another way of looking for blocks, and I am disappointed that it is so commonly taught.
But that's just the point. When you run as root, you don't have absolute control over your box; the apps that you run do. By using a non-admin account, you are not locking out yourself, you are locking out arrogant apps that think they can run your computer.
I actually got this one at a job interview and was unable to solve it. When told the answer I was very upset and explained why I would never use such a shoddy solution (and yes, I got the job:). You see, a lightbult is defined as a light-producing device; the specification says nothing about heat. If you rely on heat to make your solution work, you're asking for trouble in the long run. As lightbulb technology improves, there is absolutely no guarantee that lightbulbs will continue generating heat. In fact, it is almost a certainty that eventually they would generate only light and no heat at all, at which point your solution will break and you'll have to spend weeks hunting through your code to figure out why it isn't working. Add to that the fact that any programmer worth his salt wouldn't even think of undocumented features like this (especially because in his time all lightbulbs produce no heat), the chances of the bug being found go down significantly. The moral of the puzzle should be: "thou shalt not use undocumented features".
Don't they read the news? Last week Delphi declared bankrupcy specifically to get rid of union laborers. All those union workers will now be forced to take pay cuts down to $10. It's a sure bet that other companies will follow suit with similar measures, just as they are now dumping pension benefits in emulation of the airlines. The days of the unions are clearly numbered, and only a fool would join one now.
Now all we need is to condense the output of the steam engine into water and give it to a horse who will help pull the car. That way you'll surely be 100% efficient!
> To say "we can create such big ideas" makes it sound like the universe
> is something that wasn't around until we thought of it as some great idea.
The universe was around, but the big ideas are ours and ours alone, and did not exist before we thought of them (despite what the Platonists say). I never claimed to have created the universe, and neither would I ever think of myself as insignificant just because I don't know how to create one yet.
> I think the parent poster's point is that we still have no real
> inkling about the true nature of these "big ideas."
People who think of those "big ideas" certainly have a pretty good inkling about their true nature. Just because you can't understand them, you shouldn't assume that nobody can. Such defeatist thinking is what stops scientific progress dead cold. Never EVER say that we can't know something until you at least try. And if you try and fail, you shouldn't assume that everyone in the world is going to be equally unsuccessful until you have objective, uncontrovertible, and absolutely clear proof to the contrary.
> Similarly, your pride at being able to "travel so far" is seen as a source of
> frustration to someone who feels that we've barely left the realm of our home
> planet when there is an infinite area yet to explore.
Again, just because we haven't traveled to the stars yet, doesn't mean we can't. I can't travel to the bottom of the ocean either, but it's not because it's impossible. I just don't have enough money to build an appropriate ship. It is very important to distinguish between "I can't" and "I can, but don't have the means". It's the same as with knowledge, you can never achieve anything if you give up before really trying. And if you don't have the means to try, that's no cause for despair either. Sure I don't own a starship, but that doesn't make me insignificant. Similarly, not owning a yacht doesn't make me any more personally insignificant than the rich man who does.
> The only thing most Slashdotters are sitting astride is an office chair
Man, you really have no imagination. Your life must be pretty dull. You need to read more science fiction!
> That's 52 times the distance between the sun and the earth - makes me feel very very small...
I could never understand such abjectly pitiful thinking. Why would anyone feel small while looking at big things? I always feel big and powerful for being able to imagine big things like the solar system. It truly makes one appreciate being human, when we can create such big ideas, travel so far, and sit astride a light year looking down at it like a plaything.
To my programmer's mind the problem seems to be in the game rather than in the politics. If people don't want to wade through hundreds of boring hours of leveling up before they are allowed to do anything interesting, the logical solution is to fix the game so that they wouldn't have to. When will MMOG writers figure out that nobody wants to kill rats for a living?
So they say Apple has to respect their intellectual property. It is curious, since in most business contracts, when one party pays up, the other gets something valuable in return. What does Apple get from paying? They have thought up the interface themseleves, and Creative's only claim on it is that they have thought of it first. If Apple has never seen Creative's patent, what exactly would they be paying for? Creative did no work for them and gave them nothing of value and yet Apple has to pay up anyway? Usually this is called "extortion". In the modern times we call it the "patent system".
Hi, I'm a signature virus. Copy it into your sig to help me spread!
> So basically you take issue to features and paradigms Ruby people espouse?
> IE: that it is ok to take several well defined interfaces and then mix them
> creating an interface that is defined nowhere to acheive whatever capability you need.
I don't think you are doing what you think you are doing. I just looked at some Ruby tutorials, and to my untrained eye those mixins are nothing more than multiple inheritance. I wasn't able to figure out what the difference was, but you definitely have to define a class to mixin (Ruby calls them Modules, but I see no reason to differentiate them from classes. It must be a terminology thing. In C++ these things would be classes), and the syntax for mixing is the same as specifying a base class in C++. The tutorial mentions that there are "problems" with multiple inheritance that this supposedly avoids, but fails to mention any of them.
The capability to "extend" the class is basically the same thing as defining a derivative class and creating it with a copy constructor. Ruby seems to be simply replacing the vtable for the class with that of the new class with the extensions. I shudder to think that an object I gave some function can suddenly become a totally different object, as if I gave it a lamb and got back a wolf. I don't know how you can stand debugging such astounding transformations. If you can, you must be one hell of a wizard; I would never allow such unclean things in my code.
Since this discussion is suddenly all about Ruby, I guess I should look at it a bit closer. I've looked at http://www.rubycentral.com/book/index.html for examples and explanations. Feel free to suggest others if you disagree with my conclusions.
The language doesn't seem all that different from C++ in substance. All the OO capabilities are there, and aside from the quaint notation the code looks pretty much like it would when translated to C++. It is as if the designer really hated C++ and decided to do everything as differently as possible. That must be the justification, since I found no features that I would classify as improvements over C++.
There is even the ironic requirement of using C to extend the language, which is truly a laughable point considering the C++ can be extended using C++ just fine.
When I look at those examples, the words that come to mind are "sloppy", "wobbly", "tacky", and a few other unprintable adjectives. To a C++ person the lack of structure in the code is acutely painful. (From what you've said, that might be what you find so appealing) I'm not sure exactly what is creating that impression, the feeling of a pile of logs where one expects a building, but this problem alone is enough to instill a permanent deep aversion to the language in my mind.
> It is sort of funny you mention Martin Fowler: he really likes Ruby.
I don't base my opinions on the opinions of others. If Kernigan and Ritchie themselves proclaimed C to be evil and Ruby to be the pinnacle of quality, I would simply shrug, mutter something about how misguided they are, sigh and go back to coding. In C++, of course.
> It is possible to pretty easily determine whena nd where things are being
> mixed so you can determine: in code where the interfaces are being mixed.
> And at run time you can determine what interfaces are being mixed.
Maybe your programs just aren't that big. uSTL is ~12kl and it is downright tiny. My C++ projects routinely exceed 50kl in size and I've worked with ones as large as several million lines. There is more than enough complexity in them to worry about without intentionally introducing interface inconsistencies like the ones you're describing.
> If I want to iterate over all of the attack capabilities my creature has I
> do have access to all of the modules (IE: capabilities) that have been
> mixed in. I can then determine which of those are attacks and do whatever I want.
This is very non-object-
> specifically states the creature can possibly have this
> capability? Why not just attach it to him at runtime?
But you are designing an interface when you do this. When you "attach" a capability, you are merging that capability's interface with the interface of the creature. You would do exactly the same thing in C++ as your Ruby "mixin", like this:
This is not a very good idea though. When you talk about capabilities that can be gained or lost at runtime, you are confusing "is-a" relationship denoted by inheritance with a "has-a" relationship implemented with member objects. A better way of defining a creature with different capability types would be:
This way you get the important ability to enumerate all possible attacks this creature can currently do. This list could be used to create the "Attack" menu in your game UI or to allow random attack selection by the creature AI. I bet you can't think of a way to do that with your design! ;)
You may want to read Martin Fowler's book called "Refactoring". It offers many examples of class design methods like this.
> The creature can just have a little code that checks for a capability and uses it.
This should be the first warning sign that something is wrong with the design. Objects don't check for capabilities. They either have them or they don't. If you need to check for it, it shouldn't be a part of the interface; it should be a plugin. That way the object can treat all of them identically and after writing that generic code you will never have to touch it again no matter how many new plugins (capabilities) you may have in the future.
> What if somewhere deep in your program and just on occasion you
> really want an instance of an object (just one instance) to have different capabilities?
Then you need another class to specify the interface for that object. It doesn't matter if you only have one instance of it. If instance A of class C does something different from all the other instances of C, then A is not an instance of C. A derived class of C can have additional capabilities and be instatiated as A. Really now, typing up a derived class with one extra method is no more difficult than whatever it is you have to do to modify A in your dynamic language.
This is more of a philosophical issue. Your "special" instance is no longer the same as all the other instances. It is a different "kind" of object, which in OO programming necessarily means that it is an instance of a different class.
> He has *NO* interface that tell him anything about laser beams
> OR attacking. Yet the laser can still be attached to him and he
> can still have that capability to attack with no specification
> of it. Why is that SO terrible?
Because you are violating the programmer's expectations for working with objects of that class. When an object's behavior does not conform to expectations
I'm still not quite clear what you are doing here. You have made thingee a reference to a FooBar object; then you call some member function on thingee that FooBar doesn't have. What will happen then? Will you get a runtime error or what?
In C++ the analogy would be:
Using the textbook Shape example, I can point thingy to things that have a particular interface, defined by the Shape class. It makes perfect sense to point thingy to a Circle object or a Rectangle object, but it certainly makes no sense to point it to a MyBankAccount object, and the compiler will helpfully point this out to me. In a dynamically typed language you would not get an error until you ran the program and got to the point of invoking some Shape method, which MyBankAccount doesn't have. In most cases this will work exactly like that, but what if MyBankAccount has a Draw method that withDraws all your money? Your dynamic language will say "Hmm, this looks like a duck right here. Let's see if it walks like one." calling the Draw method anyway without any error. The Draw method drains your bank account as it is supposed to and the computer things everything is just fine. Then, eventually, a few months after you have released the product, some irate user starts calling in death threats.
> I insist that my language let me do just absolutely CRAZY stuff like invoke ANY method on an object.
Exactly! And, in following up the above example, how can you be sure that a method that looks like a duck walks like a duck? With static typing I explicitly define what interfaces an object supports, and I explicitly specify what interface I intend to use by declaring the pointer I intend to call members through. I do that because I know what interfaces I have implemented on my objects. I know I can call rect->Draw() because I know that Draw() exists and that it will draw the rectangle. When I call some other object's sdfrtu->Draw(), how do I know what sdfrtu does in there?
> Sure we start off with a pretty good spec on most projects, but clients
> and their ideas will always differ from what is written on the spec doc.
Yes, but just because you can call a different method on an object, doesn't mean that method would suddenly spring into existence. If you were calling thingy->Draw() and the client suddenly decides you should be doing thingy->ResizeAndDraw() instead, you can't just change the call and expect everything to work! You'll still have to go and implement ResizeAndDraw() on all your shapes before anything happens. That's if you remember, that is. A dynamic language will let you implement Circle::ResizeAndDraw and stop there. After all, the client only wants to do it to circles for now. A static language would force you to recognize that you have just altered an interface and that thingy->ResizeAndDraw() might not be always valid any more.
And instead of waiting until the user hits some weird special case when thingy is a Rectangle, the compiler can tell me now that here's a potential problem, so I can properly alter Shape to contain ResizeAndDraw. If I decide that there is no obvious default action (like calling Resize() followed by Draw()), I can make the call pure virtual, which will help me ensure that all derived classes have it implemented too.
A dynamic language might let you get away with postponing this work, but you will have to do it eventually. Worse, some green-behind-the-ears intern will be eventually asked to debug some inexplicable problem the user is having. Will he know how to fix it properly? And how long will he curse you for not having done it properly in the first place? And how much will your relationship with that client suffer as a result of this totally preventable bug?
> With type safety I d
According to the article what they developed is a virtual salesman, who is certainly artificial, though can hardly be called an intelligence.
To me, the truly astounding thing is that there actually are people in the world who click on these ads. It is absolutely mind-boggling that anyone would voluntarily call a telemarketer!
That is an argument against full Hungarian notation, not against static typing
Let me try rephrasing the question one more time: how can you manage to not think about the type of the identifier? When I think of variables, I think primarily of the type rather than the name. For example, here's a class I designed a couple of hours ago (just the data fields, for clarity):
My thoughts went something like this: "ok, I need an int for the classid, another int for the parentid, a string for the name, a string naming the library it's in, and a list of interfaces it exposes." When I think "m_Id", I automatically think "integer", and I would be curious to discover how you would think of it in some "typeless" way. You see, what it is makes a big difference: if it is an integer, searching is quite inexpensive and I won't worry about doing it often (this is in a compiler-type application, which spends about 40% of its time looking stuff up). If it were a string or a GUID, I'd be more concerned with performance and might add a separate index or a hash table to avoid doing hundreds of string comparisons during a search, I would also have second thoughts about using it as a key for parent class lookup, probably switching to using something else for that purpose. Similarly, I'm choosing to store strings in the object rather than in a separate stringtable to make the lookup code cleaner. This decision implies that I would want to try implementing the db reader such that it will load records on demand (with readahead through a sliding buffer, allowing me to reuse already existing async loading code) instead of reading it all in at once as I would have had to do with a stringtable.
Then I'd type them in in the order I thought of them and give a quick visual check for alignment. string and vector are both pointer-grain, and so is the vtable ptr. The classids are 4 bytes (fixed-size type because it will be directly written to a binary file), and so should be grouped together to avoid padding on 64bit platforms. I happened to think of them together already, so no reordering was necessary. No problems visible in memory, so I might stop here. Later, when writing serialization routines I realize that the interfaces vector (which is a list of 4 byte ids) should precede the string for optimal packing (vector may end on 4-grain, while I may later want to align to 8-grain if I later decide to write some 8byte int, so starting a 1-grain string in there would save space), so I quickly jump to the header and switch them (reading memory sequentially gives the best cache utilization because the read cache will prefetch stuff that way, and declaring them in order will generally cause the memory block allocated by the containers to be contiguous)
The above thought process obviously takes a lot less time than the explanation. I can usually complete all of the above considerations well before I finish typing the class in. It's not because I'm an assembly wizard. It's because I always think of these things whenever I create a new class, and have been doing it for many many years. Practice and habit make them automatic and I hardly notice I'm doing it.
> So instead of ALWAYS having to specify a type I just check the type when it matters.
How do you avoid stupid errors where you mistype the variable name and end up passing to a function something completely different from what you intended? In C++, the compiler will stop and say, "Whoa! That function works with integers, are you sure you want to give it a Window object?
> This example is of an accumulator generator
;) Readability is also a pretty big factor, as APL demonstrates with flair. To a procedural programmer like me, C++ is far more readable than Lisp and always will be.
His example in C++ is not all that larger than the lisp version, and mostly concerns syntactic necessities rather than real code. I would omit the copy constructor (because the compiler can write one by itself) and put the inlines on one line, indented to a common point, to make the real code stand out.
Also, as you pointed out, it is a functional programming example. That is another big difference between us: I really hate functional programming. Lisp to me is the language of gray-haired academics who have never seen the real world. (This view is corroborated by the fact that there really are no useful Lisp programs in the world. Pretty much all the open source code you'll see on SourceForge or elsewhere on the net is either in C, C++, or Java.) It's not so much the language syntax, but the way of thinking of processes as functional trasformations instead of instruction sequences. Since the latter is what the CPU really does, the former seems totally absurd to me. At one time I was trying out STL predicate algorithms for a while, and while they work fine for containers of integers, they fail horribly for any complex processing involving object containers. They also frequently fail to expand to the loops they represent, creating bloat and inefficiencies. So I finally rewrote everything with iterative syntax. The clarity of the code improved dramatically and so did code size and performance. Needless to say I don't use them any more.
I see the same problem as a plague to mathematics in general. The insistence on describing every system as a function increases complexity beyond all reason. It is this insistence that makes the Shrodinger equation totally useless in describing molecular interactions. If physicists started thinking iteratively and locally instead of creating giant global system equations they would no doubt come up with their GUT much faster and avoid ridiculous things like quantum mechanics.
> I would also recommend: For a Java/C++vs. Lisp comparison.
I'd have to see the C++ code to critique. A cursory look over the Lisp version suggest that a nearly direct translation to C++ would be possible.
> And for another programmers take on it where he tries the same thing: C++ hackers take
Invalid link.
> Also see another PG article: Succinctness is Power
Not necessarily. Just because you have to type less, doesn't mean the code is easier to write. Writing APL code can be pretty damn hard, and it is the most succinct language in existence
> So in my IO bound world I use the most productive and powerful languages I
> can convince my team to use without secretly wanting to murder me.
Convincing your team to switch languages is an entirely different issue from which language you yourself want to use. When on a team, you use the language the team is familiar with. It is counterproductive to use a team of Java programmers to write a C++ application. If you want to do that, you hire a team of C++ programmers. In general you would choose the language before choosing the team.
> That said is there REALLY a reason for every programmer to understand pointers?
Is there a reason for every programmer to understand that memory can be addressed? That's what pointers are all about. An address in memory. You understand pointers when you understand how your data is stored in memory, and I would argue that there are few things more important for a programmer to know.
> Do you really have to know assembly on up? Is that important for every programmer to know?
Yes. So he would know how much things cost. These days programmers raised on Java are becoming totally ignorant about the cost of what they do. It is because of them that we have obese obscenities like OpenOffice, which tak
> What does not change is that you still have to know and use pointers
:) Remember that in C++ you also need to get the appropriate library for your task. If you write everything from scratch, then of course you'll end up doing more work. In your intepreted language you probably have everything already bundled in and have no choice in what constructs you use, whether they are good or bad. The bundled functionality makes that language because it is not possible to natively reimplement them. In C++ it is always possible and is frequently done in order to create better APIs. In Java, you're pretty much stuck with what you have forever and ever.
;) [better start defining your terms and giving examples, or how else can I refute your vacuous arguments?]
> and all of the syntax required to deal with them in C++. After a time
> it becomes second nature. And with a little experience in a debugger
> you can quickly track down most pointer related mischief.
The people who complain about pointers are the same ones who don't know how to properly do memory management. I haven't had any "pointer related mischief" in years. Just as thinking about object ownership helps you avoid allocation problems, it will also rid you of all "pointer problems". I think that people are afraid of pointers only because they heard all those horror stories from bad C programmers.
> However, you will still be writing more code in C++ or Java than
> you will in a more expressive and concise language.
You better support that with an example!
> I wrote code in C long enough to know that even if you are one of the
> best C or C++ programmers in the world you are still at a disadvantage
> when compared to a great programmer that knows their way around a
> language like Lisp or Ruby.
Now, don't go lumping C with C++ here! They are worlds apart. While what you say is almost certainly true for C, it is blatantly false for C++. Once you have objects, the syntax of their creation is of limited importance.
> The argument is that statically typed languages like C, C++, Java, and C# take more lines of code
That argument I could never understand. When would you ever be in a situation that you wouldn't know the type of your variables? And how, may I ask, will the maintainers of your code know what's in them if you don't tell them what's in them? Sounds like a recipe for obfuscated code to me.
Of course, I'm not talking about object polymorphism here, which works just fine in C++, thank you.
> The truth of the matter is that most classes of programs can be written in more powerful languages.
I would agree entirely. There is, after all, no more powerful language than C++!
> So is your defense of C++ a personal bias or do you really think that C++ is more productive.
Both. Naturally I'm biased, since I know it so well, but I have also never seen any examples to the contrary. I am also immediately prejudiced against all those "great" new languages; they all claim to be such an improvement over C++, but such claims usually come from not understanding C++. Before you create a fancy new language, you better define clearly what the problem is with the one we already have. Garbage collection is a fine example of a solution to the wrong problem; instead of educating the programmer, change the language, solving one problem while creating a host of others. If you don't understand C++, you are only liable to reinvent it. Badly.
Do you love a challenge? Do you like speedrunning? Are you totally bored by your Sims game? Try the speed sims method! Put eight people in one house and build just one bathroom. Then set the game speed to two, turn on free will, and try to get them all to work in a decent state. I guarantee you'll be sweating in no time at all.
> The biggest problem I have is that C++ is just not
> required for many types of programs.
That's a problem indeed; a problem with your thinking, that is. You are thinking that C++ is some heavyweight monster that is only suitable for big problems, while nothing could be farther from the truth. C++ is the lightest language you can use, with the smallest possible footprint. You could go smaller only with C or assembly, neither of which is suitable for anything larger than a small utility program.
When I think of the enormous VMs required for interpreted languages like Java, I certainly might say that such bloat is "not required" for some small application, and rewrite it in C++. It is guaranteed to be smaller, and quite possibly faster (an I/O-bound program will be slow in any language).
> Even being one of the best few C++ coders you would be more
> efficient if you were as proficient in some more dynamic language.
I disagree. Anything your dynamic language provides is just as easily doable in C++. The difference is that interpreted languages usually have everything and the kitchen sink built in, while with C++ you have to select an appropriate library for your task. With the right library, C++ will do just as well or better than any all-powerful-language.
I know you'll be mentioning garbage collection next, so I'll explain why I don't need it. While I have no real problem with its concept, I do have a problem with the unfortunate mentality it promotes. GC programmers don't think about ownership and allocate memory too often. In my code, for example, you won't find any memory allocation. At all. You could grep for 'new' or 'delete' all day long and never find one. That's because a good C++ programmer will make use of STL containers for heap management. Those are for permanent storage of various kinds. For short-life objects we use our own GC, called the stack. For heap memory objects, it is extremely important to think about who owns them and how long they will live. In Java the mentality is to just pass around pointers wherever they are needed, reference counting them or whatever, without any thought for such things. That's why there are so many leaky Java programs. In C++ you have to do it the right way -- define an owning object for every allocated block and describe exactly how and when it is allocated and freed. Because it is the right way, I would undoubtedly do it the same way in any language, GCd or not.
> I think Java is a mess. Ditto for C++. To much baggage in both
Just because C++ has baggage, doesn't mean you need to use it. Yes, it is quite possible to use C++ in the same way as C. That's what most C programmers do when they switch. They continue to think in functions rather than in objects, refuse to learn about proper design, and complain endlessly how the compiler "does things behind their back". Lacking knowledge about class and template design, they generate slow and bloated code and blame their incompetence on the langauge. Then they go back to C, but, having gotten used to some C++ features, now starting to manually do all those things the C++ compiler used to do for them (like those hand-coded vtables in the kernel modules, for instance) and bragging about being real, macho, cycle-counting programmers.
> There are a LOT of languages out there other than C.
:) Seriously, to a hardcore C++ programmer like myself there really are no other general purpose languages. I would use a specialized language for some tasks, of course; Javascript is essential for webpages, SQL is irreplaceable for queries, and shell scripts are very useful for administration work. However, for any serious project there is simply no substitute for C++, and every time I've tried to implement something in another language (notably Perl), I ended up recoding it in C++ as soon as any really complicated task came up. The best language is the one you know well, so it is much better to have perfect knowledge of C++ then to know a dozen languages poorly.
Heresy! There are NO languages out there other than C++
> And technically automatically interpreting a line without a brace as a
> terminated statement (IE: with the semicolon) can be just as bad as
> programmers that can't find a block of code.
I didn't say I always did that, only that it takes a few distracting seconds to switch to another interpretation style, just as it takes some time to switch between speaking human languages. I interpret a line without a brace as a terminated statement in my code because that is what I usually have. No, not ifs, of course, but I do have a few terminated for loops around. I can't remember using a free block recently, but there are occasional uses for them to manage object lifetime.
> The best argument I have seen is for condensing code.
> It does save a line or two here and there if you really need it.
Saving lines is a good idea whether you need it or not. The more of the code the programmer can see on the screen, the faster he will see its control flow. If a function is so large to require scrolling, he'd have to go back and forth many times. This is particularly bad in C, where all the variables are declared in the beginning of the function. If I had to pick the worst style problem C encourages, this would be it. I hope that all compilers will eventually support declaring variables at the time of use, like gcc now does.
> With 1280x1024 being a relatively common display resolution used by
> developers these days I don't think it is such a big deal to have
> an extra line for the braces
You just wait a few years, son, and check your eyes again. I work on a 100x30 console (the real console, not an xterm), and that's about as small a font as I can comfortably read all day long. As you can imagine, this is one of the reasons the code I write is as concise as I can make it without losing clarity. In most cases clarity is gained rather than lost.
> No, you don't. In C and languages derived from it, the
> compiler couldn't care less about indentation.
We format code for people, not for the compiler. If I were writing code just for the compiler, I could put everything in one line, delete all whitespace, and name all my variables x42. If you did that while writing code for your employer, you'd be fired immediately.
> whereas these two snippets will produce different results
> even though the indentation is the same:
Every programmer's editor is perfectly capable of autoindenting the code for you. Even my ancient vi can do it. In such an editor it takes some effort to screw up indentation, and that effort would have made your mistakes obvious if you tried to type in your examples.
> Using indentation to look for code blocks is courting disaster
You look for blocks in order to separate the code into logical units, not to find bugs in it. Debugging and reading are rather different tasks in spite of being inseparably related.
> I am an old school coder
> Why do people put the opening bracket on the same line as the conditional?
You must not be very "old school" if you don't know the answer. The cuddled braces are the original K&R indentation style; they are what C was supposed to look like.
Another answer is that there are two different ways to look for blocks. I look at indentation as a clue to the new block and when I see a brace on a line by itself I immediately interpret it as:
if (x);
{
}
This is especially true when I can't see the end of the line. Obviously, it doesn't take long to switch mental gears, but it is inconvenient. No, I am not going to switch to this style. You have to indent the code anyway and since the indentation change already says "new block", the brace is redundant, and therefore should not be emphasized. I might also point out that the braces are only required for multiline blocks anyway, so looking for indentations is a skill every C programmer needs, wherever he places the braces.
People who put braces on separate lines look for the opening brace itself to signal the start of the block and panic when they see indentation level change without it. It is really just another way of looking for blocks, and I am disappointed that it is so commonly taught.
In San Francisco, a bathroom is all I can afford on my salary.
Gosh, my 1GHz Athlon MP doesn't even make the "legacy" category any more. I'll just go cry now...
But that's just the point. When you run as root, you don't have absolute control over your box; the apps that you run do. By using a non-admin account, you are not locking out yourself, you are locking out arrogant apps that think they can run your computer.
Or they would have realized what a neat name for a storm "Xena" would make.
I actually got this one at a job interview and was unable to solve it. When told the answer I was very upset and explained why I would never use such a shoddy solution (and yes, I got the job :). You see, a lightbult is defined as a light-producing device; the specification says nothing about heat. If you rely on heat to make your solution work, you're asking for trouble in the long run. As lightbulb technology improves, there is absolutely no guarantee that lightbulbs will continue generating heat. In fact, it is almost a certainty that eventually they would generate only light and no heat at all, at which point your solution will break and you'll have to spend weeks hunting through your code to figure out why it isn't working. Add to that the fact that any programmer worth his salt wouldn't even think of undocumented features like this (especially because in his time all lightbulbs produce no heat), the chances of the bug being found go down significantly. The moral of the puzzle should be: "thou shalt not use undocumented features".
Don't they read the news? Last week Delphi declared bankrupcy specifically to get rid of union laborers. All those union workers will now be forced to take pay cuts down to $10. It's a sure bet that other companies will follow suit with similar measures, just as they are now dumping pension benefits in emulation of the airlines. The days of the unions are clearly numbered, and only a fool would join one now.