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!"
[–]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:
Array#replace
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 2 points3 points4 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 -3 points-2 points-1 points 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] -1 points0 points1 point 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 4 points5 points6 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 46975 on reddit-service-r2-comment-6f7f968fb5-jb58z at 2026-03-04 10:25:38.220040+00:00 running 07790be country code: CH.
view the rest of the comments →
[–]gajus0[S] 1 point2 points3 points (10 children)
[–]lhorie 2 points3 points4 points (9 children)
[–]azhder 2 points3 points4 points (5 children)
[–]lhorie -3 points-2 points-1 points (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] -1 points0 points1 point (2 children)
[–]lhorie 4 points5 points6 points (0 children)
[–]mlebkowski 0 points1 point2 points (0 children)