5 ms·
I'm not sure I follow. Assuming that lambdas can indeed be optimized/inlined, shouldn't the same performance gain exist with a single error-handling std::funct
by makecheck 9y ago
I'm not sure I follow. Assuming that lambdas can indeed be optimized/inlined, shouldn't the same performance gain exist with a single error-handling std::function (lambda) parameter in an otherwise-normal function? In other words, avoid wrapping the entire return value in a special type, avoid weird calling conventions, and simply supply a block to invoke if/when there is an error (and if there is no error, do nothing different).
- AstralStorm 9y agoIndeed, and it is generally cleaner. The functional equivalent is continuation passing style. However, it just pushes the problem one level up, so is not a full solution. It works well when combined with the some usual techniques like the error singletons and exceptions. You can also set an error code you need by capturing the result variable. Or just do what you need in the handler itself. Returning a special type is about as annoying as returning and handling an error code.
- m1el 9y agoOh, there's many problems with suggested approach. - Callback-oriented programming is its own deep can of worms. What do you want to inline where? In case of leftMap, it's easy for a compiler to inline flatMap, because it's small. What if you're providing a lambda to a huge function? What about variable captures? Really, we've been there with JavaScript. - It will either incur a yuuge runtime overhead or will require a new calling convention. - What if you want to transform your data multiple times? Will you use nested lambdas? IMO, using sum types is the best solution to this problem. Sum types are not "weird special type", they don't require "weird calling convention", C++ is weird for NOT supporting them.
- AstralStorm 9y agoWe have also been there in a variety of functional languages and no problems there. What runtime overhead, a function call? Pointer dereference? Even template magic on the error monad type won't save you from that one. The problem is shifted to the dereference. There you get either to handle an exception or error code, or explicitly check the state of the object. Nested lambdas do work reasonably well. But remember, were generally talking about error handling, not a callback that is supposed to run big transforms.
- hellofunk 9y agostd::function and lambdas are two very different things. std::function can store a lambda, but it is a memory-allocating library class, while a lambda is a language-level construct. Very important to understand the distinction between these two.
- AstralStorm 9y agoThere are improved template magic versions of std::function that do not inhibit inlining for stateless lambdas passed directly thanks to additional magic. At worst the overhead is a function call anyway and inhibition of inlining in the error path. Generally nothing to worry about.
- hellofunk 9y ago> There are improved template magic versions of std::function But not in the standard library. Of course, in C++, you can do anything if you venture outside the standard.
- slavik81 9y agoNo, performance would probably be worse. For one, std::function is not just for lambdas. It uses type-erasure and dynamic allocation to hold any sort of callable object/function. It's a generic type with a complex implementation and I wouldn't assume it would be optimized away. Additionally, when using Either the lambdas are in the caller and are invoked almost immediately by map. The scope is small and they do not enter into any other compilation unit. If you pass them into the called function, the compiler is only going to be able to optimize them if the called function can be inlined. Even then, the optimizer will have to be smarter, because the error handler will travel through a much larger scope and a type conversion.
- AstralStorm 9y agoEither inserts a conditional and union dereference. Unions are pretty terrible on their own to optimize, even with strict aliasing. The pointer dereference and call overhead is not big and error handling code is supposed to be cold anyway.