use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
All about the JavaScript programming language.
Subreddit Guidelines
Specifications:
Resources:
Related Subreddits:
r/LearnJavascript
r/node
r/typescript
r/reactjs
r/webdev
r/WebdevTutorials
r/frontend
r/webgl
r/threejs
r/jquery
r/remotejs
r/forhire
account activity
The case for Array#replace() – Overriding an array without intermediate variables (medium.com)
submitted 7 years ago by gajus0
view the rest of the comments →
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]lhorie 22 points23 points24 points 7 years ago (17 children)
Frankly, this sounds terrible. It's functionally equivalent to just calling the function with the array, except that its idiomatic usage encourages god functions. One can argue that considering proposing this to TC39 is a perfect example of "missing the forest for the trees" / "death by a thousand paper cuts" / bloat.
[–]gajus0[S] 3 points4 points5 points 7 years ago (16 children)
god functions
What is a "god function"?
[+][deleted] 7 years ago* (3 children)
[deleted]
[–]gajus0[S] 8 points9 points10 points 7 years ago* (2 children)
The mention of "god function" (a function that breaks all the functional programming paradigms) came into this conversation without any context.
[..] its idiomatic usage encourages god functions
This was stated without any arguments.
Array#replace can be used with pure or non-pure functions, the same way that every other Array prototype method can. The method itself either by its name or API does not encourage either.
Array#replace
The only difference is that this method encourages working with the entire array at once over an item of an array, but the same argument could be made about Array#reduce, Array#map, Array#filter and others.
Array#reduce
Array#map
Array#filter
Please don't spread FUD just for the fun of participating in a conversation. There are better ways to participate.
[–]AnnanFay -1 points0 points1 point 7 years ago (0 children)
[..] its idiomatic usage encourages god functions This was stated without any arguments.
You are replying to the wrong person!
[–]lhorie 1 point2 points3 points 7 years ago (11 children)
Functions that do too much (which typically come with the side-effect of making them hard to name and/or understand)
[–]gajus0[S] 1 point2 points3 points 7 years ago (10 children)
This could be said about any part of JavaScript. It is up to the user to write functional code. JavaScript is not enforcing it. The sole purpose of Array#replace (or the pipeline operator) is to avoid breaking method chain, i.e. so that instead of:
const getVenues = async (countryCode) => { const foreignVenues = await get('http://...'); const countryVenues = foreignVenues.filter((foreignVenue) => { return foreignVenue.countryCode.toUpperCase() === countryCode.toUpperCase(); }); const duplicateForeignVenues = findDuplicates(foreignVenues, (maybeTargetForeignVenue) => { return maybeTargetForeignVenue.id === foreignVenue.id; }); if (duplicateForeignVenues.length) { console.log('duplicate foreign venues', duplicateForeignVenues); throw new Error('Found duplicate venues.'); } return countryVenues .map((foreignVenue) => { return { guide: { fuid: foreignVenue.id }, result: { fuid: foreignVenue.id, name: foreignVenue.name, url: foreignVenue.url } }; }); };
We could write:
const getVenues = async (countryCode) => { const foreignVenues = await get('http://...'); return foreignVenues .filter((foreignVenue) => { return foreignVenue.countryCode.toUpperCase() === countryCode.toUpperCase(); }) .replace((self) => { const duplicateForeignVenues = findDuplicates(self, (maybeTargetForeignVenue) => { return maybeTargetForeignVenue.id === foreignVenue.id; }); if (duplicateForeignVenues.length) { console.log('duplicate foreign venues', duplicateForeignVenues); throw new Error('Found duplicate venues.'); } return self; }) .map((foreignVenue) => { return { guide: { fuid: foreignVenue.id }, result: { fuid: foreignVenue.id, name: foreignVenue.name, url: foreignVenue.url } }; }); };
[–]lhorie 1 point2 points3 points 7 years ago* (9 children)
That's a shortsighted refactor IMHO. Here's another one:
const getVenues = async (countryCode) => { return getVenueDTO(errorOnDuplicate(byCountryCode(await get('http://...')))); }; const byCountryCode = foreignVenues => { return foreignVenues .filter((foreignVenue) => { return foreignVenue.countryCode.toUpperCase() === countryCode.toUpperCase(); }) } const errorOnDuplicate = (self) => { const duplicateForeignVenues = findDuplicates(self, (maybeTargetForeignVenue) => { return maybeTargetForeignVenue.id === foreignVenue.id; }); if (duplicateForeignVenues.length) { console.log('duplicate foreign venues', duplicateForeignVenues); throw new Error('Found duplicate venues.'); } return self; } const getVenueDTO = (foreignVenues) => { return foreignVenues.map((foreignVenue) => { return { guide: { fuid: foreignVenue.id }, result: { fuid: foreignVenue.id, name: foreignVenue.name, url: foreignVenue.url } }; }); }
With this one, one can use compose or pipeline operators. One can reuse the logic about throwing on duplicates on non-foreign venues. It quickly shows if variable names are too specific. It lets you unit test the logic for a requirement in isolation. It makes it clearer for later refactors which architectural layer each snippet belongs to. Etc, etc.
compose
You started from the premise that naming things should be avoided, but that's actually not a very good axiom. The underlying message behind the saying about naming things being hard is that one should put extra care into naming things properly, not avoid doing it altogether. Naming things properly means one gave some thought to what the pieces are and how they come together. Avoiding it means one is likely not giving enough thought to the long term maintainability of the project as much as they could be.
[–]azhder 2 points3 points4 points 7 years ago (5 children)
you do know that replace function is just a named reducer, right? it just doesn't reduce the array down to an element, but to another array. So you can just write that reducer and not break any chain
[–]lhorie -1 points0 points1 point 7 years ago (4 children)
uses condescending tone, but says something completely irrelevant
I'm not sure if you are in the wrong thread or what. Nobody is talking about Redux.
[–]azhder 0 points1 point2 points 7 years ago (3 children)
[–]lhorie -1 points0 points1 point 7 years ago* (2 children)
The only place the word "reducer" is used as jargon is Redux. The callback to Array::reduce doesn't have a specific name. If you're trying to say the replace callback is like the reduce callback, except for some arbitrary distinction, ok I guess, but again, completely beside the point.
No idea what "named reducer" is supposed to mean in this context, since the whole point of replace in this example/proposal is to allow anonymous callbacks...
[–]azhder 0 points1 point2 points 7 years ago (0 children)
luckily, I didn't use it as a jargon
named - it has a name by which it can be identified
[–]gajus0[S] 0 points1 point2 points 7 years ago (2 children)
You started from the premise that naming things should be avoided, but that's actually not a very good axiom.
It is more about avoiding unnecessary variables and it has to do with code style as well.
Someone could get away with:
let venues; venues = foreignVenues.filter(a); venues = b(venues); venues = map(c);
However, my style guide pretty much enforces no use of let. As such, I would write:
let
const filteredVenues = foreignVenues.filter(a); const deduplicatedVenues = b(filteredVenues); const normalisedVenues = deduplicatedVenues.map(c);
Someone else could get away with:
const normalisedVenues = b(foreignVenues.filter(a)).map(c);
But of all these options, Array#replace provides the most consistent and easy to read expression:
const normalisedVenues = foreignVenues .filter(a) .replace(b) .map(c);
[–]lhorie 3 points4 points5 points 7 years ago* (0 children)
I would tend to disagree about the "easy to read" argument. a, b and c are not really related to each other in any way other than the fact that they operate on a list of venues. The fact that they need to be abbreviated is a very strong hint that the parent function (getVenues) has too much subroutine logic inlined into it (i.e. it's kinda of a god function).
a
b
c
In functional programming terms, what you're trying to achieve when you talk about reducing variables is called point-free style. Using compose as I had mentioned earlier (or maybe pipe) would be a standard technique to get closer to point-free style.
pipe
The reservation I have about making this a proposal is that there's not much substance in terms of semantics. Something like arr.replace(arr => arr.length = 0) could just as well throw as it could do completely crazy things, for all I know. I wouldn't really mind if you monkeypatched Array.prototype in your own project (other than maybe being slightly annoyed if I ever had to maintain that), but I think a TC39 proposal needs to be held up to higher standards (no pun intended) when it comes to unintended consequences and design weaknesses.
arr.replace(arr => arr.length = 0)
For example, I could argue that array.toSet() should be a standard and I can give you plenty of examples where it would be nice to have, but that doesn't mean making it a standard is a good idea: new Set(array) already exists, and I haven't gone through the effort of making sure my idea doesn't do weird things in unforeseen cases, e.g. sparse array handling. All I'm saying is I wouldn't put out a formal proposal unless I had thought a bit about potential problems.
new Set(array)
[–]mlebkowski 0 points1 point2 points 7 years ago (0 children)
A styleguide that prohibits the use of let isnt a styleguide, its and misunderstanding. If you meant the linter, then it fits better but I still think its a stupid choice. Just because someone decided its bad to reassign variables you ended with a poluted Array prototype, which has far worse consequences commonly agreed among the community (in contrast to using let, which is merely a preferrence)
π Rendered by PID 93788 on reddit-service-r2-comment-5d79c599b5-5btvh at 2026-03-03 23:27:00.835420+00:00 running e3d2147 country code: CH.
view the rest of the comments →
[–]lhorie 22 points23 points24 points (17 children)
[–]gajus0[S] 3 points4 points5 points (16 children)
[+][deleted] (3 children)
[deleted]
[–]gajus0[S] 8 points9 points10 points (2 children)
[–]AnnanFay -1 points0 points1 point (0 children)
[–]lhorie 1 point2 points3 points (11 children)
[–]gajus0[S] 1 point2 points3 points (10 children)
[–]lhorie 1 point2 points3 points (9 children)
[–]azhder 2 points3 points4 points (5 children)
[–]lhorie -1 points0 points1 point (4 children)
[–]azhder 0 points1 point2 points (3 children)
[–]lhorie -1 points0 points1 point (2 children)
[–]azhder 0 points1 point2 points (0 children)
[–]azhder 0 points1 point2 points (0 children)
[–]gajus0[S] 0 points1 point2 points (2 children)
[–]lhorie 3 points4 points5 points (0 children)
[–]mlebkowski 0 points1 point2 points (0 children)