4 ms·
It's certainly true that dynamic, high-level languages save you from having to worry about ownership-semantics, but you still care a lot about the return-type (
by dilap 15y ago
It's certainly true that dynamic, high-level languages save you from having to worry about ownership-semantics, but you still care a lot about the return-type (e.g., am I getting back an int, a str, a set, a dict, a simple list, a generator, &c &c &c)!
You care about this; either it must be obvious (e.g., fairly obvious with a function like len()), or you have to look it up in the documentation or comments of the function. If it's not documented, you have to try to figure it out from the function body, which is often non-trivial. This is why you'll typically see what amounts informal type annotations in the comments of functions of mature code.
Despite all this, many people feel that the flexibility of not having to specify types is a net-win.
C++ "auto" adds some of the convenience, but at a much lower cost in readibility, since when you see something like
auto x = foo.gimmeBar();
you can find out the type of x immediately just by looking at the definition of gimmeBar() (with IDE support, this could even be zero-effort (i.e., it could show a little grey popup bubble with the deduced type); even with something old-fashioned like emacs+ctags, it's just a hop-skip-and-a-jump away).
*
By the way, regarding ownership-semantics, it's true they could be a massive PITA pre-C++11, and (sort of analogously to the what-are-the-types-in-a-dynamic-language situation) you'd often have to fall back to relying on comments to know what was going on. If they're weren't comments and you were getting back a raw pointer, well...that could be rough.
This is a problem that can be fixed with library support (for smart pointers) and disciplined coding -- i.e., using the smart pointers. For a good example of this working really well in practice, see Objective-C.
C++11 helps because it gives us built-in library support, and will hopefully provide the community motivation for the convention/discipline of actually using the libs.
(This pointer-ownership stuff is pretty much orthogonal to auto, though, IMO.)
- rayiner 15y ago> but you still care a lot about the return-type (e.g., am I getting back an int, a str, a set, a dict, a simple list, a generator, You do, but convention gives you a lot more context. If, by the nature of the function, I know I'm expecting a list, I know I'm going to get a list. I'm not going to get a pointer to a list versus a reference to a list versus a smart pointer to a list versus an iterator pointing into a list, etc. Compare the C++ STL to Common Lisp's standard library. A given STL function might take or return an iterator, an iterator pointing to a pair, a pointer, or a value. In the Common Lisp standard library, something is going to return either a value or a collection and its obvious from context which it is going to do.
- dilap 15y agoI think you're sugar-coating a bit -- at least for Python, any function that might return a list could also reasonably return a generator, and might even return a tuple or a set. I can't speak to common lisp, but I have a fair amount of experience with Python and with the STL (and other stuff, but those two most of all), and I've found the STL to be one of best-designed, most predictable, and easy to use libraries out there. YMMV, of course. (BTW, an iterator is just a generalization of the concept of a pointer; i.e., a pointer is an iterator.)
- Someone 15y ago"It's certainly true that dynamic, high-level languages save you from having to worry about ownership-semantics" What languages are you thinking about? In most languages I can think of as being "dynamic, high-level", state is mutable. So, if a method on an object returns a collection, and the caller wants to keep the result around, the programmer will have to somehow know whether the collection that the method returned was freshly allocated or internal to the object, whether it is modifiable, how long the content of the collection is guaranteed to be stay constant (e.g: what happens when I append to a list from a loop that iterates over it?), etc. Similarly, if one passes an object to say a constructor, one should know whether the constructed object holds a reference to that object, thus sort-of claiming ownership. It is true, though, that whenever I think about such issues, I am amazed that these things so rarely lead to problems. Apparently, all programmers share a single mental model for the 'natural' ownership policies.