TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

Loopless Programming

199 点作者 codesections超过 5 年前

29 条评论

jameshart超过 5 年前
Most programmers have worked in a largely loopless programming language: SQL. IT lets you easily build the same sort of ‘Boolean state for every item’ as this discusses, but it requires you to be much more explicit about which items you want to line up next to one another if you’re joining two lists together.<p>In modern languages we usually just use mapreduce like functional approaches to handle the same sort of thing, so I’m not sure this approach is as unusual as the author seems to think.
评论 #21301782 未加载
评论 #21302958 未加载
评论 #21301680 未加载
NOGDP超过 5 年前
&gt; Looping - performing a computation repeatedly - is what programs do. In most computer languages, all loops are expressed by one of two statements:<p>&gt; Do While - repeat a code block until a condition is met<p>&gt; For - repeat a code block, with a loop index indicating how many times the block has been repeated.<p>&gt; Programmers trained on scalar languages have spent many years internalizing the Do-While and For paradigms. Discarding these paradigms is the biggest re-think they need to make when they learn J.<p>A lot of languages have these kinds of semantics and arguably in a more streamlined &#x2F; better organised way - Haskell typeclasses for example. I don&#x27;t know if it&#x27;s true that &#x27;most languages&#x27; only support for&#x2F;while loops, but probably not. It also doesn&#x27;t take &#x27;many years&#x27; to internalise for&#x2F;while loops, these are fairly basic constructs which are learned by most novices in the beginning of an introductory programming course.<p>&gt; (x + y) is an expression rather than a statement. The J programmer can embed (x + y) in a larger expression, perhaps a matrix multiplication (w +&#x2F; . * (x + y)) which adds the equivalent of three more nested loops, but is still a single expression. Expressions can be combined; statements cannot.<p>(x + y) is going to be an expression in almost any language...<p>&gt; Many modern languages have iterators, which slightly streamline the For loop, but without addressing its fundamental deficiencies.<p>What are the &#x27;fundamental deficiencies&#x27;?<p>This seems like a pretty low-effort write-up.
评论 #21301019 未加载
评论 #21301038 未加载
评论 #21301236 未加载
评论 #21301813 未加载
unnouinceput超过 5 年前
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&#x2F;matrix. For any meaningful project maintenance is the threshold that will make it or break it.
评论 #21301331 未加载
评论 #21301176 未加载
评论 #21301151 未加载
pjungwir超过 5 年前
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 <i>not getting it</i>. &quot;Why would you want to do the same thing twice?&quot;<p>Just this morning my own 10-year-old was looking over my shoulder while I was debugging some C, and I explained for loops to him. Since he plays violin I said it was like a repeat in music, and he seemed to grok that right away.<p>My other memory of those days is, after years of dismissing GOSUB as useless (&quot;Why would I want to go back to the same place I just left?&quot;), finally having a flash of enlightenment and getting the point. It&#x27;s a function call! (Not that I knew what those were....)<p>Sorry this has nothing to do with the wiki page. :-) Except maybe that to at least one kid loopy programming was unnatural.
评论 #21302656 未加载
评论 #21302595 未加载
jadbox超过 5 年前
As far as explicit loops, I probably use write out a loop once a month and maybe not even that often. Using map&#x2F;filter&#x2F;reduce [as well as sugar funcs until&#x2F;any&#x2F;all] solves virtually all the common cases of working with lists. Granting it&#x27;s not sufficient if you&#x27;re writing specialized code like sorting arrays efficiently, but for general development, going higher-order is the way to go.
评论 #21301845 未加载
评论 #21301393 未加载
评论 #21300927 未加载
Athas超过 5 年前
Last time I did APL programming I was a bit bothered by the performance implications of some of the standard loopless programming styles. In particular, it&#x27;s hard to nest loops.<p>As an example of the implications, consider computing the Mandelbrot set. I&#x27;ll be using Numpy here to ensure people can follow what I&#x27;m doing, but for the point I wish to make, it&#x27;s similar to how you&#x27;d write it in APL. The Mandelbrot set is compute by applying a function like this to each of a bunch of complex numbers:<p><pre><code> def divergence(c, d): i = 0 z = c while i &lt; d and dot(z) &lt; 4.0: z = c + z * z i = i + 1 return i </code></pre> To apply this to many points simultaneously in a vectorised &quot;loopless&quot; style, we&#x27;d write it like this:<p><pre><code> def mandelbrot_numpy(c, d): output = np.zeros(c.shape) z = np.zeros(c.shape, np.complex32) for it in range(d): notdone = np.less(z.real*z.real + z.imag*z.imag, 4.0) output[notdone] = it z[notdone] = z[notdone]**2 + c[notdone] return output </code></pre> There is just one `for` loop, which is pretty easy to do in APL. The `while` loop has been subsumed into control flow encoded in boolean arrays. This is not <i>exactly</i> how you&#x27;d do in APL, but it has a similar feel. It&#x27;s also pretty slow, because we are manifesting the entire `z` array in memory for every iteration in the outer loop. In contrast, an old school loop over every point, with an inner while loop for every point, would involve only two memory accesses per point. On a GPU, I have measured the vectorised style to be about 30x slower than one with a conventional `while` loop.
评论 #21302903 未加载
JesseAldridge超过 5 年前
&gt; add each number in a list x to each number in the corresponding row of a two-dimensional array y<p>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.<p>Skimming the rest of the article, I don&#x27;t get how this is different from any other language. The primary difference seems to be the function names are all one or two characters long for some reason. I must be missing something...
评论 #21302662 未加载
johnday超过 5 年前
Almost any functional programming language has the same power and quality of life in programming, except with the added bonus that things have <i>names</i>.<p>If you come up with a new looping construct (which you probably won&#x27;t), just create a type class for it and you&#x27;re done; any data structure you want now has that construct, if you give it a sensible implementation.<p>It would be very unusual to write a Haskell program with explicit loops in it. The closest you ever get would be something like `forM_` and even that doesn&#x27;t really count. I suppose a more direct example would be a recursive function call, but imperative programmers may be surprised at just how few of these actually crop up in production code.
评论 #21301683 未加载
japanoise超过 5 年前
J is one of the strangest programming languages I&#x27;ve ever tried. I would reccomend giving it a go, though I wouldn&#x27;t personally write actual software in it.
评论 #21300994 未加载
评论 #21300897 未加载
defanor超过 5 年前
See also: array programming [0] (apparently 1970s APL, on which J is based, didn&#x27;t even have explicit for&#x2F;while loops).<p>Nowadays even common imperative languages have higher-order functions, so I don&#x27;t find it very exciting. Though still quite handy in R and similar languages where you deal with array-like structures almost all the time.<p>[0] <a href="https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Array_programming" rel="nofollow">https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Array_programming</a>
henrikschroder超过 5 年前
In C#&#x2F;.Net there&#x27;s language constructs like LINQ, and framework methods on generic collections like Select() and Where() and SkipWhile(), etc.<p>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.<p>But it&#x27;s still just syntactic sugar, the neater code just masks the underlying code that contains the actual loops and conditionals.<p>As always, it&#x27;s a tool, and can be misused like all tools. It&#x27;s a balance, the neater code might be more readable, but the for&#x2F;if code might be easier to change or optimize down the line if conditions change. It all depends. There are no silver bullets, just tools, and trying to minimize the amount of tools in your toolbox is just dumb.
评论 #21301371 未加载
stewbrew超过 5 年前
2 questions:<p>- Doesn&#x27;t &quot;loopless&quot; actually mean &quot;implicit looping&quot;? (unless you assume infinite parallelization)<p>- How do you debug a chain of &quot;loopless&quot; functions when some corner case invalidates your assumptions?
评论 #21302485 未加载
stabbles超过 5 年前
C++ devs are encouraged to do loopless programming by using algorithms in the standard library; plus C++20 ranges should improve the ease of loopless programming.<p>Where J shines is array based programming. The C++ algorithms are concerned with vectors, but in J you can combine matrices, vectors and scalars in concise expressions.
评论 #21302519 未加载
评论 #21301972 未加载
jonny383超过 5 年前
This article doesn&#x27;t actually list any self-claimed &quot;fundamental deficiencies&quot;. There&#x27;s a reason that C (any many other languages) have been using pre and post conditional loops for over fifty years - because it&#x27;s what the machine actually does, and they are straight forward to follow.<p>The article mentions &quot;A C programmer would write&quot;, and then shows two nested for loops. This is almost correct, but I think any good C programmer would write this once as a method or a macro, and then calling it is as simple x + y, without the snake-oil.<p>In either case, both are going to execute something like<p>.loop CMP r0, r1 JNZ .end_of_loop ADD r2, r1 ; move some memory around JMP .loop .end_of_loop ;<p>And what does that look like... oh wow it&#x27;s a loop.<p>The J language was written in 1990. It&#x27;s now 2019. The language is just wrong.
评论 #21302380 未加载
hinkley超过 5 年前
I recall another language that was trying to do something similar. In most languages you have to decide about x:1 versus x:* relationships very early and it’s a painful refactor to go back and fix it. This one tried to fix it as well so that much of the time you only changed the variable declaration and the code just worked.<p>jQuery made a similar observation, and many of its functions are list comprehensions. If they had chosen a different default behavior for empty lists I might still be championing it today. But the silent failures were a bitter pill to swallow.<p>In fact I sometimes still fantasize about building a mini front end framework containing the inverse behavior and some other more modern ideas.
评论 #21301534 未加载
评论 #21300841 未加载
lsb超过 5 年前
You see some of this with Numpy, where a +, for instance, has been overridden to mean addition of n dimensional arrays, and Numpy is foundational for a lot of the data science programming these days
ncmncm超过 5 年前
Tl;dr : APL has implicit loops because almost everything is an array, and mentioning an array implies a loop to process it.<p>In C++, nowadays, people are encouraged to use Standard Library algorithms in preference to most loops; and to make an algorithm out of any loop that can&#x27;t be cleanly replaced with a Standard one, and call that. The reasoning is similar to that explained in the article, except that saying which you are doing, by naming the algorithm, communicates better what you are trying to achieve than does coding the loop in place.<p>In APL, of course, naming anything with more than two or three letters, or wrapping a one- or two-operator expression in a function, gets you looked at funny, so that reason wouldn&#x27;t apply.
评论 #21301909 未加载
m0zg超过 5 年前
Loops of known size is the one of the best hints you can give to your compiler though. If the computation inside the loop isn&#x27;t too complicated, the compiler will unroll these, often resulting in amazing speedups. In fact if you know that your array is pretty long but don&#x27;t know its size, it&#x27;s often worthwhile to structure the computation as a nested loop, where the inner loop processes chunks of known length (which should be fairly short, and picked to utilize the widest SIMD on your target CPU, e.g. 8 for fp32 on most Intel chips). Then when you run out of chunks you &quot;mop up&quot; at the end. Furthermore, if your chunk size is a power of 2 (which it should be), don&#x27;t be afraid of the modulo operator (which is normally very slow): the compiler will automatically apply the x % chunk_size == x &amp; (chunk_size - 1) trick for you. All of the above obviously only works if chunk size is known at compile time.
评论 #21301157 未加载
jancsika超过 5 年前
&gt; In J we do this by <i>creating</i> a Boolean list, one value (0 or 1) per item of z<p>Does the word &quot;creating&quot; here mean you can&#x27;t do a relatively simple check across array elements in J <i>without</i> allocating memory? E.g., soft realtime scheduling for such a simply operation is essentially just not possible in J?
评论 #21301553 未加载
kbbr超过 5 年前
Unless you can leverage special instructions &#x2F; hw to realize your array operations, loops will be the fundamental operations generated by the compiler executed by the CPU. For a lot of scenarios, loopless code is surely more expressive. However, I would not say that it is per se in any kind superior. Rather, it is a feature of each language, how much to abstract from the actual CPU instructions.<p>So to have fine granular control over your generated code, classic loops in C always relevant, while a simple array operation can be expressed in such high level way for other use cases.
manmal超过 5 年前
Swift provides many of the required Collection operators to go loopless - map, reduce, flatMap, compactMap (eliminate nil values), filter, first, contains, prefix&#x2F;suffix, ... there’s even an OSS library that gives a compile time guarantee that a Collection is non-empty.<p>There are only some instances where I ever need a loop:<p>- map cannot produce a Dictionary, so Dictionary manipulations usually require a loop<p>- Sometimes, a more complex qualifier or stopping condition is needed. Like striding through a Collection in a non-linear way.
评论 #21302877 未加载
chris_wot超过 5 年前
That table if alternatives to loops is really interesting. I wonder if there is a similar table for C++ in some form on another website?
评论 #21302181 未加载
评论 #21304079 未加载
agumonkey超过 5 年前
I find that most programming languages are often wasting time on the notion of plurals .. loopless sounds appealing there.
ridiculous_fish超过 5 年前
First I&#x27;ve heard of J! Say you want to compute the product of integers in a list. Should you encounter a zero, you can exit immediately since the product is known. In C this would be an `if (arr[i] == 0) break`. How would one express this in J&#x27;s loopless style?
kerzol超过 5 年前
There is a CS concept with a similar name, but completely different meaning:<p><a href="https:&#x2F;&#x2F;en.m.wikipedia.org&#x2F;wiki&#x2F;Loopless_algorithm" rel="nofollow">https:&#x2F;&#x2F;en.m.wikipedia.org&#x2F;wiki&#x2F;Loopless_algorithm</a>
fake-name超过 5 年前
s&#x2F;loopless&#x2F;explicit loop&#x2F;
theamk超过 5 年前
If you really want to play with loopless programming, I recommend Python’s numpy. It implements many of the same constructs, but using regular English words instead of punctuation.
评论 #21301676 未加载
joncp超过 5 年前
I&#x27;ve gotten to where I see loops as a code smell. That includes thinly-veiled loops like ruby&#x27;s Enumerable#each.
评论 #21301154 未加载
flexblue超过 5 年前
Quote:<p>&quot;(x + y) is an expression rather than a statement. The J programmer can embed (x + y) in a larger expression, perhaps a matrix multiplication (w +&#x2F; . * (x + y)) which adds the equivalent of three more nested loops, but is still a single expression. Expressions can be combined; statements cannot.&quot;<p>What about an expression like (x * x + y * y)? This would still be a single loop in C. Is J smart enough to figure that out, or will it turn that into three loops?