Live data from Hacker News

C++11 and Boost - Succinct like Python

fendrich.se

101–110 of 172 posts

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

#101
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 difference (lines 54, 56) between parsing the track (which is a byte), and the year, written as 4 digits. The byte can just be cast to an int, the string needs to be parsed by the strconv package.

* I have a little bit of defensive programming in the form of a panic(), which would tell me if something that I thought was impossible has happened.

* defer on line 19 makes sure the file closes if we managed to open it, regardless of when we return.

* type casts are explicit, even from int to int64 (line 20)

* I don't specify which interfaces a type implements, the compiler handles that all for me.

* Parse() returns map[string]interface{}, which allows me to store anything (in this case just ints and strings) in a key-value store.

* A type-safe printf! "%v" (line 67) uses reflection to look at the type of the argument and deduce the natural format. So I can pass it an int or a string and it works :)

* On line 86 I pass this weird new type to a printf function and it goes ahead and uses the String() method that we defined. If we hadn't defined that we'd get a printout of the type, which in this case would be the 128 bytes we read.

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

#102
post #34
post #27

It's succint, all right (well, sort of). But Python's major strength is readability, even more than coinciseness, or better, to provide both at the same time. C was born as a terse language, sacrificing readability for coinciseness (the original examples in K&R are incredibly succint, almost elegant, but far from readable). I can't see many improvements in C++ (a language that arguably has worse coinciseness than C,…

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…

Absolutely agreed: to me, Python is a local maximum rather early on the readability vs. complexity graph. I think as complexity increases, an explicitly-typed language becomes much more understandable because local type annotations require less context switching to reason about when compared to an implicit language.

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

#103
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…

boost::range can makes a bit less verbose:

    std::string type("foo");
    auto range = channel_widgets | filter([type](const std::shared_ptr &w) { 
                                              return w->getType() == type;
                                          });
    if (range) {
        std::string target_widget = *range.begin();
        std::cout 

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

#104

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.

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)),
          ("artist", ((33, 30, stripnulls)),
          ...
Haskell will correctly infer that TagDataMap :: [(String, (Integer, Integer, String -> String)].

Ok, technically this is an associative list, not a Python dictionary, but it is a map and can be accessed like one. Hell, most people use dictionaries with less than 10 items, which are much slower than arrays most of the time

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

#105

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.

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.

Even in Hindley-Miller type systems it is considered good practice to add types as documentation to top-level constructs (see Haskell). In Python it is also considered good practice to add argument and return type info in the doc string. In a dynamic language you would also have to add a unit test or two for cases for some of the things that the compiler can catch for you.

Looking at the complete picture makes a language with local type inference (like C++11) more or less as verbose as one with complete type inference.

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

#106
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…

"I may be missing out on some C++11 for doing this better"

First write a function that searches an entire range with a predicate, so you don't have to write the .begin() and .end() anymore. That's just applying DRY. Then you could write a helper struct that wraps an iterator and the end iterator of the range searched, so you can give it an operator bool (). Return this struct from your find function and you get code like this:

  auto result = my::find_if( channel_widgets, predicate );
  if( result )
    do_stuf_with_result( result.it );
  else
    error();

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

#107
post #8

Earlier quoted context omitted.

I wrote this post. The program is I/O-bound, so the only speed improvement comes from not having to start up the Python interpreter. If the task was CPU bound, you would get a great performance boost (sometimes 100x over CPython), but that is well known. There can be other reasons than performance for writing in C++. Used well, the strong static type system can catch many bugs. I suspect (but I cannot prove) that it…

It won't be as good as Haskell for memory safety. For example, this program, using only C++11 idioms, crashes: #include #include int main() { std::vector v; v.push_back(std::string("Hello")); v.push_back(std::string("there")); for (auto ii = v.begin(), ie = v.end(); ii != ie; ++ii) { v.clear(); std::cout Preventing this sort of thing requires strong guarantees about aliasing (to ensure that "v" can't alias the vector…

That does not look like C++11. You don't use initializer lists. You don't use new-style for-loops. I'll give you that those don't add much to safety, though. A functional style with Boost ranges, adapters and algorithms do, however. I clearly write in the post that you shouldn't use for-loops. Use ranges and pipes.

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

#108
post #91

This is neat and C++11 is pretty exciting, but one thing that C++ doesn't need is the further propagation of tuples into non-generic code. Requiring make_tuple instead of allowing shorthand was the right decision. Tuples in python are a reasonable tradeoff between not wanting to declare anything and the hassle of anonymous structure. This doesn't apply C++ where the equivalent is the POD struct: //In the olden days w…

Yes, of course a POD is better, but that would be cheating, since this is supposed to show that you can do the Python stuff, including tuples and tuple deconstruction, just like in the linked Python original.

Perhaps I should have mentioned that, though.

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

#109
post #13

The changes to C++ are too little, too late. These changes should have been made years ago, and C++ has lost momentum and credibility. Is anyone comparing Python to c++? nope, only the other way around.

Too little, too late? There's no zero sum game here. Perhaps you're conflating Internet-popular (which doesn't mean shit) with useful?

Internet popular means libraries on github and good tutorials, means useful.

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

#110
post #107

Earlier quoted context omitted.

It won't be as good as Haskell for memory safety. For example, this program, using only C++11 idioms, crashes: #include #include int main() { std::vector v; v.push_back(std::string("Hello")); v.push_back(std::string("there")); for (auto ii = v.begin(), ie = v.end(); ii != ie; ++ii) { v.clear(); std::cout Preventing this sort of thing requires strong guarantees about aliasing (to ensure that "v" can't alias the vector…

That does not look like C++11. You don't use initializer lists. You don't use new-style for-loops. I'll give you that those don't add much to safety, though. A functional style with Boost ranges, adapters and algorithms do, however. I clearly write in the post that you shouldn't use for-loops. Use ranges and pipes.

I don't see how Boost algorithms provide the aliasing guarantees you need to avoid invalidating iterators. It's a very difficult problem. Even if you use a library to pipe instances of your custom string class to cout and you trust that library, the method or function that sends your custom string class to cout could perform arbitrary mutations, which would invalidate the iterator.

For example:

    #include 
    #include 
    #include 
    #include 

    class mystring {
    public:
        std::string m_s;
        mystring(const std::string &s) : m_s(s) {}
    };

    std::vector v;

    void operator(std::cout, "\n"));
        return 0;
    }
Post reply on HN