Live data from Hacker News

Loopless Programming

code.jsoftware.com

91–100 of 129 posts

Re: Loopless Programming

#91
post #90
post #75

Earlier quoted context omitted.

Pretty mind-blowing. Any Haskell experts want to attempt a point-free version of the function that calculates the next generation for an arbitrary matrix in Conway’s Game of Life?

If you use a the right representation of the board in Haskell then you don't have to write a function to calculate the next generation at all, you can just use Comanadic extend, as Chris Penner does here: https://github.com/ChrisPenner/conway/blob/master/src/Conway...

While this code is awesomely mindbending, it does seem to be limited to a 20×20 grid, rather than being applicable to grids of any size. Also, and correct me if I'm wrong here, it looks like it would take more than 5 minutes to write.

The more interesting aspect, though, is that it seems to be organized in an almost totally different way from the APL code. I suggest that this is largely because the two languages foster very different approaches to problem-solving (though also I get that this is not the normal way to program Life in Haskell either).

Re: Loopless Programming

#92
post #79

Earlier quoted context omitted.

PL/SQL is not SQL.

Do recursive CTEs count as SQL, then? Despite the name, they are practically loops.

I wrote this query for Dercuano the other day; it computes the Collatz sequence starting from each of the first 100 integers, running a second Collatz computation twice as fast in parallel to detect any cycles (and of course there are none):

    with recursive collatz as 
       (select 1 as x, 1 as n, 1 as m, 0 as p, 0=1 as exit union
        select case when nextx then x + 1 else x end as x,
               case when nextx then x + 1
                               else (case n % 2 when 1 then 3*n + 1
                                                       else n / 2 end)
               end as n,
               case when nextx then x + 1
                               else (case newm % 2 when 1 then 3*newm + 1
                                                          else newm / 2 end)
               end as m,
               case when nextx then 0 else p+1 end as p,
               case when nextx then 0 = 1 else n = newm end as exit
        from (select (m = 1 or newm = 1) as nextx, x, n, m, p, newm
              from (select x, n, m, p,
                    case m % 2 when 1 then 3*m + 1 else m / 2 end as newm
                    from collatz where not exit) a) b
        where x 
It works in Postgres 9.5.14; I'm interested to hear if it works or doesn't in other SQL implementations.

I think this definitely qualifies as a loop.

Re: Loopless Programming

#93

I still remember as a kid back in the 80s when a friend and I were making BASIC games on our Tandy 1000s with just the reference manual that came with the computer, and he was trying to explain to me what a FOR loop was, and I was not getting it . "Why would you want to do the same thing twice?" Just this morning my own 10-year-old was looking over my shoulder while I was debugging some C, and I explained for loops t…

Haha, you're not alone. I remember when I first learned programming, loops me a while to get. Can't remember why, just remember the confusion :P Now if I'm teaching someone, I like to explain loops like going through a stack of books. You have a stack of books, and you go through each one and do something with it.

Re: Loopless Programming

#95
post #40

Earlier quoted context omitted.

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.

It covers the use cases for loops over arrays/lists, not over more general graph-like structures.

Re: Loopless Programming

#96
post #91
post #90

Earlier quoted context omitted.

If you use a the right representation of the board in Haskell then you don't have to write a function to calculate the next generation at all, you can just use Comanadic extend, as Chris Penner does here: https://github.com/ChrisPenner/conway/blob/master/src/Conway...

While this code is awesomely mindbending, it does seem to be limited to a 20×20 grid, rather than being applicable to grids of any size. Also, and correct me if I'm wrong here, it looks like it would take more than 5 minutes to write. The more interesting aspect, though, is that it seems to be organized in an almost totally different way from the APL code. I suggest that this is largely because the two languages fost…

It doesn't have to be a finite grid. Here is another comonadic implementation of Life with an infinite board: https://github.com/BartoszMilewski/GameOfLife/blob/master/Li...

Either version would definitely take me more than five minutes to write, but then again it would take me more than five minutes to write the APL version too. For someone like Penner or Milewski the comonadic Haskell versions might be achievable in the five minute ballpark.

Re: Loopless Programming

#97

Earlier quoted context omitted.

From someone who has experience in mostly SQL, Python, Linux commands, and a smattering of other languages that I've played with (Haskell, Common Lisp, F#, Ada, Prolog, Julia, Forth, Fortran...etc) I can say that J and modern APL systems are completely different in a lot of ways. Yes functional languages have a lot built around map/fold/filter that is very similar to J's tacit programming, but the implementation make…

It seems to me like it is terse because this is a DSL for dealing with vectors and arrays of numbers. Sure the equivalent C for loops are a lot more wordy for the problems that this language solves, but you'll drive yourself crazy trying to write a simple event loop for your GUI in J.

You do everything differently in j/k/apl, so the notion of eventloop is not what you want to do there (under the hood that happens ofcourse). People would not typically write GUIs in these languages but you can [0]. They are actual languages, not DSLs.

[0] https://www.jsoftware.com/help/primer/gui.htm

Re: Loopless Programming

#98

I still remember as a kid back in the 80s when a friend and I were making BASIC games on our Tandy 1000s with just the reference manual that came with the computer, and he was trying to explain to me what a FOR loop was, and I was not getting it . "Why would you want to do the same thing twice?" Just this morning my own 10-year-old was looking over my shoulder while I was debugging some C, and I explained for loops t…

Ha! Yes, I only had the reference manual and some (published by photocopying matrix printed writing) magazines to work with begin 80s as a kid and I remember making goto’s jump forward and then when done backward; some older guy at a meetup (I was the youngest for many years there) told me to check out gosub; that suddenly clicked after that. At first I thought they were just inconvenient goto’s.

I guess my relationship between that time and j/k is that I really like the concept of just needing a (printed!) reference manual and being able to do everything you need. It is so liberating (for me anyway); it is also the reason why I like embedded asm/c programming: mostly I need nothing but the reference manual (and after all these years, not that even). To me it makes other types of work (web frontend/backend or native apps) with all their (unstable) libs tedious to work with; I am good at those (esp native apps) but I don’t really enjoy it as much.

Re: Loopless Programming

#99

> add each number in a list x to each number in the corresponding row of a two-dimensional array y I mean, I could write a function `add(x, y)` that does that in any language. You could even inspect the data or type to make it polymorphic. I believe NumPy does this, for example. Skimming the rest of the article, I don't get how this is different from any other language. The primary difference seems to be the function…

The fact that they're built into the language is in fact significant. Yes, you obviously could implement J's set of primitives in nearly any language and then use those. In practice though, you won't, and if you did then many of the people reading the code wouldn't understand it very well.

Imagine if lodash was built into JS, and optimized by the implementations to the point where it was faster than not using it. Idiomatic JS would look very different even though it hasn't made anything possible that wasn't previously possible.

Re: Loopless Programming

#100
post #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 w…

I have a substantial library with those functions for C#. Why not use Linq? Because I see people struggle with it (usually external clients who license our code and outsource development); when they do, they resort to loops. So I wrote these simpler functions which are implemented mostly with Linq but they keep people who do not understand linq (again, yes, they are there and rather a lot of them) from messing up the codebase. Advantage is that these functions translate to any other language, while Linq doesn’t, so we have the same (partially implemented) semantics for the same things over a few languages we use.
Post reply on HN