7 ms·
Given that people have asked why not use a statically typed language, seems appropriate to mention that it's possible to write pythonic-looking C++: http://pre
by Cieplak 9y ago
Given that people have asked why not use a statically typed language, seems appropriate to mention that it's possible to write pythonic-looking C++:
http://preshing.com/20141202/cpp-has-become-more-pythonic/ http://preshing.com/20141202/cpp-has-become-more-pythonic/
I have been using C++ a lot lately but really wish there were more tools for reflection at compile time, e.g., ability to iterate over all the members of a class. Other than that, I'm really loving C++17's auto template parameters and type deduction capabilities, plus code that's 200x faster at runtime than most interpreted languages. I've found autocompletion in CLion to be slightly better than autocompletion PyCharm, but not quite as good as IPython or IntelliJ with Java.
- aub3bhat 9y agoPlease show me C++ equivalent of sorted([(k.weight, k.name) for k in somelist], reverse=True)
- nickelbox 9y agoYou could implement the following with a decent bit of work (declaring k and reversed to be variables of special, hand-written/macro-generated types with overloaded operator, and operator=). sorted( (k.weight, k.name).for_(k).in(somelist), reverse=true)); You would never be able to get that past code review, however.
- joshuamorton 9y agoSure, but at that point you've just reimplemented python in macros ;) The other thing to note is that sorted([(k.weight, k.name) for k in somelist], reverse=True) is essentially already typechecked: def biggest_ks(ks: K): return sorted([(k.weight, k.name) for k in ks], reverse=True) The above code now has all the same type guarantees as your c++, actually maybe more since the macros you use are going to be...uhhh, mysterious.
- nickelbox 9y agoThe macro would only be used to generate k for convenience. It could be all implemented in straight, macro-less C++98 in O(minutes). My point was just that you can implement almost whatever you want (even without macros, they'll just expand the design space).
- joshuamorton 9y agoI don't see how you could implement the (k.attr).for_(k) part. That's essentially an assignment, a macro could maybe convert it to a lambda, but I don't see how it would be done macro-free.
- Wehrdo 9y agoI'll bite. std::vector<std::pair<float, std::string>> in_order; std::transform(data.begin(), data.end(), std::back_inserter(in_order), [](auto& item) {return std::make_pair(item.weight, item.name);}); std::sort(in_order.begin(), in_order.end(), std::greater<>()); While I won't claim it to be as elegant as Python, it doesn't seem too ugly. Does anybody have an idea about how `auto` could be utilized to avoid the long vector<pair...> type declaration? For the adventurous: https://repl.it/repls/RepentantGentleKudu https://repl.it/repls/RepentantGentleKudu
- jdashg 9y agoTemplates, auto, and type toys can give you some serious build-your-own syntactic sugar: https://repl.it/repls/PleasingLovingQueenslandheeler https://repl.it/repls/PleasingLovingQueenslandheeler Pulling things out of tuples isn't great, though.
- deathanatos 9y agoNote: my C++ is extremely rusty. Right now, I think that's approximately, vector<tuple<int, string>> output; transform( somelist.begin(), somelist.end(), back_inserter(output), [](const auto &f) { return make_tuple(f.weight, f.name); } ); sort(output.rbegin(), output.rend()); Ranges, I believe, would reduce this a lot, possibly even to a single line. If I am reading the docs on it correctly, something like, vector<auto>(somelist | view::transform([](const auto &f) { return make_tuple(f.weight, f.name); })) | action::sort; I think. Two notes, however: 1. I feel like most of the desire for a static language is to know what type something is. Is C++ exactly as brief as Python? No, as I think you've demonstrated. But I think you're a lot more likely to know the type of something. Rarely do I think I find that Python has annotations, and annotations can be wrong. 2. C++ is, in general, I feel, much more explicit about where copies occur. I elided one of the copies in your example, opting instead for an in-place sort (but this is trivial to fix in the Python).
- mehrdadn 9y ago> vector<auto> Really? O.o How could this possibly work?
- deathanatos 9y agoOh, that was probably a typo (it was late); replace that with a concrete type.
- lmm 9y ago> 1. I feel like most of the desire for a static language is to know what type something is. Is C++ exactly as brief as Python? No, as I think you've demonstrated. But I think you're a lot more likely to know the type of something. Sure, but you don't have to choose between them, there are plenty of languages where you can have both Pythonic terseness and full type safety. E.g. Scala: (for {k <- somelist} yield (k.weight, k.name)).sorted.reverse Many other strongly typed (ML-like) functional languages are similar.
- mehrdadn 9y agoHere (http://rextester.com/QUIK26485 http://rextester.com/QUIK26485): somelist | transformed([](auto &&k) { return make_pair(k.weight, k.name); }) | sorted | reversed;
- tigershark 9y agoNo idea about C++ but in C# seems quite more readable (and flexible) someList.OrderByDescending(x => x.weight).ThenByDescending(x => x.Name); It's quite similar to expressing the concept in English, certainly more than using list comprehension in Python. And how would you order it in Python by ascending on the first field and descending on the second using list comprehension?
- joshuamorton 9y agoThat's not the same thing, you've sorted a list of objects, we're looking for a list of tuples of `weight, name`) In answer to your question though, sorted(((k.weight, k.name) for k in some_list), key=lambda x: (-x[0], x[1]), reverse=True) appears to work. This does use a non-obvious trick, but being more explicit is a smidge difficult, since the key function is called only n times, as opposed to O(nlogn) in the C# example. Alternatively, you can use sorted(sorted(((k.weight, k.name) for k in some_list), key=lambda x: x[1], reverse=True), key=x[0]) Which is more like the original example, and if you're doing it in place, you get outs = [k.weight, k.name) for k in some_list] outs.sort(key=lambda x: x[1], reverse=True) outs.sort(key=lambda x: x[0]) Python's builtin sort is timsort, so despite sorting the list twice, this will still run in approximately NlogN comparisons, not 2NlogN. You could also manually define a custom comparator, ie lambda s, o: (s[0] > o[0] * 10 + s[1] < o[1]) and pass it to `functools.cmp_to_key`.
- Cieplak 9y agoEasy: std::vector<P> people = { P{"jane", 47}, P{"mary", 71}, P{"john", 65} }; ranges::sort(people, [](auto& x, auto& y){ return x.weight > y.weight; }); Compile this gist with `c++ -std=c++1z -I range-v3/include`: https://gist.github.com/cieplak/dcd587c67d989768900e4110e776842c https://gist.github.com/cieplak/dcd587c67d989768900e4110e776...
- joshuamorton 9y agoWhat if two weights are equal, the python code will also sort by name as well ;)
- Waterluvian 9y agoThat's kind of missing the point though. Languages are tools for different purposes. You may love chizels and lathes and saws but you wouldn't build a suspension bridge with wood. Just like I wouldn't build a cabinet with cement, steel, and rebar. Picking C++ over Python is like picking woodworking over metalworking. Python being slow is never an issue unless someone is insisting on using the wrong tool for the job.
- mehrdadn 9y ago> Python being slow is never an issue unless someone is insisting on using the wrong tool for the job. So you think, for example, Numba (and everything that uses it) is misguided?
- semi-extrinsic 9y agoNumba is like laminating wood to build structural beams - it will get you close to the performance of metal, for some applications, if you can accept the weight increase etc. Numba could be seen as misguided from some points of view. E.g. when using Python for high performance scientific computing, you will typically be writing your computational kernels, I/O etc. in some compiled, superfast language (C/Fortran/CUDA/whatnot) and all the input handling/case setup/etc. in Python. If 1% of your compute time is spent Python and 99% is carefully optimized C, Numba is obviously pointless. But that's for one application. Python is used for so many different things that you can't make blanket statements like this.
- lmm 9y agoWhy C++ though? In e.g. Scala you have much more pythonlike code than even modern C++, full type safety, much better performance than Python, strong IDE support, and the ability to do the things you would want compile-time reflection for (e.g. typeclass derivation and similar use cases for "iterate over all the members of a class") in a completely type-safe way without needing dangerously flexible macros or code generation. Other ML-family languages will be similar.