Quote:
Originally Posted by
citizen
Are you suggesting that a generic algorithm is never suited to a task? At face value, this statement can be too absurd. For example, what if you had a list of some objects, and you had to copy the list into a better data structure for other processing (such as searching), like a tree?
No, no. OK, I'm trying to set things right here.
Algorithms:
- Good in sense that they can perform tasks so that you don't need to rewrite code that does the same thing on multiple objects.
- Error prone in sense that it may require a couple of arguments and they must be right.
- Lessens readability because an algorithm is not an easy thing to some and especially those who do not know the algorithm or what it does.
Free functions:
- Good in sense that they are not limited to one object - they can work with multiple string classes, say, given they have the right interface.
- Increase encapsulation.
- More readable than algorithms.
- Bad in that this is the "the classes themselves does not do the work" analogy (I'll explain that later).
Member functions:
- The objects themselves perform the work.
- Most readable of all three.
And the "the class does all the work" or not... if you call a free function, then the function is doing the work. If you call a member function, the class does the work.
It's not about where the code goes or how it works, but about who you are assigning to make it work. The function you're calling. It doesn't matter if the member function to_lower calls the free to_lower--that's implementation issues which are always hidden from the outside.
I mean, just because you're an expert in some profession doesn't mean you can't hire someone to help. So whatever happens after you call a member function doesn't matter the slightest. The implementation in a class is hidden to the outside - as it should be. We don't know what happens inside nor should we care. That's the class's out business.
Quote:
You state that you prefer a logical breakdown:
methods -> free functions -> generic algorithms
How aggressive are you in persuing your best approach? Are you rebuilding the STL with algorithms as classes?
Am I? Yes and no, to an extent. No, I'm not rebuilding any STL classes per se, but I am building a big framework myself. Mostly I've been reorganizing and encapsulating C stuff (like Windows API), but I'm also planning on writing my own string class because the existing ones are lacking.
Quote:
Seriously, like:
binary_search< item, value > test( ).go( );
I don't know if I would do that. It's constructing the item. That's the work of the constructor, is it not?
Quote:
Would you recommend this? Perhaps I'm just a bit comfortable with what I know but I don't see the same glaring error that you do, exactly. I point out that foo.bar() is essentially the same as bar( foo ); the difference is in syntactic sugars. bar is not necessarily a free function, at least, if you've ever used python. I don't think there is a valid argument there and if we are to assume that your whole critiscism of the STL is based on syntactic sugar, than you're a silly goose. :p Programming is much more than syntax.
It's not about the syntactical that I'm hung over, but it's more of the idea who does the work. The free function or the class? If it's a class that you're working with, then the class should do the work, if possible. Because we're breaking the concept that a class is an object with free functions. In that I mean, the object should do all the work - you shouldn't tell someone else to tell the object to do it.
And the object itself can do the things better than a free function because it has access to its private members and internal workings. So the object can always be more efficient, at the cost of some encapsulation.
Quote:
Originally Posted by
phantomotap
Nonsense. You can say a 'to_upper' method won't need to be changed. That isn't the point of making and using freestanding functions over methods. One goal is to insulate yourself from changes. That changes may not occur is irrelevant; what if change happens? (Obviously, a no parameter 'to_upper' would likely never change in interface. Changes in a mechanic however...)
Not nonsense. What the free function does is just take an extra argument and call the public interfaces. I could just as well create a member function that takes no extra arguments and uses public interfaces.
This completely eliminates the advantage of making it freestanding for this argument.
However, they are good for other things - especially not requiring to implement the same methods into all classes since a free function can work over multiple classes.
(But then again, you could just copy the member functions over to the other classes. If they use public interfaces, no changes needs to be made. This is, of course, assuming that the member function and the free function uses the same functions, in which case both would work or both would fail.)
Quote:
Nonsense. If there exists a correct, complete implementation for some mechanic then the public method and freestanding function must be same--or one is lacking in correctness or completeness. If the freestanding function, complete and correct as above, can exist then the only thing you might possibly gain compared with a method is typing a few less characters.
Indeed, but the object would do the work, as it should.
Quote:
With your logic, you must inherit from 'cat' to introduce a new type 'cat_what_can_sing'. Now, obviously, again with your logic, 'cat_what_can_sing' can't just provide an additional interface for implementing freestanding 'sing_song' functions; instead, you must introduce yet another typed named 'cat_what_can_sing_music_of_the_night' providing the method 'sing_music_of_the_night' that 'cat_what_can_sing::sing' might call. All I can say is: Gods help you if you want the thing to sing more than one song. >_<
So sue me. I like it better with objects. Within reasonable limits, I will reinvent the wheel.
Quote:
False. I have no idea why you responded with this. As has been said, if, for whatever reason, you decide to change the interface of your method, I must change the target source. I can keep the target source unchanged if I write it with a freestanding function to begin with precisely because I can control the freestanding function. They are obviously very different.
Untrue. See above.
Quote:
Nonsense. They, that is to say the use, are not more error prone than any alternative. (A large number of "one trick ponies" is not an alternative to a generic function, method or freestanding.)
How is algorithms not error prone? Unless you know how to use them, which is harder than normal member function OR free functions, they WILL go wrong.
Quote:
That the object isn't "doing the work" is a tremendously odd statement. (If the method only serves to call other methods or freestanding functions the different is entirely syntactical.) With "harder to read" being subjective entirely.
Anyway, I have to ask: In my library there are no freestanding functions, only objects--"functiods"--that must be instantiated; who/what "does the work"? I mean, my variant of 'std::copy' creates an instance and invokes my variant of 'std::assign' repeatedly which in turn may call a virtual copy constructor of some object, for example. (A long story involving disheartening tales of caching, exception requirements, threading goals, and the all important interface dreams. My 'std::vector', for example, "behaves" "correctly" for 'std::vector<some_type &>' in the face of threading, exceptions, and manages to be pretty fast all the same.)
I addressed that above. Have a read.