6 ms·
I made it a goal of mine about 10 years ago to avoid explicit for-loops. It turns out using declarative style makes things more readable and safer and better op
by goalieca 8y ago
I made it a goal of mine about 10 years ago to avoid explicit for-loops. It turns out using declarative style makes things more readable and safer and better optimized by the compiler. I can usually tell the purpose of the loop by just reading the function name (map, filter, ..) and the lambda. Sometimes parallel comes for free. Plus, all those off by one errors, iterator errors from erasing elements, etc. are all eliminated :)
- sametmax 8y agoFor loop don't have to mean counters. We had automated for loops for years, generators and comprehensions that are basically map/filter integrated in syntax. E.g you have map and filter in python but they are rarely used for that reason. No need to be dogmatic.
- jstimpfle 8y ago> It turns out using declarative style makes things more readable and safer and better optimized by the compiler. I don't think most of my loops are straightforward maps or filters of a single iterable. I need to reference various data sources and execute actions with side-effects. To do that using a functional framework, something like Haskell's mapM ("monadic map") is required. But that brings quite some mental overhead and I find it way too constraining for the typical case. > more readable and safer and better optimized by the compiler. I doubt these are in general qualities of non-builtin constructs vs builtin ones. But yes, too much builtin and non-orthogonal functionality leads to detrimental complexity. In any case I don't think it matters much to most compilers whether you write a loop using syntactic sugar or as labels and jumps.
- goalieca 8y agoI haven’t really encountered a loop that there isn’t a function for. There ought to be some exhaustive list of all the different kinds of loops in computer science textbook. But Most of what you need is in Zip, fold, map, reduce, filter, find, sort, reverse, transpose, permute, concat, any, all, max, min, cycle, take, .. I’ve periodically done microbenchmarks of inner loops over the years and the various gcc outputs of the c++ loop functions are always performing slightly better than if I hand rolled. Perhaps with gcc7 or clang this is different.
- jstimpfle 8y ago> Zip, fold, map, reduce, filter, sort, reverse, transpose, permute, concat, any, all, max, min, cycle, take, .. Cool, so if that's all we should just use those. But wait, what about those dozens of megabytes of data, should we really zip/transpose/concat them? We should use non-strict evaluation then...
- tuukkah 8y agoYou can use lazy lists / streams even with strict evaluation, you just have to be explicit.
- jstimpfle 8y agoPoint being, I'd rather not have this complexity. Do you mean to explicitly take each next value from the stream? And then possibly throwing all this "lazy" work away? Or memoizing the work and writing extra code that checks if the work was already done when the data is accessed? And then probably forgetting to get rid of the data when it's no longer needed? No thanks, that's even worse. It's honest, but that doesn't make it a good idea. I like to do one thing at a time, not jump around like a wild horse. Turns out optimizing for not jumping around too much also makes programs simpler overall. I've recently cleaned up some code of this kind. Defines objects with unsuitable lifetime and tries to be smart about reusing work instead of planning out in which order to do things in the first place. While the actual task was not difficult, the code was incomprehensible, to state it in a diplomatic way.