|
^^ Not before I make this post that I've already been typing Objective-C has had this so-called "monkeypatching"/extension methods for about 100 years now in the form of categories, and it's about time other languages like C# have decided that it's a feature worth having. I often hear self-proclaimed "OO purists" complain that attaching methods to a class you didn't write is a violation of OO design, but I would argue that forcing the user to put unrelated methods statically into some kind of "StringUtils" class or whatever is an even more egregious violation. There's no "object" there -- it's a workaround for an implementation detail and has nothing to do with the component design of the project. And as long as the language doesn't permit extension methods/categories to access private data in the class, then there's no violation of encapsulation either. I use categories all the time when I do Cocoa programming and I can't imagine living without them. I wrote a method once that escaped XML entities (ampersand, quotes, greater/less-than signs) and returned the new string, and it makes a lot more sense to write (I'll use C#-style syntax here for those unfamiliar with Obj-C) x = the_string.escapeXMLEntities() than it is to write x = HurfDurfXMLEscaper.escapeXMLEntities(the_string). It's no loving contest.
|
# ? Aug 27, 2008 19:00 |
|
|
# ? May 16, 2024 18:29 |
|
Well, you could just write a class that derives from string, which includes your new methods.
|
# ? Aug 27, 2008 19:36 |
|
Anonymous Name posted:Well, you could just write a class that derives from string, which includes your new methods. System.String is sealed in the .NET Framework.
|
# ? Aug 27, 2008 19:39 |
|
Mr. Herlihy posted:System.String is sealed in the .NET Framework. And java.lang.String is final. You'd have to facade it, and lose a bunch of syntatic sugar.
|
# ? Aug 27, 2008 19:52 |
|
Flobbster posted:I often hear self-proclaimed "OO purists" complain that attaching methods to a class you didn't write is a violation of OO design, but I would argue that ... You've just nailed one of the biggest meta-horrors there is. Programmers* are superstitious fucks who care more about fidelity to the received wisdom of their teachers and blind adherence to dogma than actually mapping out a solution in terms that match the way they think about the problem (don't worry, though; after doing this long enough, you forget how to think about problems in any other terms than those that match your One True Model!). They will move mountains to shoehorn a [potentially simple] design into their [convoluted] methodology of choice (likely the only one they bothered learning), and berate without end their peers that do otherwise. They will argue at length without reason or sense about topics in which they hold no expertise. There are a lot of issues that feed these pathologies; computer programming and software engineering are immature fields that have made vast gains in very few years, and no analysis of said gains has been sorted out as a clear winner yet. Often, when programmers are being taught, trite and contorted examples of 'bad' techniques are trotted trotted out as straw men for 'better' techniques to tear down (in some cases, bad and better are accurate, which is why it's really sad that they're demonstrated so poorly); related to this, programmers tend to know just enough about logic, the scientific method and statistics to be dangerous. Finally, the social aspects of programming can encourage the formation of primadonnas and other borderline personality types. For some examples, talk to three C++ programmers: one taught in the early '80s (a more recent coder who is comfortable in C is an accaepable substitute), one taught in the early/mid '90s, and one in the last few years. *vast overgeneralization for the sake of argument (physician heal thyself lol)
|
# ? Aug 27, 2008 20:33 |
|
Anonymous Name posted:Well, you could just write a class that derives from string, which includes your new methods. Even if this was possible, it still wouldn't work cleanly on strings you didn't create.
|
# ? Aug 27, 2008 20:39 |
|
Sounds like it should be easily possible to make foo == any_of(bar, baz, qux) work in C++, if some boost lib does not already.
|
# ? Aug 27, 2008 21:12 |
|
Does the runtime overhead of creating a list and copying elements to it count as a coding horror?
|
# ? Aug 27, 2008 21:45 |
|
No, because if the number of possibilities is small enough that you would otherwise list them in the code then the performance difference is negligible. If the choices are dynamic or enormous you'll probably (hopefully) be using a list operation anyway (albeit not likely an inline one). Only if you are doing many such checks in rapid succession would the difference manifest itself, in which case you would then optimize accordingly. Of course, you shouldn't be optimizing before you need to anyway. So any drawbacks are in most cases purely theoretical.
|
# ? Aug 27, 2008 21:50 |
|
Volte posted:No, because if the number of possibilities is small enough that you would otherwise list them in the code then the performance difference is negligible.
|
# ? Aug 27, 2008 21:56 |
|
Mustach posted:Maybe, but it's an unnecessary source of potential overhead for a negligible readability improvement. I haven't had an opportunity to play around with variadic templates yet in the upcoming C++0x, but I bet something like this could be thrown together: code:
This is also CRAZY and going way out of one's way to implement what amounts to syntactic sugar for a sequence of OR comparisons
|
# ? Aug 27, 2008 22:12 |
|
Flobbster posted:This is also CRAZY and going way out of one's way to implement what amounts to syntactic sugar for a sequence of OR comparisons So basically you are saying it is going to be in the next boost release? Edit: Based on your example, seems to work with gcc 4.3.1: code:
Vanadium fucked around with this message at 22:33 on Aug 27, 2008 |
# ? Aug 27, 2008 22:21 |
|
Vanadium posted:I would still prefer to have the 'a == any_of(b, c, d)" syntax because it is easier to read and probably makes it easy to overload other operators than == as well. I did not bother with the whole "taking template arguments by const reference" thing because you probably need to use boost.call_traits to do it correctly, and I have no idea how to apply that to variadic templates. After thinking about it, 'a == any_of(b, c, d)' might be easier than I first thought. Instead of doing the comparison inside 'any_of' like above, just have it return an instance of a class, say, AnyOfComparator. Then define global operators, template <typename T> bool operator==(const T& lhs, const AnyOfComparator<???>& rhs) and template <typename T> bool operator==(const AnyOfComparator<???>& lhs, const T& rhs) (I can't visualize what the template args for this class would be without playing around with it). These operators would just delegate to a helper function in the comparator class to do the actual comparison. This way, you could extend it to other relops by just overloading them. I may just have to download the latest gcc to play with this, just for my own curiosity. I really just want to see if code like this would get inlined into a similar sequence of comparison/branches that the raw conditional statement would. Things like this is why I can't wait for C++0x to be official. I rarely do any serious C++ programming anymore, but this would be like a fun new Christmas toy for me. vvv Except what we're talking about is syntax like: string s; s.myOwnExtensionFunction();, in which no conversion, implicit or otherwise, will downcast "s" from a string to some arbitrary subclass that I write. Nor should it. Flobbster fucked around with this message at 22:48 on Aug 27, 2008 |
# ? Aug 27, 2008 22:45 |
|
Plorkyeran posted:Even if this was possible, it still wouldn't work cleanly on strings you didn't create.
|
# ? Aug 27, 2008 22:46 |
|
Holy poo poo, I made 'any_of' with variadic templates work. (g++ 4.3.0) I suppose the code below definitely qualifies as a "horror".code:
So the original question was, how efficient is this compared to a chain of if-statements? With -O3 enabled, the compiler does a phenomenal job of inlining this and it turns out it's exactly the same: code:
EDIT: removed an extra not in the != operator Flobbster fucked around with this message at 00:55 on Aug 28, 2008 |
# ? Aug 28, 2008 00:24 |
|
I got pretty much as far, except I did the recursion by composition and not inheritance, but then I tried to wrap boost::call_traits<T>::param_type around everything to avoid needless copying and it all fell apart. Edit: I guess they just gently caress with argument deduction. How does this perfect forwarding thing work again... Any ideas how to make it require less copying? code:
Vanadium fucked around with this message at 00:44 on Aug 28, 2008 |
# ? Aug 28, 2008 00:29 |
|
You guys code too much.
|
# ? Aug 28, 2008 00:57 |
|
Flobbster posted:So the original question was, how efficient is this compared to a chain of if-statements? With -O3 enabled, the compiler does a phenomenal job of inlining this and it turns out it's exactly the same:
|
# ? Aug 28, 2008 01:21 |
|
Vanadium posted:I got pretty much as far, except I did the recursion by composition and not inheritance, but then I tried to wrap boost::call_traits<T>::param_type around everything to avoid needless copying and it all fell apart. It would be impossible to deduce T in an expression like that because you'd be trying to deduce an unknown metafunction's nested type. The purpose of call_traits is for times when T is already known, for instance if T is a template parameter of a class and you wish to use call_traits to determine the parameter type to be used for a member function which takes a T. std::forward in 0x actually uses this behavior to its advantage to make it so that you have to explicitly specify the template instantiation when using it (its parameter type is based on the evaluation of an identity metafunction of the specified type).
|
# ? Aug 28, 2008 01:39 |
|
Scaevolus posted:What about -O2? -O2 comes out the same as -O3, compiled into to an inlined sequence of cmp/branch instructions. Under -O/-O1 though, the class, instantiated object, and method calls remain.
|
# ? Aug 28, 2008 01:44 |
|
At work someone wrote this:code:
|
# ? Aug 28, 2008 02:06 |
|
Lets bring this thread back to easy to understand coding horrors A few days ago I saw return ((x > 0) ? true : false); and there were like 10 of these in a line.
|
# ? Aug 28, 2008 02:44 |
|
Flobbster posted:-O2 comes out the same as -O3, compiled into to an inlined sequence of cmp/branch instructions. Under -O/-O1 though, the class, instantiated object, and method calls remain. I ask because -O3 can cause some weird bugs, so I tend to use -O2.
|
# ? Aug 28, 2008 04:17 |
|
vanjalolz posted:Lets bring this thread back to easy to understand coding horrors I've seen return(((some_bool) ? (true) : (false)));
|
# ? Aug 28, 2008 04:19 |
|
more falafel please posted:I've seen return(((some_bool) ? (true) : (false))); Sometimes you need to make absolutely sure you really mean true.
|
# ? Aug 28, 2008 06:07 |
|
I sawcode:
|
# ? Aug 28, 2008 07:32 |
|
I saw this in some JavaScript yesterday:code:
|
# ? Aug 28, 2008 11:22 |
code:
|
|
# ? Aug 28, 2008 14:27 |
|
RegonaldPointdexter posted:I saw this in some JavaScript yesterday: Maybe the developer is a staunch republican?
|
# ? Aug 28, 2008 14:32 |
|
Just spotted this in the source for a web performance analysis tool:code:
|
# ? Aug 28, 2008 16:49 |
|
RegonaldPointdexter posted:I saw this in some JavaScript yesterday: Just trying to be thread safe!
|
# ? Aug 28, 2008 17:05 |
|
Ugg boots posted:Just trying to be thread safe! Hahahahaha. I had a coworker who used to pepper functions with sleep calls and identical database updates as a poor attempt to work around race conditions. His code looked like the guy from Memento wrote it.
|
# ? Aug 28, 2008 17:13 |
|
Searching for "if 1" in my code base here finds enough results that I'm not sure if it's in the tens of thousands or hundreds of thousands.
|
# ? Aug 28, 2008 18:33 |
|
Mikey-San posted:
Nothing wrong with that (except the doubled ; ). It's future-proofing. If you want to add more tests to that method, you put them between the two return statements. If you left out the first one, whoever extends it next might forget to check if pObj is set. For most things this wouldn't be appropriate, but "if (pObj == NULL)" is an obvious guard and not part of the method's internal logic.
|
# ? Aug 28, 2008 18:43 |
|
JoeNotCharles posted:Nothing wrong with that (except the doubled ; ). It's future-proofing. If you want to add more tests to that method, you put them between the two return statements. If you left out the first one, whoever extends it next might forget to check if pObj is set. Then there should be a comment indicating exactly what you just said
|
# ? Aug 28, 2008 19:21 |
|
Flobbster posted:Then there should be a comment indicating exactly what you just said And when you do that, the code isn't necessary at all. Don't rely on code to convey intent, that's what comments are for. If you're worried about a future traveler not knowing to look for a potential situation and handle it differently, make a note in a comment.
|
# ? Aug 28, 2008 19:54 |
|
RegonaldPointdexter posted:I saw this in some JavaScript yesterday: Looks like the loop would potentially reset change to true if it turned out it did not actually want to exit, and the first "change = false" is just a quick hack to disable the loop entirely.
|
# ? Aug 28, 2008 22:10 |
|
RegonaldPointdexter posted:I saw this in some JavaScript yesterday: I actually did this in an early version of C#, to demonstrate a bug. I don't remember the exact circumstances leading up to this code, but I was having problems with string assignment, and this code actually looped forever: code:
|
# ? Aug 28, 2008 23:19 |
|
Ryouga Inverse posted:I was quite aggravated about this. No exceptions, nothing. I wish I could find the code again.
|
# ? Aug 29, 2008 13:52 |
|
|
# ? May 16, 2024 18:29 |
|
== and != are overloaded to do value comparison for Strings in C#.
|
# ? Aug 29, 2008 14:14 |