(no title)
desumeku | 11 months ago
You don't really think that functional languages aren't appending things, using temp vars, and using conditional logic behind the scenes, do you? What do you think ".filter(node => !node.isHidden)" does? It's nothing but a for loop and a conditional by another name and wrapped in an awkward, unwieldy package.
>which introduces a performance regression from having to periodically grow the array
This is simply ridiculous, do you just believe that the magic of Lisp/FP allows it to pluck the target variables out of the sky in perfectly-sized packages with zero allocation or overhead?
stouset|11 months ago
You "can't see and don't have access to" `if`, `range`, or `append` but somehow you don't find this a problem at all. I wonder why not?
> You don't really think that functional languages aren't appending things, using temp vars, and using conditional logic behind the scenes, do you?
By this metric all languages that compile down to machine instructions are equivalent. After all, it winds up in the same registers and a bunch of CMP, MOV, JMP, and so on.
`.distinct()` could sort the result and look for consecutive entries, it could build up a set internally, it could use a hashmap, or any one of a million other approaches. It can even probe the size of the array to pick the performance-optimal approach. I don't have to care.
> [".filter(node => !node.isHidden)" is] nothing but a for loop and a conditional by another name and wrapped in an awkward, unwieldy package.
This is honestly an absurd take. I truly have no other words for it. map, filter, and friends are quite literally some of the clearest and most ergonomic abstractions ever devised.
DonHopkins|11 months ago
cepstrum: inverse spectrum
lifter: inverse filter
saphe: inverse phase
quefrency alanysis: inverse frequency analysis
gisnal orpcessing: inverse signal processing
https://en.wikipedia.org/wiki/Cepstrum
desumeku|11 months ago
Well, this is probably why functional programming doesn't see a lot of real use in production environments. Usually, you actually do have to care. Talk about noticing a performance regression because I was simply appending to an array. You have no idea what performance regressions are happening in ANY line of FP code, and on top of that, most FP languages are dead-set on "immutability" which simply means creating copies of objects wherever you possibly can... (instead of thinking about when it makes sense and how to be performant about it)
porridgeraisin|11 months ago
False equivalence. You're saying that the statement "both for.. append and .map() executing the _same steps_ in the _same order_ are the same" is equivalent to saying that "two statements being composed of cmp,jmp, etc (in totally different ways) are the same" That is a dishonest argument.
> Distinct could sort and look for consecutive, it could use a hashmap
People love happy theories like this, but find me one major implementation that does this. For example, here is the distinct() implementation in the most abstraction-happy language that I know - C#
https://github.com/dotnet/runtime/blob/main/src%2Flibraries%...
It unconditionally uses a hashset regardless of input.
Edit: found an example which does different things depending on input
https://github.com/php/php-src/blob/master/ext/standard/arra...
This does the usual hashset based approach only if the array has strings. Otherwise, it gets the comparator and does a sort | uniq. So, you get a needless O(nlogn), without having a way to distinct() by say, an `id` field in your objects. Very ergonomic...
On the other hand...
Let us say you want to refactor and store a struct instead of just a string. The code would change to... Visually, it is basically the same, with clear visual messaging of what has changed. And as a bonus, it isn't incurring a random performance degradation.Edit 2: An SO question for how to do array_unique for objects in php. Some very ergonomic choices there... https://stackoverflow.com/questions/2426557/array-unique-for...
AdieuToLogic|11 months ago
This is a key difference between imperative programming and other paradigms.
> You don't really think that functional languages aren't appending things, using temp vars, and using conditional logic behind the scenes, do you?
A key concept in a FP approach is Referential Transparency[0]. Here, this concept is relevant in that however FP constructs do what they do "under the hood" is immaterial to collaborators. All that matters is if, for some function/method `f(x)`, it is given the same value for `x`, `f(x)` will produce the same result without observable side effects.
> What do you think ".filter(node => !node.isHidden)" does?
Depending on the language, apply a predicate to a value in a container, which could be a "traditional" collection (List, Set, etc.), an optional type (cardinality of 0 or 1), a future, an I/O operation, a ...
> It's nothing but a for loop and a conditional by another name and wrapped in an awkward, unwieldy package.
There is something to be said for the value of using appropriate abstractions. If not, then we would still be writing COBOL.
0 - https://en.wikipedia.org/wiki/Referential_transparency
JadeNB|11 months ago
But the whole point of higher-level languages is that you don't have to think about what's going on behind the scenes, and can focus on expressing intent while worrying less about implementation. Just because a HLL is eventually compiled into assembler, and so the assembler expresses everything the HLL did, doesn't mean the HLL and assembler are equally readable.
(And I think that your parent's point is that "awkward, unwieldy package" is a judgment call, rather than an objective evaluation, based, probably, on familiarity and experience—it certainly doesn't look awkward or unwiely to me, though I disagree with some of the other aesthetic judgments made by your parent.)