5 ms·
How can any sane person think this is a reasonable way to program? While perhaps stated with slight hyperbole, this is actually a serious question. I don't se
by pcmonk 12y ago
How can any sane person think this is a reasonable way to program?
While perhaps stated with slight hyperbole, this is actually a serious question. I don't see how, for example, these pipable functions give any additional real expressive power, and they seem incredibly hacky in how you have to build them. I simply don't understand why anyone would use this kind of thing. C makes sense; I can see an argument for C++03; this is madness.
- pfultz2 12y agoWell this can help when you have many nested functions that are chained together, for example, like this: auto r = select(where(numbers, [](int x) { return x > 2; }), [](int x) { return x * x; }); Because of nesting this can be hard to read(and even write). If we can make the function pipable, the above can be written like this: auto r = numbers | where([](int x) { return x > 2; }) | select([](int x) { return x * x; }); Which it is easier to see what this does. So this blogpost goes over how to implement an utility that will take care of the boilerplate involved in writing a function that can be pipable. It does take advantage of a lot of C++14 features to implement this such as such as vardiac templates, rvalue reference, generic lambdas, and auto type deduction, but those feature actually make it simpler. I have in the past implemented something similar for C++03 and the code looks awful with way too much noise. > this is madness. Why do you consider this madness? Maybe my mind has already been warped by C++.
- grundprinzip 12y agoI really like your above example. For people coming from Ruby on Rails or Python Django, such a notation makes it simple to understand what the code will do, even without knowing how to implement it. Thanks
- pcmonk 12y agoTo me, the first is much easier to read, but perhaps my mind has been warped by functional programming languages. At any rate, the thing that's strange about it is how verbose and hackish everything is. It's obvious the language wasn't designed to do anything like this, so the only way you can incorporate features like this is with unnecessarily obtuse and complex blocks of code.
- pfultz2 12y ago> To me, the first is much easier to read, but perhaps my mind has been warped by functional programming languages. Actually, pipable is very similiar to haskell's `$` function. So a similiar thing is done to improve readability of chaining functions in functional languages as well. > At any rate, the thing that's strange about it is how verbose and hackish everything is. It's obvious the language wasn't designed to do anything like this, so the only way you can incorporate features like this is with unnecessarily obtuse and complex blocks of code. How is the code obtuse and complex? I am using fairly straightforward techniques. I understand that I am working around the lack of perfect capturing for lambdas, but it is not complicated or clever the workaround.
- jschwartzi 12y agoThe first one looks like you're chaining functions together, while the second one looks like you're taking multiple bitwise or operations over the result of each function. I think it's fascinating to see how the language can be extended. On the other hand I would not want to be the poor bastard stuck maintaining either construct after discovering some compiler edge case. If I've learned anything it's that just because you can do something doesn't mean you should. The issue with extending operators in this fashion is that you're violating the principle of least surprise. | is an operator that should only really do exactly what it always does--bitwise or. If composition of functions is fundamentally analogous to taking the bitwise or of two values then I would concede that your second syntax is a bit clearer. Personally I feel that this is not the case.
- pfultz2 12y ago> The issue with extending operators in this fashion is that you're violating the principle of least surprise. It is really common for the `|` operator to be used for piping functions together. There are several libraries that support it: [Boost.Range](http://www.boost.org/doc/libs/1_56_0/libs/range/doc/html/index.html http://www.boost.org/doc/libs/1_56_0/libs/range/doc/html/ind...), [PStade Oven](http://p-stade.sourceforge.net/oven/doc/html/index.html http://p-stade.sourceforge.net/oven/doc/html/index.html), [Linq](http://pfultz2.github.io/Linq/ http://pfultz2.github.io/Linq/), and [Streams](http://jscheiny.github.io/Streams/ http://jscheiny.github.io/Streams/). Plus, its even being proposed as part of the ranges library in future C++: https://github.com/ericniebler/range-v3/blob/master/doc/D4128.md https://github.com/ericniebler/range-v3/blob/master/doc/D412... So just as the bit shift operators in C++ also have the meaning of streaming in and out, the bitwise or also has the meaning of pipe, so this is should not at all be a suprise.
- jschwartzi 12y agoInteresting. I was not aware of this, so thank you.
- nawitus 12y agoI'd say JavaScript-style chaining is more (or atleast as) readable as that. E.g. numbers.where().select();
- vinkelhake 12y agoA more reasonable example of this kind of function composition would be the range adaptors from boost.range. http://www.boost.org/doc/libs/1_56_0/libs/range/doc/html/range/reference/adaptors/introduction.html http://www.boost.org/doc/libs/1_56_0/libs/range/doc/html/ran...
- hendzen 12y agoThis kind of complexity is only really needed for library writers... e.g. someone writing a package for Boost. Your run-of-the mill application code in C++ will probably stay away from this kind of wizardry.