3 ms·
What makes lazyness difficult for me isn't the mental model, it's the fact that when you get an error, the error is far from its call-site, and the truly helpfu
by PopsiclePete 8y ago
What makes lazyness difficult for me isn't the mental model, it's the fact that when you get an error, the error is far from its call-site, and the truly helpful information that I could've had in the stack trace is gone. I'm looking at the error - but which lazy operation in the sequence caused it? Where? When?
I by no means claim to be a Clojure guru, and I'm sure people who have more experience can just look at it and know, but for me, the time lost to pinpoint that error is too much. And when I have something in production, I need to be able to pinpoint the error in minutes and deploy the fix quickly.
>Either way, making eager evaluation the default is a form of premature optimization.
I don't see how that's true - it's the default way CPU's operate on the silicon level. Millions upon millions of lines of non-lazy code have been written and put into production and they perform real, valuable work.
I'm not against lazy evaluation or against Clojure - all I'm saying is - it's hard for me to reason about it when things go wrong.
If they don't go wrong (almost never for me) - it truly is a thing of beauty.
- nybble41 8y ago> when you get an error, the error is far from its call-site, and the truly helpful information that I could've had in the stack trace is gone I'll grant you that one. Languages with non-strict evaluation (or tail calls, or inlining, or extensive use of macros) rarely have useful stack traces. You can see what was being evaluated but not necessarily how it got there. The ability to leverage the stack as a debugging aid is a feature of certain runtime conventions more applicable to imperative programming paradigms than to functional ones. In modern Haskell there is a way for functions to receive extra information about their call site as an implicit parameter, which helps with error reporting. I'm not sure what tools Clojure might offer along these lines. I will point out that tracing the source of incorrect or corrupted data is no less of a problem for programs written in strict, imperative languages. Functional programming adds to this by emphasising functions as a form of data, and non-strict evaluation carries that still further by treating all data as closures. On the other hand, strong static typing limits the kinds of runtime errors which lay hidden within those closures to a manageable set (assuming a pure functional language like Haskell). >> Either way, making eager evaluation the default is a form of premature optimization. > I don't see how that's true - it's the default way CPU's operate on the silicon level. That's not really true, given the existence of speculative and out-of-order execution. In any case, how the CPU operates at the silicon level has very little to do with whether a high-level language optimization is premature. > Millions upon millions of lines of non-lazy code have been written and put into production and they perform real, valuable work. I'm not disputing that, but it's beside the point. Code which has been prematurely optimized can still "perform real, valuable work". It just may take a bit longer to run or require more resources to develop (for example by being harder to reuse, requiring more code to be written to accomplish the same result).