He was and is quite good, A to A+ level player; and it showed especially in ProLeague, where he is one of the three legs of the BBF SKT T1 line. However, he always got knocked out by the Dong or the God Bonjwa in individual leagues; but he has produced some epic games while doing so.
That was sort of my impression, which is why I brought up the individual leagues vs Proleague in my last post.
Don't get me wrong; I didn't have any particular dislike for Fantasy (unlike a couple of the youtube commentators:-p), I just never picked up a particular like for him like I did for a few other players. (Stork, Flash for a while (he's kind of gotten too good), good Bisu, and a couple others.)
Also, Zs rely on Mutas even in Air to Air warfare, Devourers (damn you SC2 for making me think Corruptors) were used as support units to make every Glaive Wurm hit from Mutas pack a harder punch instead of being the primary DPS since they were simply too expensive. They were insanely good against extremely late-game BCs and Carriers though.
One of my favorite games (and one of the fairly early ones I watched) illustrates this pretty well: Stork vs GGPlay, a game where they mined out Andromeda. (It's close to an hour and a half long.) Stork was wreaking havoc with his Carriers for a while, but GGPlay got out his devourers and just started destroying them.
You by any chance go by the moniker of evanthebouncy?;)
I'll admit that I haven't, and I suppose I should have said that my perspective was from a period roughly mid 2008 to 2010 (I think I got into it shortly after the big July vs Best series, and haven't watched much in the last year), so if the Valkyrie was used before I started or after I stopped, that would skew my statement.
The other thing that would do it is that I didn't watch all that much Proleague, rather just the individual leagues, and I don't remember quite how much Fantasy was represented there. He wasn't one of the players that I really liked watching (though if I knew about his Valkonic build, maybe that would have changed:-)), and so would have only usually watched if either he was playing another player I did like (which would mean probably not zerg) or if it was pretty late in the tournament.
So neither the leagues nor the games nor the players of the games I watched were really fairly chosen, so there could easily have been some systematic bias I was unaware of that took me away from games with Valkyries.
(And if you're wondering, the two games that I do remember were Flash vs Effort on Match Point where they restarted, and Calm vs Upmagic on Outsider. The last one I thought was awesome at the time except for Upmagic losing, but in retrospect has been majorly tainted by Upmagic's involvement in the match rigging scandal.)
I know that; I was responding to my parent, who apparently didn't. His claim was that Valve buys user-generated content, and that Portal is an example of that. It is not.
BTW, I can't speak to the others, but Portal was developed by the team while they were at Valve. Portal's a far, far cry from Narbacular Drop. That was definitely not a case of Valve buying an existing program and rebranding it.
True; but things like Valkyries and whatever the Zerg AoE aircraft is were introduced in Brood War as a counter.
The thing about Valkyries though... is that they were almost never used in high-level play. Relatively early mutas (lair right into spire right into mutas) came out in most ZvTs, but I can think of two Korean games in two or three years of watching quite a few where you got to see Valkyries. (I'm sure there were plenty more, but they were not common.) Generally the counter was just the usual M&M plus turrets.
Age shouldn't matter, but it's quite reasonable to make seniority matter: it rewards loyalty. At the very least, sticking with the same company reduces the expenses of recruitment, interviewing, formal training, and your new employees becoming familiar with the code base. There are less concrete benefits to the company too, especially if you're a good employee, like the fact that even after the expenses above it's a crap shoot as to whether the new guy will be as useful as you.
But, why remove it in the first place? For a decade or more, the status bas has been useful to check what that link you are about to click on actually points to. Removing it just opens people up to all sorts of things.
I'm not going to debate the relative merits of the old approach and new approach, but as pointed out repeatedly in each of these discussions, FF4 still shows you the target URL, just in a different place. It's likely that it will be truncated fare more and far more often, but at least according to one poster, it at least does the right thing and elides the middle.
Which is annoying, because IE still sucks, Safari is annoying, and I can't even begin to care about Chrome.
Not knowing what you have against Chrome, you might try out Opera. I've been using it as my primary browser at home for quite some time, though I'm not all convinced that I wouldn't like another one better, and I might go to FF4 when it comes out for a bit. But it is a good browser.
Opera puts the find at top, and I dislike it. Why? It's not a fixed part of the UI. Which means that when you hit ctrl-F, the page shifts down so that the find bar doesn't cover the top. When you hit esc, the page shifts back up. I prefer the FF approach. (It's a similar reason to why I dislike the Mac "change the size of the window when you change tabs" dialogs.)
In C++ the name is not "plus" but the symbol "+". This symbol "+" can stand for anything you want, like append, save, concat, plus, add, etc. ppp. If you set a normal name for the operation like "append" or even "add" for complex numbers, the user of your library does not need to look up what the method is doing because it tells him in the name.
I personally feel that, if I tell you "I'm calling operator+ with a [type of the first operand] and a [type of the second operand]" and you can't immediately make an accurate guess as to what the result will be, that is probably an abuse of the operator overloading feature. If you allow yourself to read some generic usage information about the types involved and that's still true, then I'd say it almost certainly is. (The latter would "allow" operator overloading in some more esoteric cases like my expression tree builder I've mentioned elsewhere in this thread.)
(Also I feel like you're padding your list a bit there what with both "plus" and "add", but that's beside the point.) But why it is not in the C++ standard like in Java is "+" for Strings a concatenation?
It is in the standard.
Why's it not in the core language? Because strings aren't, so so saying "the language should say + on strings should do concatenation" doesn't make any sense. You could say that if you replace "string" with "char*" but that brings out a whole HOST of other problems.
Now you can argue (very reasonably) that perhaps strings should be a core language feature and not just a feature of the library, but this ignores that the language designer can't add EVERY type for which it is reasonable to write a "+" operator to the core language.
The same goes for keywords, are you going to argue that keywords overloading is a good idea?
Heh, now that's an interesting question. And I have a couple answers.
First, understand that I've become a fair fan of syntactic abstraction. This plays a big part of why I like C++ (where I developed it), and is why I love Lisps. So don't count on me to see some innate problem with keyword overloading just because it's keyword overloading.
Second, it's not like operator overloading ever changes the meaning of anything, really. To the compiler, it adds a new meaning where there wasn't one before. To the programmer, if there is some meaning of "+" that doesn't make sense, then go down the hall and hit the programmer who wrote it or shoot an email to the dev list, and write a wrapper function. Why when someone does that with operator overloading do we say "a language shouldn't support operator overloading" but when someone comes up with a bad name for a function (would you like some examples? I've seen plenty) we don't say "a language shouldn't support functions"?
Third, I can actually think of cases where a simple way of doing "keyword overloading" might actually be a reasonable idea, but I kind of don't have time to type it out right now. If you're curious I can expound more fully, but the idea is something like "overload if/while to reduce the temptation to add an automatic conversion to boolean (a la the iostream types)."
Machine language is probably the most widely used of all since everything eventually breaks down to it, but does that mean it's a programming language?
Sure. So is Java bytecode. Just because it's obnoxious to use doesn't mean it's not a programming language.
Nothing is more ubiquitous today than HTML, yet most "programmers" would argue that HTML is not a programming language, but guess what - it is a "declarative" language as opposed to an "imperative" language, but does that really disqualify it as a programming language? Many would argue yes, it does.
Ah, now see, HTML is an interesting question. I'm not sure how I feel about it. I would tend to say "no", though I'm not completely set on that belief.
But that declarative vs imperative? Not at all the problem. Haskell is clearly a programming language, and it's not imperative. I would say Prolog is too, and it's quite declarative (although I don't understand how you would actually use it for most tasks, that's my own failing).
No, if HTML isn't a programming language, it's because it's not Turing complete. Heck, I don't even know how you could add 1 + 1 with HTML and display 2 let alone do more complex loop/recursion computations.
CLisp, Clojure and Arc are not the same as LISP, they are dialects of LISP.
Okay, fair enough, but then why bring up LISP? Has anyone actually used true LISP any time in the last couple decades?
The one and only place where "+" is good name is numbers.
Is it? What about strings? Or lists? (Most languages, of course, use + for string concatenation. You could argue that strings should be a primitive, and I kind of agree, but there are definitely reasons that speak in favor of C++'s approach as well. In particular, it means that you can write classes that are almost strings, but different in some small but important way (e.g. encoding), and use them the same. Some languages think + makes sense for lists. Python does. C++ doesn't. I think it's at least not unreasonable to have a list + a list give you a list.)
Or what about some other weird things? What about for a library that builds expression trees. "+" takes two trees and returns a tree that represents their sum. Is "+" such an unreasonable name for that? (While I think that application is definitely more questionable than the traditional number-like object, I'm hard pressed to come up with a pithy alternative. And in this application, switching to overloaded operators for building expression trees made the code easier to read to the extent where what was there was a comment with the expression written in traditional infix notation preceding an ugly mess of function calls, and what I wound up with was almost character-for-character identical to that comment.)
Is it worth it? Is it really worth to be able to add matrixes with +? I have never written a single program where "+" could have been a descriptive name for a function.
And I've written at least a couple, even restricting to just programs that use + to add number-like classes. Funny thing that, how it's nice that languages can cater to multiple people.
Or why not tear down the strawman. How 'bout []? That's an operator. How many programs have you written that use random access containers? (Feel free to answer the negation of that question.)
Look at any managed runtime environment with garbage collection.
I've looked at many of them. I was in a grad class with two friends who did a class project that became a tech report on the topic. None of the languages I would consider anywhere close to mainstream have support as good as C++'s.
The problem is that managed libraries give you management of memory -- and nothing else. The best that most languages provide is stuff like Python's context managers, C#'s using statement, and a couple Lisp's dynamic-wind. These are good, but they introduce syntactic overhead every time you need to use it, which you don't get with C++. That puts them at a small disadvantage.
"Some other" popular languages leave you with nothing more than the finally block. This is error-prone enough that a couple projects define classes (e.g. a wrapper for the File object, which must be closed) with a single "run" function that does the cleanup in a finally block, and then to use the file object you write an anonymous inner class. Even the Java folks themselves realized that the finally-based scheme was terribly error prone and did something similar for their protected code API. So now you've got this wonderful syntactic mess:
AccessController.doPrivileged(
new PrivilegedAction() {
public Object run() { /* work to do while privileged */
}
});
(The doPrivileged function calls a function beginPrivileged, calls run, then calls endPrivileged in a finally block.) This, IMO, doesn't remotely compare to RAII.
The only language I can think of that has a resource-cleanup mechanism that I actually like as much as C++'s is D, which actually improves it.
This is where exception handling actually works without the need for the developers to contort themselves with library-provided helpers over every pointer assignment, and ensure that no destructor can throw exceptions.
Now, I'm not going to claim that C++'s exception handling semantics don't have their dark corners -- actually almost everything about C++ has plenty of dark corners. I also don't want to diminish the value of a managed environment: I said above that it gives you management of memory "and nothing else", but managing memory is admittedly a huge deal.
But, I still feel that C++'s resource management is basically second to none.
(I'm also working on a large C++ project now where basically everything is a smart pointer, and I'm not sure what "library-provided helpers" we're contorting ourselves "over every pointer assignment". I hesitate to bring this up because this is a research project and we're probably about as safe from exceptions as a water balloon is safe from a pin, but at the same time we've also had basically no issues caused my memory safety. I suspect you may be overstating the drawbacks of C++ here a bit.)
Bah, I messed up the HTML and didn't spot it in preview. This reply just corrects that; feel free to reply to whichever, but this will be way easier to read. (The other will have missing parts that were chopped out by interpreting << as markup.)
Why obscure the code with op.ov.? Why not state very clear in the code what you are going to do?
Because when a class overloads an operator, chances are pretty darn good that the clearest way write code using that class is with that operator!
Suppose I write a complex number class. (Or, if you feel like saying "what about C99's _Complex, a matrix class.) Which is easier to read:
z = z * z + c;
or
z = z.times(z).plus(c);
To me, it's not even a particularly close contest, and that's a pretty dead simple expression. The difference in readability grows dramatically as it gets more complicated, especially if you need grouping (parens).
As a pretty drastic example, I was working on a project that has a step in which the code builds up expression trees for a reasonably complicated expression. I introduced some overloaded operators (e.g. operator+ takes two tree nodes and returns an AST representing their sum) and rewrote the expressions. And when I was done, I realized that I had duplicated -- almost character-for-character -- the comments that were sitting above the expression. I turned comments into executable code with operator overloading. And while I feel a twinge of guilt at this story in the sense that even I am not completely convinced that was a completely appropriate use of operator overloading, there's no way in my mind that I think the code didn't become way more readable.
As example, a very abused operator is the <<. You write file << "text" It's look very cool, but what does it mean? Why not state clearly what it means: file.append("text") or file.save("text").
What kind of answer do you want here? The most direct answer is because C++ doesn't support external methods (and doesn't root all objects at an Object class with a toString method) or variadic templates.
In other words, say I wrote that complex number class from above. I want to print my complex number z. How do I do it? Well, I can't say file.append(z) because file's class has no idea what my complex number is. That means that I have to write either a toString method and say file.append(z.toString()) or I have to reverse it and make a method of the complex class that takes a stream and say z.writeTo(file). Neither approach is super attractive. file.append(z.toString()) is way more wordy than file << z (almost 3x the number of characters and over 3x the number of tokens), and if I do the latter thing, you can't just chain things together. (What would in actual C++ be file << "(" << z << ")" would have to become three separate statements.)
Operators get around this by allowing you to use free functions. Now you could do the same thing with non-operator free functions too: make a set of write(stream, object) functions. But that quickly becomes obnoxious to edit. That chained output from before would become write(write(write(file, "("), z), ")"). Not only is that obnoxious to read, but if you want to add a fourth thing to print out, you have to insert stuff not just at the end of the line but at the beginning of it as well.
Now, external methods make the first solution (file.append) workable because you'd be able to add new overloaded append methods for to your class without mucking about with file's definition. Variadic templates would allow you to refine the second version to write(file, "(", z, ")") and keep typesafety and extensibility (which printf lacks). I'd personally be quite happy if C++ supported either or both of these, but then-again my syntactic-sugar sweet tooth is as activ
Why obscure the code with op.ov.? Why not state very clear in the code what you are going to do?
Because when a class overloads an operator, chances are pretty darn good that the clearest way write code using that class is with that operator!
Suppose I write a complex number class. (Or, if you feel like saying "what about C99's _Complex, a matrix class.) Which is easier to read:
z = z * z + c;
or
z = z.times(z).plus(c);
To me, it's not even a particularly close contest, and that's a pretty dead simple expression. The difference in readability grows dramatically as it gets more complicated, especially if you need grouping (parens).
As a pretty drastic example, I was working on a project that has a step in which the code builds up expression trees for a reasonably complicated expression. I introduced some overloaded operators (e.g. operator+ takes two tree nodes and returns an AST representing their sum) and rewrote the expressions. And when I was done, I realized that I had duplicated -- almost character-for-character -- the comments that were sitting above the expression. I turned comments into executable code with operator overloading. And while I feel a twinge of guilt at this story in the sense that even I am not completely convinced that was a completely appropriate use of operator overloading, there's no way in my mind that I think the code didn't become way more readable.
As example, a very abused operator is the
What kind of answer do you want here? The most direct answer is because C++ doesn't support external methods (and doesn't root all objects at an Object class with a toString method) or variadic templates.
In other words, say I wrote that complex number class from above. I want to print my complex number z. How do I do it? Well, I can't say file.append(z) because file's class has no idea what my complex number is. That means that I have to write either a toString method and say file.append(z.toString()) or I have to reverse it and make a method of the complex class that takes a stream and say z.writeTo(file). Neither approach is super attractive. file.append(z.toString()) is way more wordy than file (almost 3x the number of characters and over 3x the number of tokens), and if I do the latter thing, you can't just chain things together. (What would in actual C++ be file would have to become three separate statements.)
Operators get around this by allowing you to use free functions. Now you could do the same thing with non-operator free functions too: make a set of write(stream, object) functions. But that quickly becomes obnoxious to edit. That chained output from before would become write(write(write(file, "("), z), ")"). Not only is that obnoxious to read, but if you want to add a fourth thing to print out, you have to insert stuff not just at the end of the line but at the beginning of it as well.
Now, external methods make the first solution (file.append) workable because you'd be able to add new overloaded append methods for to your class without mucking about with file's definition. Variadic templates would allow you to refine the second version to write(file, "(", z, ")") and keep typesafety and extensibility (which printf lacks). I'd personally be quite happy if C++ supported either or both of these, but my syntactic-sugar sweet tooth is as active as my normal sweet tooth.
But without either of those features, the only alternative to the overloading of > that I think is even remotely attractive is the forced toString. And given how early programmers are introduced to the > operators, how idiomatic their uses are, and the clutter they remove from the source code, I think the overloaded operators are the least bad alternative.
I hope by RAII you mean the general pattern of freeing allocated resources in the destructor of the object that owns them, and not the obligation to wrap everything with smart pointers and similar gunk in order to attain "exception safety". Because the latter is entirely self-inflicted by the language design.
Combination of both. RAII is a good idea and awesome even if C++ did not have exceptions, however exceptions make something RAII-like nearly essential to avoid those leaks. (I happen to think that exceptions are a good idea too, but am much less... certain of that position than some of my others. I also haven't seen a language that I think gets exception safety in a substantially better way than C++ does.)
If you want to read assembly for your target architecture but cannot understand what it does, how is it the C compiler's problem? It does what you ask it to do.
That's not my point: my point is this. One of the arguments people bring up for using C over C++ is "C++ makes it harder to know what the compiler will do." But with today's optimizers, you need a reasonably intimate familiarity with your compiler to know what it'll do even in C code. So if you really care that much about the code it generates, you have to look. But you can look in C++ code as well, and see what it's doing. So both languages are in the same ballpark when it comes to "how easy is it to expect what the compiler emits."
The app store. But that's beside the point. You would be hard-pressed to find a place that's actually called "The Clothing Store" or "The Department Store", because they are almost certainly not trademarkable names: a competition could open right next door and call themselves "The Clothing Store" and the original store wouldn't be able to do anything about it. That is MS's argument.
Add templates and whether it's an object or not will depend on what the template gets used on.
So I'll grant you that. Let me ask this question, because I think it bears on this issue and I'm too lazy to type out my arguments for both cases. What do you feel about function overloading? (Specifically based on types, and not numbers, of arguments.)
My reply was slightly tongue-in-cheek, but I do think you have to be using a stupidly restrictive definition of "programming language" for it to exclude at least any Lisp from the last four decades or so.
Even that link you gave in the other post to the McCarthy paper includes things right near the top (of that section) that say "[LISP] has been or will be used for the following purposes:... writing a program to... writing programs for... writing programs to..."
And in your other reply you say "LISP has it's place as a powerful tool for creating domain specific languages and as a macro processor (as used in emacs), in AI and mathematics, but is not and was never intended as a general purpose programming language," which, even if it's technically true of McCarthy's LISP, definitely isn't true of a lot of more modern Lisps. Even if you think that Scheme wasn't intended as a general purpose language and is instead aimed at teaching (something that I would disagree with at least in terms of what it's become), I think it's pretty absurd to argue that Common Lisp, Clojure, and Arc aren't intended as such.
Operator overloading amounts to "allowing" folks to put their car into reverse gear while it is moving forward.
Like the car analogies, huh? How 'bout this? (I admit it's not as brief, but I feel it's at least actually closer to reality.) A language supports a Car primitive type, which has a gearShift. As an app developer, you are creating a Truck type. A language that doesn't allow operator overloading makes you invent a new name, say transmissionLever, and operate it with your foot. Meanwhile, the next guy comes along and designs an EighteenWheeler, calling his gear shift the gearChangeLever (you still operate it with your foot).
Of course now someone who wants to write a generic "drive" function is somewhat screwed because there are now three different names for the same concept. (Of course, you're not using a language that supports actual generic programming, so it's not like it matters anyway.)
Meanwhile, because I'm using a language that allows operator overloading, I write my Truck class and I call my gear shift the gearShift, because that name isn't restricted to just Car objects. I allow the driver to use his hand to use the gearShift, because the language lets me and it's more natural to use that power in this case then to force the driver to use his foot. I then write my EighteenWheeler class, and I name the gear shift the gearShift, and allow the driver to use his hand. Now all three vehicles work the same way, which makes using them more uniform and allows me to write that generic "drive" function that you'd have had to jump through hoops for.
How's that for an analogy? (Hint for the allegorically challenged: read "operator+" for "gearShift", "use like 'a + b'" for "uses your hand", and "use like a.foo(b)" for "uses your foot".)
I certainly agree that a language can encourage poor practice or discourage it, but I firmly believe that, on the whole, operator overloading leads to cleaner code.
That's why I'm actually excited about the Rock Band Squier guitar coming out. Rock Band 3 and that thing should go a long way toward your (and my) desire. It'll be interesting to see how long; hopefully it won't turn out to be a letdown.
(errr.. LISP? - there is considerable debate over whether LISP is even a true "programming language" but rather an alternate implementation of a Turing machine, but I digress)
Where are there debates like this? I'd like to see them so I can laugh at whatever definition of "programming language" the proponents of that idea are using that excludes a language that is really good for writing programs in.
(Or, probably more likely, see "Now, I haven't actually programmed in a Lisp, but...".)
...that leaves external hard drives. So buy a couple, back up from one to the other, and keep one somewhere else.
I put the best of the best of my pictures up on Flickr pro account, but that only works out to a couple dozen a month on average at most.
He was and is quite good, A to A+ level player; and it showed especially in ProLeague, where he is one of the three legs of the BBF SKT T1 line. However, he always got knocked out by the Dong or the God Bonjwa in individual leagues; but he has produced some epic games while doing so.
That was sort of my impression, which is why I brought up the individual leagues vs Proleague in my last post.
Don't get me wrong; I didn't have any particular dislike for Fantasy (unlike a couple of the youtube commentators :-p), I just never picked up a particular like for him like I did for a few other players. (Stork, Flash for a while (he's kind of gotten too good), good Bisu, and a couple others.)
Also, Zs rely on Mutas even in Air to Air warfare, Devourers (damn you SC2 for making me think Corruptors) were used as support units to make every Glaive Wurm hit from Mutas pack a harder punch instead of being the primary DPS since they were simply too expensive. They were insanely good against extremely late-game BCs and Carriers though.
One of my favorite games (and one of the fairly early ones I watched) illustrates this pretty well: Stork vs GGPlay, a game where they mined out Andromeda. (It's close to an hour and a half long.) Stork was wreaking havoc with his Carriers for a while, but GGPlay got out his devourers and just started destroying them.
You by any chance go by the moniker of evanthebouncy? ;)
Nope, sorry. I'm EvanED basically everywhere.
I'll admit that I haven't, and I suppose I should have said that my perspective was from a period roughly mid 2008 to 2010 (I think I got into it shortly after the big July vs Best series, and haven't watched much in the last year), so if the Valkyrie was used before I started or after I stopped, that would skew my statement.
The other thing that would do it is that I didn't watch all that much Proleague, rather just the individual leagues, and I don't remember quite how much Fantasy was represented there. He wasn't one of the players that I really liked watching (though if I knew about his Valkonic build, maybe that would have changed :-)), and so would have only usually watched if either he was playing another player I did like (which would mean probably not zerg) or if it was pretty late in the tournament.
So neither the leagues nor the games nor the players of the games I watched were really fairly chosen, so there could easily have been some systematic bias I was unaware of that took me away from games with Valkyries.
(And if you're wondering, the two games that I do remember were Flash vs Effort on Match Point where they restarted, and Calm vs Upmagic on Outsider. The last one I thought was awesome at the time except for Upmagic losing, but in retrospect has been majorly tainted by Upmagic's involvement in the match rigging scandal.)
(Reading "latter" for "former")
I know that; I was responding to my parent, who apparently didn't. His claim was that Valve buys user-generated content, and that Portal is an example of that. It is not.
And this is a problem... why?
BTW, I can't speak to the others, but Portal was developed by the team while they were at Valve. Portal's a far, far cry from Narbacular Drop. That was definitely not a case of Valve buying an existing program and rebranding it.
True; but things like Valkyries and whatever the Zerg AoE aircraft is were introduced in Brood War as a counter.
The thing about Valkyries though... is that they were almost never used in high-level play. Relatively early mutas (lair right into spire right into mutas) came out in most ZvTs, but I can think of two Korean games in two or three years of watching quite a few where you got to see Valkyries. (I'm sure there were plenty more, but they were not common.) Generally the counter was just the usual M&M plus turrets.
Age shouldn't matter, but it's quite reasonable to make seniority matter: it rewards loyalty. At the very least, sticking with the same company reduces the expenses of recruitment, interviewing, formal training, and your new employees becoming familiar with the code base. There are less concrete benefits to the company too, especially if you're a good employee, like the fact that even after the expenses above it's a crap shoot as to whether the new guy will be as useful as you.
But, why remove it in the first place? For a decade or more, the status bas has been useful to check what that link you are about to click on actually points to. Removing it just opens people up to all sorts of things.
I'm not going to debate the relative merits of the old approach and new approach, but as pointed out repeatedly in each of these discussions, FF4 still shows you the target URL, just in a different place. It's likely that it will be truncated fare more and far more often, but at least according to one poster, it at least does the right thing and elides the middle.
Which is annoying, because IE still sucks, Safari is annoying, and I can't even begin to care about Chrome.
Not knowing what you have against Chrome, you might try out Opera. I've been using it as my primary browser at home for quite some time, though I'm not all convinced that I wouldn't like another one better, and I might go to FF4 when it comes out for a bit. But it is a good browser.
Changing the default behavior is always bad. Always.
If that were true then you'd turn on the computer and get "C:\>" (or "$" as appropriate). Clearly absolutes are not so absolute.
You might want to talk to this guy
Opera puts the find at top, and I dislike it. Why? It's not a fixed part of the UI. Which means that when you hit ctrl-F, the page shifts down so that the find bar doesn't cover the top. When you hit esc, the page shifts back up. I prefer the FF approach. (It's a similar reason to why I dislike the Mac "change the size of the window when you change tabs" dialogs.)
Of course C allows you to do the same thing with goto
Or, you know, "return". Not that anyone uses that black sheep of a keyword.
In C++ the name is not "plus" but the symbol "+". This symbol "+" can stand for anything you want, like append, save, concat, plus, add, etc. ppp. If you set a normal name for the operation like "append" or even "add" for complex numbers, the user of your library does not need to look up what the method is doing because it tells him in the name.
I personally feel that, if I tell you "I'm calling operator+ with a [type of the first operand] and a [type of the second operand]" and you can't immediately make an accurate guess as to what the result will be, that is probably an abuse of the operator overloading feature. If you allow yourself to read some generic usage information about the types involved and that's still true, then I'd say it almost certainly is. (The latter would "allow" operator overloading in some more esoteric cases like my expression tree builder I've mentioned elsewhere in this thread.)
(Also I feel like you're padding your list a bit there what with both "plus" and "add", but that's beside the point.)
But why it is not in the C++ standard like in Java is "+" for Strings a concatenation?
It is in the standard.
Why's it not in the core language? Because strings aren't, so so saying "the language should say + on strings should do concatenation" doesn't make any sense. You could say that if you replace "string" with "char*" but that brings out a whole HOST of other problems.
Now you can argue (very reasonably) that perhaps strings should be a core language feature and not just a feature of the library, but this ignores that the language designer can't add EVERY type for which it is reasonable to write a "+" operator to the core language.
The same goes for keywords, are you going to argue that keywords overloading is a good idea?
Heh, now that's an interesting question. And I have a couple answers.
First, understand that I've become a fair fan of syntactic abstraction. This plays a big part of why I like C++ (where I developed it), and is why I love Lisps. So don't count on me to see some innate problem with keyword overloading just because it's keyword overloading.
Second, it's not like operator overloading ever changes the meaning of anything, really. To the compiler, it adds a new meaning where there wasn't one before. To the programmer, if there is some meaning of "+" that doesn't make sense, then go down the hall and hit the programmer who wrote it or shoot an email to the dev list, and write a wrapper function. Why when someone does that with operator overloading do we say "a language shouldn't support operator overloading" but when someone comes up with a bad name for a function (would you like some examples? I've seen plenty) we don't say "a language shouldn't support functions"?
Third, I can actually think of cases where a simple way of doing "keyword overloading" might actually be a reasonable idea, but I kind of don't have time to type it out right now. If you're curious I can expound more fully, but the idea is something like "overload if/while to reduce the temptation to add an automatic conversion to boolean (a la the iostream types)."
Machine language is probably the most widely used of all since everything eventually breaks down to it, but does that mean it's a programming language?
Sure. So is Java bytecode. Just because it's obnoxious to use doesn't mean it's not a programming language.
Nothing is more ubiquitous today than HTML, yet most "programmers" would argue that HTML is not a programming language, but guess what - it is a "declarative" language as opposed to an "imperative" language, but does that really disqualify it as a programming language? Many would argue yes, it does.
Ah, now see, HTML is an interesting question. I'm not sure how I feel about it. I would tend to say "no", though I'm not completely set on that belief.
But that declarative vs imperative? Not at all the problem. Haskell is clearly a programming language, and it's not imperative. I would say Prolog is too, and it's quite declarative (although I don't understand how you would actually use it for most tasks, that's my own failing).
No, if HTML isn't a programming language, it's because it's not Turing complete. Heck, I don't even know how you could add 1 + 1 with HTML and display 2 let alone do more complex loop/recursion computations.
CLisp, Clojure and Arc are not the same as LISP, they are dialects of LISP.
Okay, fair enough, but then why bring up LISP? Has anyone actually used true LISP any time in the last couple decades?
The one and only place where "+" is good name is numbers.
Is it? What about strings? Or lists? (Most languages, of course, use + for string concatenation. You could argue that strings should be a primitive, and I kind of agree, but there are definitely reasons that speak in favor of C++'s approach as well. In particular, it means that you can write classes that are almost strings, but different in some small but important way (e.g. encoding), and use them the same. Some languages think + makes sense for lists. Python does. C++ doesn't. I think it's at least not unreasonable to have a list + a list give you a list.)
Or what about some other weird things? What about for a library that builds expression trees. "+" takes two trees and returns a tree that represents their sum. Is "+" such an unreasonable name for that? (While I think that application is definitely more questionable than the traditional number-like object, I'm hard pressed to come up with a pithy alternative. And in this application, switching to overloaded operators for building expression trees made the code easier to read to the extent where what was there was a comment with the expression written in traditional infix notation preceding an ugly mess of function calls, and what I wound up with was almost character-for-character identical to that comment.)
Is it worth it? Is it really worth to be able to add matrixes with +? I have never written a single program where "+" could have been a descriptive name for a function.
And I've written at least a couple, even restricting to just programs that use + to add number-like classes. Funny thing that, how it's nice that languages can cater to multiple people.
Or why not tear down the strawman. How 'bout []? That's an operator. How many programs have you written that use random access containers? (Feel free to answer the negation of that question.)
Look at any managed runtime environment with garbage collection.
I've looked at many of them. I was in a grad class with two friends who did a class project that became a tech report on the topic. None of the languages I would consider anywhere close to mainstream have support as good as C++'s.
The problem is that managed libraries give you management of memory -- and nothing else. The best that most languages provide is stuff like Python's context managers, C#'s using statement, and a couple Lisp's dynamic-wind. These are good, but they introduce syntactic overhead every time you need to use it, which you don't get with C++. That puts them at a small disadvantage.
"Some other" popular languages leave you with nothing more than the finally block. This is error-prone enough that a couple projects define classes (e.g. a wrapper for the File object, which must be closed) with a single "run" function that does the cleanup in a finally block, and then to use the file object you write an anonymous inner class. Even the Java folks themselves realized that the finally-based scheme was terribly error prone and did something similar for their protected code API. So now you've got this wonderful syntactic mess:
(The doPrivileged function calls a function beginPrivileged, calls run, then calls endPrivileged in a finally block.) This, IMO, doesn't remotely compare to RAII.
The only language I can think of that has a resource-cleanup mechanism that I actually like as much as C++'s is D, which actually improves it.
This is where exception handling actually works without the need for the developers to contort themselves with library-provided helpers over every pointer assignment, and ensure that no destructor can throw exceptions.
Now, I'm not going to claim that C++'s exception handling semantics don't have their dark corners -- actually almost everything about C++ has plenty of dark corners. I also don't want to diminish the value of a managed environment: I said above that it gives you management of memory "and nothing else", but managing memory is admittedly a huge deal.
But, I still feel that C++'s resource management is basically second to none.
(I'm also working on a large C++ project now where basically everything is a smart pointer, and I'm not sure what "library-provided helpers" we're contorting ourselves "over every pointer assignment". I hesitate to bring this up because this is a research project and we're probably about as safe from exceptions as a water balloon is safe from a pin, but at the same time we've also had basically no issues caused my memory safety. I suspect you may be overstating the drawbacks of C++ here a bit.)
Bah, I messed up the HTML and didn't spot it in preview. This reply just corrects that; feel free to reply to whichever, but this will be way easier to read. (The other will have missing parts that were chopped out by interpreting << as markup.)
Why obscure the code with op.ov.? Why not state very clear in the code what you are going to do?
Because when a class overloads an operator, chances are pretty darn good that the clearest way write code using that class is with that operator!
Suppose I write a complex number class. (Or, if you feel like saying "what about C99's _Complex, a matrix class.) Which is easier to read:
or
To me, it's not even a particularly close contest, and that's a pretty dead simple expression. The difference in readability grows dramatically as it gets more complicated, especially if you need grouping (parens).
As a pretty drastic example, I was working on a project that has a step in which the code builds up expression trees for a reasonably complicated expression. I introduced some overloaded operators (e.g. operator+ takes two tree nodes and returns an AST representing their sum) and rewrote the expressions. And when I was done, I realized that I had duplicated -- almost character-for-character -- the comments that were sitting above the expression. I turned comments into executable code with operator overloading. And while I feel a twinge of guilt at this story in the sense that even I am not completely convinced that was a completely appropriate use of operator overloading, there's no way in my mind that I think the code didn't become way more readable.
As example, a very abused operator is the <<. You write file << "text" It's look very cool, but what does it mean? Why not state clearly what it means: file.append("text") or file.save("text").
What kind of answer do you want here? The most direct answer is because C++ doesn't support external methods (and doesn't root all objects at an Object class with a toString method) or variadic templates.
In other words, say I wrote that complex number class from above. I want to print my complex number z. How do I do it? Well, I can't say file.append(z) because file's class has no idea what my complex number is. That means that I have to write either a toString method and say file.append(z.toString()) or I have to reverse it and make a method of the complex class that takes a stream and say z.writeTo(file). Neither approach is super attractive. file.append(z.toString()) is way more wordy than file << z (almost 3x the number of characters and over 3x the number of tokens), and if I do the latter thing, you can't just chain things together. (What would in actual C++ be file << "(" << z << ")" would have to become three separate statements.)
Operators get around this by allowing you to use free functions. Now you could do the same thing with non-operator free functions too: make a set of write(stream, object) functions. But that quickly becomes obnoxious to edit. That chained output from before would become write(write(write(file, "("), z), ")"). Not only is that obnoxious to read, but if you want to add a fourth thing to print out, you have to insert stuff not just at the end of the line but at the beginning of it as well.
Now, external methods make the first solution (file.append) workable because you'd be able to add new overloaded append methods for to your class without mucking about with file's definition. Variadic templates would allow you to refine the second version to write(file, "(", z, ")") and keep typesafety and extensibility (which printf lacks). I'd personally be quite happy if C++ supported either or both of these, but then-again my syntactic-sugar sweet tooth is as activ
Why obscure the code with op.ov.? Why not state very clear in the code what you are going to do?
Because when a class overloads an operator, chances are pretty darn good that the clearest way write code using that class is with that operator!
Suppose I write a complex number class. (Or, if you feel like saying "what about C99's _Complex, a matrix class.) Which is easier to read:
or
To me, it's not even a particularly close contest, and that's a pretty dead simple expression. The difference in readability grows dramatically as it gets more complicated, especially if you need grouping (parens).
As a pretty drastic example, I was working on a project that has a step in which the code builds up expression trees for a reasonably complicated expression. I introduced some overloaded operators (e.g. operator+ takes two tree nodes and returns an AST representing their sum) and rewrote the expressions. And when I was done, I realized that I had duplicated -- almost character-for-character -- the comments that were sitting above the expression. I turned comments into executable code with operator overloading. And while I feel a twinge of guilt at this story in the sense that even I am not completely convinced that was a completely appropriate use of operator overloading, there's no way in my mind that I think the code didn't become way more readable.
As example, a very abused operator is the
What kind of answer do you want here? The most direct answer is because C++ doesn't support external methods (and doesn't root all objects at an Object class with a toString method) or variadic templates.
In other words, say I wrote that complex number class from above. I want to print my complex number z. How do I do it? Well, I can't say file.append(z) because file's class has no idea what my complex number is. That means that I have to write either a toString method and say file.append(z.toString()) or I have to reverse it and make a method of the complex class that takes a stream and say z.writeTo(file). Neither approach is super attractive. file.append(z.toString()) is way more wordy than file (almost 3x the number of characters and over 3x the number of tokens), and if I do the latter thing, you can't just chain things together. (What would in actual C++ be file would have to become three separate statements.)
Operators get around this by allowing you to use free functions. Now you could do the same thing with non-operator free functions too: make a set of write(stream, object) functions. But that quickly becomes obnoxious to edit. That chained output from before would become write(write(write(file, "("), z), ")"). Not only is that obnoxious to read, but if you want to add a fourth thing to print out, you have to insert stuff not just at the end of the line but at the beginning of it as well.
Now, external methods make the first solution (file.append) workable because you'd be able to add new overloaded append methods for to your class without mucking about with file's definition. Variadic templates would allow you to refine the second version to write(file, "(", z, ")") and keep typesafety and extensibility (which printf lacks). I'd personally be quite happy if C++ supported either or both of these, but my syntactic-sugar sweet tooth is as active as my normal sweet tooth.
But without either of those features, the only alternative to the overloading of > that I think is even remotely attractive is the forced toString. And given how early programmers are introduced to the > operators, how idiomatic their uses are, and the clutter they remove from the source code, I think the overloaded operators are the least bad alternative.
I hope by RAII you mean the general pattern of freeing allocated resources in the destructor of the object that owns them, and not the obligation to wrap everything with smart pointers and similar gunk in order to attain "exception safety". Because the latter is entirely self-inflicted by the language design.
Combination of both. RAII is a good idea and awesome even if C++ did not have exceptions, however exceptions make something RAII-like nearly essential to avoid those leaks. (I happen to think that exceptions are a good idea too, but am much less... certain of that position than some of my others. I also haven't seen a language that I think gets exception safety in a substantially better way than C++ does.)
If you want to read assembly for your target architecture but cannot understand what it does, how is it the C compiler's problem? It does what you ask it to do.
That's not my point: my point is this. One of the arguments people bring up for using C over C++ is "C++ makes it harder to know what the compiler will do." But with today's optimizers, you need a reasonably intimate familiarity with your compiler to know what it'll do even in C code. So if you really care that much about the code it generates, you have to look. But you can look in C++ code as well, and see what it's doing. So both languages are in the same ballpark when it comes to "how easy is it to expect what the compiler emits."
The app store. But that's beside the point. You would be hard-pressed to find a place that's actually called "The Clothing Store" or "The Department Store", because they are almost certainly not trademarkable names: a competition could open right next door and call themselves "The Clothing Store" and the original store wouldn't be able to do anything about it. That is MS's argument.
Add templates and whether it's an object or not will depend on what the template gets used on.
So I'll grant you that. Let me ask this question, because I think it bears on this issue and I'm too lazy to type out my arguments for both cases. What do you feel about function overloading? (Specifically based on types, and not numbers, of arguments.)
My reply was slightly tongue-in-cheek, but I do think you have to be using a stupidly restrictive definition of "programming language" for it to exclude at least any Lisp from the last four decades or so.
Even that link you gave in the other post to the McCarthy paper includes things right near the top (of that section) that say "[LISP] has been or will be used for the following purposes: ... writing a program to ... writing programs for ... writing programs to ..."
And in your other reply you say "LISP has it's place as a powerful tool for creating domain specific languages and as a macro processor (as used in emacs), in AI and mathematics, but is not and was never intended as a general purpose programming language," which, even if it's technically true of McCarthy's LISP, definitely isn't true of a lot of more modern Lisps. Even if you think that Scheme wasn't intended as a general purpose language and is instead aimed at teaching (something that I would disagree with at least in terms of what it's become), I think it's pretty absurd to argue that Common Lisp, Clojure, and Arc aren't intended as such.
Operator overloading amounts to "allowing" folks to put their car into reverse gear while it is moving forward.
Like the car analogies, huh? How 'bout this? (I admit it's not as brief, but I feel it's at least actually closer to reality.) A language supports a Car primitive type, which has a gearShift. As an app developer, you are creating a Truck type. A language that doesn't allow operator overloading makes you invent a new name, say transmissionLever, and operate it with your foot. Meanwhile, the next guy comes along and designs an EighteenWheeler, calling his gear shift the gearChangeLever (you still operate it with your foot).
Of course now someone who wants to write a generic "drive" function is somewhat screwed because there are now three different names for the same concept. (Of course, you're not using a language that supports actual generic programming, so it's not like it matters anyway.)
Meanwhile, because I'm using a language that allows operator overloading, I write my Truck class and I call my gear shift the gearShift, because that name isn't restricted to just Car objects. I allow the driver to use his hand to use the gearShift, because the language lets me and it's more natural to use that power in this case then to force the driver to use his foot. I then write my EighteenWheeler class, and I name the gear shift the gearShift, and allow the driver to use his hand. Now all three vehicles work the same way, which makes using them more uniform and allows me to write that generic "drive" function that you'd have had to jump through hoops for.
How's that for an analogy? (Hint for the allegorically challenged: read "operator+" for "gearShift", "use like 'a + b'" for "uses your hand", and "use like a.foo(b)" for "uses your foot".)
I certainly agree that a language can encourage poor practice or discourage it, but I firmly believe that, on the whole, operator overloading leads to cleaner code.
That's why I'm actually excited about the Rock Band Squier guitar coming out. Rock Band 3 and that thing should go a long way toward your (and my) desire. It'll be interesting to see how long; hopefully it won't turn out to be a letdown.
(errr.. LISP? - there is considerable debate over whether LISP is even a true "programming language" but rather an alternate implementation of a Turing machine, but I digress)
Where are there debates like this? I'd like to see them so I can laugh at whatever definition of "programming language" the proponents of that idea are using that excludes a language that is really good for writing programs in.
(Or, probably more likely, see "Now, I haven't actually programmed in a Lisp, but...".)