Live data from Hacker News

C++11 and Boost - Succinct like Python

fendrich.se

111–120 of 172 posts

Re: C++11 and Boost - Succinct like Python

#111

Is it too late for me to bang my Go drum? http://play.golang.org/p/53jSv32wSF (You can't access the filesystem on the playground, so it doesn't run.) * Look at that error handling. Mmmmhmmm, clear and explicit. If something goes wrong, I'll know about it. * Apart from, of course, errors that I ignore, such as when converting the year from 4 chars to an int (line 54). I don't care if I can't parse that. * Note the dif…

At the end after line 24 do we need another line of code that reads data into the newly created byte array? If so, that says a lot about the readability of the code since I'm not a Go developer...

Re: C++11 and Boost - Succinct like Python

#112

Earlier quoted context omitted.

The extra syntax is not there for nothing. It's adding type information. Thus allowing error checking or dispatching by type or optimisations at compile time. It is a cost in terms of syntax and readability but it's not for nothing. So for correct programs the end result might be the same in terms of values. For buggy code and runtime speed that's not necessarily the case.

This is what caught my eye too as being really ugly and hard to read. const map > TagDataMap { {"title" , make_tuple( 3, 30, stripnulls)}, Why can't the compiler figure out the types involved in this map structure itself? The user-defined functions are declared above, make_tuple will be declared in some library, and the others are string/int literals.

One thing you cannot do is infer `const`ness. This isn't a problem in Hindley-Milner systems because variables are not assignable--they're all `const`, all the time. Literals are inherently immutable but when you assign a C++ variable a literal value, sometimes you want a const variable and sometimes you don't.

I don't think C++ can figure out the map part simply because lots of things could have list initializers that accept lists of 2 item lists. C++'s overloading and implicit conversion conflicts with perfect type inferencing. This is an example of the kind of thing the FQA talks about, where several of C++'s issues collide to produce counter-intuitive behavior.

I do wonder if you could get away with this:

    const map TagDataMap { ...
I don't have access to a C++11 compiler from where I am to find out though. I am particularly unclear on the interaction between `auto` and other aspects of a type declaration--I don't know if you can nest `auto` like this deep inside some other type declaration. I don't see why you couldn't, but wouldn't be shocked either.

Re: C++11 and Boost - Succinct like Python

#113
post #111

Is it too late for me to bang my Go drum? http://play.golang.org/p/53jSv32wSF (You can't access the filesystem on the playground, so it doesn't run.) * Look at that error handling. Mmmmhmmm, clear and explicit. If something goes wrong, I'll know about it. * Apart from, of course, errors that I ignore, such as when converting the year from 4 chars to an int (line 54). I don't care if I can't parse that. * Note the dif…

At the end after line 24 do we need another line of code that reads data into the newly created byte array? If so, that says a lot about the readability of the code since I'm not a Go developer...

I'm not sure what you mean. Could you be more specific?

Line 24 makes a byte slice, line 25 populates it with data read from the file.

Re: C++11 and Boost - Succinct like Python

#114
post #111

Earlier quoted context omitted.

At the end after line 24 do we need another line of code that reads data into the newly created byte array? If so, that says a lot about the readability of the code since I'm not a Go developer...

I'm not sure what you mean. Could you be more specific? Line 24 makes a byte slice, line 25 populates it with data read from the file.

Turns out, my iPad was truncating the whole thing at line 24. Sorry, nevermind!

Re: C++11 and Boost - Succinct like Python

#115

Earlier quoted context omitted.

And this is where I decide the language is too far developed on the wrong foundation. I cannot put up with type systems that don't have complete or near-complete type inference. I don't know why one would start a new project in a language that didn't support Hindley-Milner.

Just to elaborate on what danking00 is saying, the extra syntax in this case is not adding any extra information (to the compiler). The left hand type of the expression can be completely inferred at compile time, in this case. What that required syntax is adding is pain, but no gain (except for imperceptibly faster compile time). In Haskell this would look like: TagDataMap = [ ("title", ((3, 30, stripnulls)), ("artis…

"the extra syntax in this case is not adding any extra information (to the compiler)." This actually isn't true in C++, because there could be many classes in scope that could take a list initializer like this. In Haskell, no literal with [] can "turn into" something besides a list, but that can happen in C++:

    vector items = {1,2,3,4};
    int[] items       = {1,2,3,4};
These have different types, so how would C++ know which one you meant if you instead wrote:

    auto items = {1,2,3,4};
Again, in Haskell this isn't a problem because literals have essentially a single type. (Edge cases around integers and strings notwithstanding).

Edit: Just to clarify, in a Hindley-Milner system you could maybe get away with something like that, but everything you name in an HM system you must use, and that isn't the case in C++:

    void foo() {
      auto items = {1,2,3,4};
      return;
    }
I can then make two classes with list constructors:

    struct FooClass {
      FooClass(std::initializer_list list) {
        cout  list) {
        format_your_hard_disk();
      }
    };
Obviously there are consequences to choosing the right type, but the type of that value never leaks out of the function. Nevertheless, because side-effects can happen anywhere, even in a constructor, C++ cannot optimize that out.

This might be a convoluted example, and it may be flawed, but conjuring up others is not hard and demonstrates that C++ simply cannot ever have true HM type inferencing. Since the "real deal" is not possible, the language is complex and the standard is large, I would not expect to be able to live without annotations in C++-land. (Again, the FQA makes the horror of multiple non-orthogonal solutions to the same problems quite clear).

Re: C++11 and Boost - Succinct like Python

#116
post #97

I've been using both C++11 and Python lately. While the new C++11 features add a lot of value, I still find it frustratingly verbose for some things. For example, finding an element in a collection: std::string type = "foo"; auto it = std::find_if( channel_widgets.begin(), channel_widgets.end(), [type](const std::shared_ptr &w){ return (w->getType() == type); } ); if (it == channel_widgets.end()) { std::cerr target_w…

Um... maybe it's verbose because you're trying to be too clever? :-P How about

    auto it = channel_widgets.begin();
    while (it != channel_widgets.end())
      if (it->getType() == type) goto found;
    // error
    found: // whatever
I kinda hate myself every time I write such for-loop, but it's still more succint than any variant of find_if. Generally, I use "trivial" STL algorithms (find, find_if, for_each, ...) only if I can reuse the functor several times. Otherwise it's not worth the hassle.

PS: you can do it also without goto... use "break" after if, and after while you write

    if (it == channel_widgets.end())
      whatever; // not_found

Re: C++11 and Boost - Succinct like Python

#117

Earlier quoted context omitted.

“C++11 idioms” include a preference for immutability, which leads to natural factorings. You don’t have to worry about things like iterator invalidation that way. #include #include #include #include using namespace std; template void print(const T& v) { copy(begin(v), end(v), ostream_iterator (cout, "\n")); } int main(int argc, char** argv) { vector v{"Hello", "there"}; print(v); } Also, Haskell is only so safe—at wo…

"const" doesn't help you in the presence of aliasing: #include #include template void print(const T& v, U& w) { for (auto ii = v.begin(), ie = v.end(); ii != ie; ++ii) { w.clear(); std::cout v; v.push_back(std::string("Hello")); v.push_back(std::string("there")); print(v, v); return 0; } In general there are lots of ways to get non-const access to const data. You'd need a sophisticated form of whole-program alias ana…

I don't disagree about aliasing, but a print function shouldn't be taking ref to a non-const anything anyways, it should have no need to mutate the vector. You can't clear through a ref to const. Your general point holds but I would say I have probably written/found very few aliasing bugs in C++ over the years, it just doesn't seem to arise often, perhaps your experience differs. Alas there are few ways to prevent dedicated folks from writing really ill-advised code.

Re: C++11 and Boost - Succinct like Python

#118

Earlier quoted context omitted.

“C++11 idioms” include a preference for immutability, which leads to natural factorings. You don’t have to worry about things like iterator invalidation that way. #include #include #include #include using namespace std; template void print(const T& v) { copy(begin(v), end(v), ostream_iterator (cout, "\n")); } int main(int argc, char** argv) { vector v{"Hello", "there"}; print(v); } Also, Haskell is only so safe—at wo…

"const" doesn't help you in the presence of aliasing: #include #include template void print(const T& v, U& w) { for (auto ii = v.begin(), ie = v.end(); ii != ie; ++ii) { w.clear(); std::cout v; v.push_back(std::string("Hello")); v.push_back(std::string("there")); print(v, v); return 0; } In general there are lots of ways to get non-const access to const data. You'd need a sophisticated form of whole-program alias ana…

I see what you’re getting at. Still, if you do the sensible things—immutability, encapsulation of shared state, &c.—then you’re most of the way to safety. I would that C++ made it easier, though; that’s the real issue.

Re: C++11 and Boost - Succinct like Python

#119
post #34

Earlier quoted context omitted.

I call shenanigans. That's true of simple scripts, I'm sure. But you can't seriously claim to me that you can understand decorator idioms, iterables or list comprehensions without a deep understanding of the language. What you say might have been true for Python c. 1998, it certainly isn't true today. Broadly: reading code is just hard. It's much harder than writing code. There are no non-trivial codebases that can b…

Here's an example: A co-worker looked at a function I wrote that converts a table to a tree, and he said to me, "I thought Python was supposed to be readable, but I have no idea what this is doing." See for yourself: https://gist.github.com/3988350

I agree with your co-worker. The indirection is kind of annoying to follow to be completely honest, so if your co-worker isn't proficient in Python I can understand how this would seem impossible to sort out.

Re: C++11 and Boost - Succinct like Python

#120
post #97

I've been using both C++11 and Python lately. While the new C++11 features add a lot of value, I still find it frustratingly verbose for some things. For example, finding an element in a collection: std::string type = "foo"; auto it = std::find_if( channel_widgets.begin(), channel_widgets.end(), [type](const std::shared_ptr &w){ return (w->getType() == type); } ); if (it == channel_widgets.end()) { std::cerr target_w…

Can't comment on C++11 but the Python version is better written as: type = "foo" try: target_widget = (x for x in widgets if x.get_type() == type).next() print "widget found:",target_widget except StopIteration: print "widget not found"

You can also use the `next(x for x in ...)` form where you can even supply a default value.
Post reply on HN