Live data from Hacker News

Loopless Programming

code.jsoftware.com

31–40 of 129 posts

Re: Loopless Programming

#31
post #21

This reminds me of regex, and the struggle 2 months later to remember wtf I was trying to do there. Easy to write, hard to maintain, so thank you but no thank you, I prefer the loops instead even if it means going down at individual elements in a list/matrix. For any meaningful project maintenance is the threshold that will make it or break it.

There are cases where I very much prefer a declarative style. Multiplying matrices for example. Depending on the context, I will know what it does conceptually, but don't want to see the implementation, as it probably won't matter. My rule of thumb is: are you doing something unexpected ? show the implementation : show the concept

How often do you actually write out matrix multiplication in the main code flow? Generally you extract that into a function and just call it like `matrix_multiply(A, B)`, which in language which supports operator overloading could be attached behind the expression `A * B`. It's not that loops aren't happening, but the loops are just wrapped up in another expression that is more semantically meaningful, which is a good practice in general.

Re: Loopless Programming

#32
post #12

I've gotten to where I see loops as a code smell. That includes thinly-veiled loops like ruby's Enumerable#each.

And instead you use...?

Yeah I'd like to know also. Loops are a foundational operation. Instead of a loop you could use a function/operator overload, which would just call another function which contains the loop. But that isn't doing away with loops, it is just encapsulating them inside a function and calling them in order to avoid polluting up the higher level code context with loop code, and makes that upper context easier to read.

Re: Loopless Programming

#33

This reminds me of regex, and the struggle 2 months later to remember wtf I was trying to do there. Easy to write, hard to maintain, so thank you but no thank you, I prefer the loops instead even if it means going down at individual elements in a list/matrix. For any meaningful project maintenance is the threshold that will make it or break it.

>I prefer the loops instead even if it means going down at individual elements in a list/matrix.

Actually you have it backwards, probably because you confused J's somewhat cryptic notation as the only way to implement the same concept.

It's the for loops, with their sprawl of non-declarative code, that would be equivalent to the regex opaqueness, and a well named operator or function to achieve the same thing that would be more like J.

E.g. would you rather use a:

  sort(myList, order=desc) 
or write your own sorting with for loops?

Similarly, think of operations like:

  findElement(myList, predicate)

  filterElements(myList, predicate)

  keepElements(myList, predicate)

  forEach(myList, myFunc)

  forEachParallel(myList, myFunc, chunks=5)
In other words, reduce, map, and specialized versions of them.

If 10-20 such language provided functions covered all cases, I'd use them over for loops all the time. In fact that's how people use e.g. lodash.

What J adds is a succinct syntax to write and compose such primitives at the language level.

But such a syntax is not necessary to achieve the same concept (although not the same brevity/expressiveness) and be better/more readable than for loops...

P.S And regexes themselves should be compared to the equivalent parsing code -- which could require a FSM, or an ad-hoc buggy implementation of the same checks/captures spanning 10s or 100s of lines depending on the regex. Except if you just use a regex for very simple things where e.g. a "contains" function or some splitting etc will be simpler.

Re: Loopless Programming

#35

In C#/.Net there's language constructs like LINQ, and framework methods on generic collections like Select() and Where() and SkipWhile(), etc. For example, if you want to write code that returns the first X items in an array that satisfy a predicate P, it will look a lot neater and readable using code like that, than if you were to write it with for loops and if statements. But it's still just syntactic sugar, the ne…

> But it's still just syntactic sugar, the neater code just masks the underlying code that contains the actual loops and conditionals.

It seemed to me that was often more performant than using a loop.

Re: Loopless Programming

#37
post #35

In C#/.Net there's language constructs like LINQ, and framework methods on generic collections like Select() and Where() and SkipWhile(), etc. For example, if you want to write code that returns the first X items in an array that satisfy a predicate P, it will look a lot neater and readable using code like that, than if you were to write it with for loops and if statements. But it's still just syntactic sugar, the ne…

> But it's still just syntactic sugar, the neater code just masks the underlying code that contains the actual loops and conditionals. It seemed to me that was often more performant than using a loop.

Linq pipelines are lazily evaluated, so you can get linear performance instead of polynomial.

Re: Loopless Programming

#38
post #7

As far as explicit loops, I probably use write out a loop once a month and maybe not even that often. Using map/filter/reduce [as well as sugar funcs until/any/all] solves virtually all the common cases of working with lists. Granting it's not sufficient if you're writing specialized code like sorting arrays efficiently, but for general development, going higher-order is the way to go.

You can say this now but not long ago map/filter/reduce were almost esoteric.

Re: Loopless Programming

#39
post #35

In C#/.Net there's language constructs like LINQ, and framework methods on generic collections like Select() and Where() and SkipWhile(), etc. For example, if you want to write code that returns the first X items in an array that satisfy a predicate P, it will look a lot neater and readable using code like that, than if you were to write it with for loops and if statements. But it's still just syntactic sugar, the ne…

> But it's still just syntactic sugar, the neater code just masks the underlying code that contains the actual loops and conditionals. It seemed to me that was often more performant than using a loop.

It depends on what you do, and the underlying code can be pretty smart. But it can also be pretty dumb.

The main difference is that if you use .Where(P).Take(X), you're actually generating a new enumerator, a new coroutine, and that code doesn't get called until you actually enumerate it.

But if you write your for/if loop, you run the code immediately, you go through the source array, run the predicate on each item, until you have your X items, and then you return a new array with those elements.

Re: Loopless Programming

#40

Earlier quoted context omitted.

And instead you use...?

Yeah I'd like to know also. Loops are a foundational operation. Instead of a loop you could use a function/operator overload, which would just call another function which contains the loop. But that isn't doing away with loops, it is just encapsulating them inside a function and calling them in order to avoid polluting up the higher level code context with loop code, and makes that upper context easier to read.

You described the GPs point perfectly. This is also covered in the article; it exhaustively covers the use cases for loops and provides higher level functions and operators instead.
Post reply on HN