News for hackers. Stuff that matters.
Re:Click by johnfn on Friday March 19, 2021 @06:19PM (#26518703)
Well, that's an unconventional way to write a for loop. Maybe the website is commending you on that :-)
Re:Click by halfmatthalfcat on Friday March 19, 2021 @06:38PM (#26518854)
Can save more bits by doing:

Array.from({ length: 10000 }, button.click);

Re:Click by warent on Friday March 19, 2021 @08:09PM (#26519442)
I this awesome... I've always done Array.from(new Array

But your approach makes perfect sense and is so much cleaner. Thank you!

If anyone is wondering why it works, it's because everything in JavaScript is an object. So, an array is an object with a length prop. Apparently Array.from just needs any object with a length prop to work

Re:Click by kvirani on Friday March 19, 2021 @08:53PM (#26519759)
Something about ducks?
Re:Click by chpmrc on Friday March 19, 2021 @09:32PM (#26519973)
"If it walks like a duck, and it quacks like a duck, then it must be an object"
Re:Click by DonHopkins on Saturday March 20, 2021 @07:17AM (#26522283)
"If it walks like a duck, and it quacks like a duck, then it must be created by a QuackEnumeratorWalkManangerRepositoryProxyFactoryFactoryAdapterBroker." -Java
Re:Click by erhk on Saturday March 20, 2021 @03:13AM (#26521393)
Of it has feathers, then as far as I'm concerned it is a duck.

Similarly, when I pick up a feathered pen in real life I become a duck

Re:Click by chmod775 on Saturday March 20, 2021 @05:17AM (#26521781)
duckduckduck.duck is still available, by the way.

Well, .duck isn't a TLD yet and it may not be publicly available...

https://icannwiki.org/.duck

Re:Click by Freak_NL on Saturday March 20, 2021 @06:19AM (#26521997)
Now gogo.duck and go.duck would be nice aliases for DuckDuckGo. (There is ddg.gg of course.)
Re:Click by franky47 on Friday March 19, 2021 @06:46PM (#26518939)
I did not know this variant, thanks. Having to fill the array with anything (even `undefined`) to iterate on it seemed such a weird concept (but then again, JS is weird).
Re:Click by a1371 on Friday March 19, 2021 @07:05PM (#26519070)
The spread operator does not have the same quirk. I use it but it's still a bit weird tough

[...new Array(1000)].map(something)

Re:Click by ficklepickle on Saturday March 20, 2021 @01:57AM (#26521094)
You can drop the new

[...Array(1000)]

I think that is the least bits. Would love to be proven wrong :D

Re:Click by franky47 on Saturday March 20, 2021 @02:06AM (#26521138)
It may be shorter, but I like the spread syntax best used sparingly, it's harder to grasp why it was necessary there at a glance.

That's what I like in the elegance of Array.from({ length: 1000 }): it's a hack, but it reads naturally.

Re:Click by antonvs on Sunday March 21, 2021 @07:38PM (#26535162)
"Harder to grasp" only lasts until you're mildly familiar with the idiom.
Re:Click by trehalose on Saturday March 20, 2021 @07:45PM (#26526943)
[...Array(1e3)]
Re:Click by bawolff on Friday March 19, 2021 @07:01PM (#26519037)
new Array(1000); ?
Re:Click by franky47 on Friday March 19, 2021 @07:05PM (#26519069)
Try iterating on it, it won't work. This creates 1000 "empty slots".
Re:Click by jholman on Friday March 19, 2021 @07:26PM (#26519192)
In addition to franky47's more important point, I'll add that `new Array()` and `Array()` are equivalent.
Re:Click by The_rationalist on Friday March 19, 2021 @11:10PM (#26520514)
In java it would be default initialized but it isn't in js
Re:Click by phogster on Friday March 19, 2021 @06:44PM (#26518916)
Never heard of a "from" loop before.
Re:Click by franky47 on Friday March 19, 2021 @06:49PM (#26518963)
Array.from lets you build an array from an iterable source (often used in conjunction with `new Set` to eliminate duplicates), or in this case, of a fixed length.
Re:Click by klyrs on Friday March 19, 2021 @07:40PM (#26519271)
Re:Click by notJim on Friday March 19, 2021 @06:34PM (#26518814)
This is your brain on javascript :)

Guessing it's bc one-liners are easier to write than for loops in the console.

Re:Click by hahajk on Friday March 19, 2021 @11:51PM (#26520687)
I haven’t had an off-by-one error since I stopped using for loops.
Re:Click by trulyme on Saturday March 20, 2021 @11:28AM (#26523793)
Got any solution for naming and caching too?
Re:Click by TobTobXX on Saturday March 20, 2021 @05:13PM (#26526104)
I get my variable names from `openssl rand -hex 20`
Re:Click by mrcartmenez on Friday March 19, 2021 @07:16PM (#26519139)
It’s also because it’s good practice to use the lowest power loop possible.

A for loop can implement a reduce, a reduce can implement a map, a map can implement a forEach, but not the inverse.

Re:Click by thaumasiotes on Friday March 19, 2021 @08:33PM (#26519637)
Huh? I don't follow.

  In [1]: def lred(function, iterable, initializer): 
     ...:   acc = initializer 
     ...:   def reductor(el): 
     ...:     nonlocal acc 
     ...:     acc = function(acc, el) 
     ...:   for n in map(reductor, iterable): pass 
     ...:   return acc 
     ...:                                                                             
  
  In [2]: lred(lambda a,b: 10*a + b, [2,4,6,3,1], 40)                                 
  Out[2]: 4024631
What's stopping you from running these equivalencies in either direction?
Re:Click by jessedhillon on Friday March 19, 2021 @08:59PM (#26519796)
They mean that the forEach runs code per element, but cannot return a transformed list of values, you need map for that.

A map can run code per list element but the result must be injective (one-to-one).

Reduce can do all of the above, but must return a lower dimension result from its input.

And finally, a for loop is basically omnipotent.

Re:Click by thaumasiotes on Saturday March 20, 2021 @01:54AM (#26521073)
A forEach can easily return a transformed list of values.

  acc = []
  for el in values:
    acc.append(f(el))
  return acc
This hierarchy doesn't exist; you can pretty much implement any of them in terms of the others.

To make that untrue, you need to define very strict limits on what else your language can do.

(Sure, we produce a transformed list here through the use of side effects. But note that the original example sparking the claim that forEach can't do what map can was this:

  .forEach(() => button.click())
Side effects are clearly allowed.)
Re:Click by joe-user on Saturday March 20, 2021 @02:22AM (#26521195)
The forEach isn't returning it in your example, the line after it is returning. Try again without acc and I believe that's what was meant.

You can implement any of them in terms of the others, but only if you break convention and introduce side effects. Follow convention and try to implement (for example) reduce with map and you'll find that it's not possible.

Re:Click by thaumasiotes on Saturday March 20, 2021 @02:31AM (#26521229)
> You can implement any of them in terms of the others, but only if you break convention and introduce side effects.

This can't be right. forEach has no effects other than side effects. A convention that says not to use side effects prevents you from using forEach at all.

But that would make claims about the place of forEach in a hierarchy into meaningless nonsense.

> The forEach isn't returning it in your example, the line after it is returning.

That depends on your point of view. C has numerous functions which accept pointer parameters and return values in those parameters. That's just the normal way to return multiple values in C.

And by that standard, the forEach itself is returning the transformed list; that's where the transformation occurs. The following `return` line is only necessary if this is a snippet within a function whose purpose is to execute a for statement; you would actually do this inline, by just writing the for statement without needing a following `return`.

Re:Click by HeavyStorm on Saturday March 20, 2021 @05:32AM (#26521846)
I really don't think you got the original point...
Re:Click by thaumasiotes on Saturday March 20, 2021 @12:28PM (#26524194)
What was the original point?
Re:Click by lurn on Saturday March 20, 2021 @01:10PM (#26524471)
I think they’re only talking about JavaScript, in which case the forEach function doesn’t return anything. So you can do x.map(…).forEach(…) because map returns an array. But u can’t do x.forEach(…).map(…) Ur examples seem like they’re for a different language.
Re:Click by momentoftop on Saturday March 20, 2021 @06:55AM (#26522168)
Haskell has strict limits on side-effects, but also abstracts these functions over the thing you're "forEaching." There, a reduce can't implement a map, because a map is required to return the same type of collection you put in. A reduce can only return an arbitrarily chosen collection (say, an Array).

And without side-effects, a map can't implement a forEach.

Re:Click by thaumasiotes on Saturday March 20, 2021 @12:35PM (#26524249)
> And without side-effects, a map can't implement a forEach.

Yes, it can, because without side effects, forEach is a NOP. That's not difficult to implement. As long as you don't do anything with the return value from map, you're there.

Re:Click by seedboot on Saturday March 20, 2021 @02:28AM (#26521223)
Re:Click by DangitBobby on Friday March 19, 2021 @09:15PM (#26519888)
> Reduce can do all of the above, but must return a lower dimension result from its input.

What do you mean by this? You can accumulate just about anything into the resulting object, including a copy of the original array.

Re:Click by SamBam on Friday March 19, 2021 @09:51PM (#26520060)
I think it's just being confusingly stated. GP already said that reduce could implement map. I think it's merely that reduce can just output a single result, of any type. (Which is already more powerful than map, which must output an array.)

Of course, in fact you could hack anything in any of these, since you could be doing other work in the function called. But I think the general principle is sound.

Re:Click by thaumasiotes on Saturday March 20, 2021 @01:57AM (#26521093)
> (Which is already more powerful than map, which must output an array.)

Don't tell Common Lisp.

Re:Click by jolux on Friday March 19, 2021 @11:20PM (#26520563)
forEach is actually more powerful than map, you would not be able to use map for side effects in a static and/or lazy language. In a strict, dynamic language, it matters less. Even so I wouldn't describe being an expression vs statement as a difference in power. It's contextual.
Re:Click by thaumasiotes on Saturday March 20, 2021 @01:55AM (#26521080)
> forEach is actually more powerful than map, you would not be able to use map for side effects in a static and/or lazy language.

You might notice this problem above, where it's necessary to do

  for n in map(reductor, iterable): pass
to realize the mapping.
Re:Click by eru on Friday March 19, 2021 @10:40PM (#26520338)
Especially, a for-loop can break out early or skip elements.
Re:Click by thaumasiotes on Saturday March 20, 2021 @02:18AM (#26521179)
So can reduce. You'd put that logic in the function you pass to the call to reduce.

So can map. Ditto.

So can foreach. Ditto again.

  for el in values:
    if el == 3: pass
    else:
      do_something_with( el )
Re:Click by mekkkkkk on Saturday March 20, 2021 @04:07AM (#26521569)
No, that's just a guard condition. Parent post was referring to break, i.e. skip the rest of the iteration.
Re:Click by thaumasiotes on Saturday March 20, 2021 @12:30PM (#26524218)
For forEach that's easy:

  for el in values:
    if el == 3: return
    do_something_with( el )
For the other two, you still can, but you'll need to handle the control flow yourself, by doing something like goto or invoking a continuation.
Re:Click by mekkkkkk on Saturday March 20, 2021 @03:05PM (#26525280)
That's a for loop. And depending on the language I'm pretty sure that return call would exit the parent scope.
Re:Click by thaumasiotes on Saturday March 20, 2021 @05:33PM (#26526217)
> That's a for loop.

I take it you've never read any Python? That's a forEach. Python doesn't even have a for loop construct (though it does have while, which is equivalent).

> And depending on the language I'm pretty sure that return call would exit the parent scope.

Yes, that's the point, that's an illustration of terminating the forEach before you've processed each element.

Re:Click by mekkkkkk on Saturday March 20, 2021 @08:47PM (#26527233)
I'm not very proficient in Python, no. I thought you were giving pseudo-code examples. If your argument doesn't apply to the common array methods (forEach, map, reduce) in JS and similar languages, then you missed the entire point of this comment thread.
Re:Click by eru on Monday March 22, 2021 @05:24AM (#26538481)
Python's for-loops are really for-each loops.

If you have a C-style for-loop, you can and have to do everything yourself. That means you can skip elements or processer them twice, etc.

In a Python-style for-each loop, you can break out with break or return, but you have a harder time skipping or changing the order of processing. So they are weaker. And that's good.

(Your examples still process elements in the body of the loop. It's just that sometimes the body decides to do a no-op.)

Putting the no-op logic in the body of the loop, or in the function you pass to reduce is different than being able to short-cut evaluation.

You can see the difference most clearly, when trying to process (the start of) an infinite generator with reduce or a for-loop. Reduce will just hang.

Re:Click by vsareto on Friday March 19, 2021 @08:21PM (#26519538)
>Guessing it's bc one-liners are easier to write than for loops in the console.

Firefox has a pretty good multi-line editor now if anyone was looking for that

Re:Click by anonu on Friday March 19, 2021 @10:44PM (#26520360)
It's how you would do it with a language like APL or q.