6 ms·
The surprising bit comes in with the fact that: 1. parseInt is used with only a single argument in most cases. 2. Only the first argument of map is used in most
by matharmin 7y ago
The surprising bit comes in with the fact that:
1. parseInt is used with only a single argument in most cases.
2. Only the first argument of map is used in most cases.
Using multiple parameters for those are so uncommon that it's easy not to realise that it's supported.
_If you know all of that_ it may not be surprising to you, but in most cases there is no need for the average developer to know it, making it very surprising when it crops up like this.
- acdha 7y agoThere's some interesting history for awareness of the first issue: parseInt used to be a notorious source of bugs and so it used to be more common to see it with a second argument on any project which used a linter in that era. ES5 deprecated that behaviour and it's been widespread enough that code which started in the IE9+ era now looks like the very old buggy code omitting the radix, so anyone getting started relatively recently quite reasonably may never have needed to learn about it: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt#ECMAScript_5_removes_octal_interpretation https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe... https://eslint.org/docs/rules/radix https://eslint.org/docs/rules/radix
- sdegutis 7y agoI didn't know about the second parameter until I saw it in a TypeScript signature a few months ago, which acted as a sort of warning to me to avoid using it incorrectly. But TypeScript doesn't catch this specific bug because it's technically correct[1] from an API stand-point, as the second parameter to parseInt is a number and the second argument to map's callback is a number. For as many situations as TypeScript genuinely helps you, there are just as many situations where it gives you false security, like in this case, and I'm starting to consider not using it anymore. [2] [1] not actually "the best kind of correct" despite popular television quotes [2] https://sdegutis.com/2019-06-20-considering-removing-typescript https://sdegutis.com/2019-06-20-considering-removing-typescr...
- carlmr 7y agoYeah, the problem this one time isn't typing but the JS developers implementing map wrong. Map should not take two arguments. There should be a different function like enumerate in in python for this.
- sdegutis 7y agoThere's nothing wrong with Array#map passing callback(val, i, array), it's a legitimate feature, and the two other arguments can be omitted in actual callbacks. It just means we need to be aware of how it works, which is basically true about any programming language, any standard library, and basically any kind of tool that any kind of professional uses, whether abstract or literal: know how to use your own tools, and avoid blaming the wrench because it's a poor excuse for a hammer.
- acdha 7y ago> know how to use your own tools, and avoid blaming the wrench because it's a poor excuse for a hammer This is, of course, why famously machine shops simply put up signs saying “don't touch the whirring metal” rather than using safety guards and similar measures. I don't disagree that it's useful to have the extra arguments for map but the part which is really deadly is ignoring extra arguments, even if it's obvious why backwards-compatibility made changing it unlikely. I really wish that JavaScript had implemented keyword-arguments when the benefits had become obvious because when features like map were added a decade or two later they could have been defined as passing arguments by keyword and causing an error when given a function which didn't accept those names.
- jmull 7y agoWell, the average developer should use a lint tool with Javascript. A bunch of confusion points in Javascript (including this one) have been well understood for a long time, best practices have been developed to deal with them, and mature tooling exists to easily enforce them. Put another way: If you are unsure, go download eslint along with the plugins for your environment, and find/create a ruleset that turns on almost everything.
- lucideer 7y ago> in most cases there is no need for the average developer to know it This may come off as arrogant but.. I'll proceed nonetheless. There is a need for the average developer to know the interfaces of the functions they're choosing to use. They're well documented, and the documentation is neither hard to find, nor difficult to read. There may be an argument here for strongly typed languages -vs- weakly typed ones, where often some of the ambiguity around optional function parameters is eased, but most languages have optional function parameters, this is not in any way unique to JS. And parseInt and [].map are very common JS methods: this is not some obscure API not all devs would be unfamiliar with, these are built-ins.
- egeozcan 7y agoI don't understand why this is downvoted to death without any replies. Sounds like a reasonable opinion but I'd also love to hear why people think it's downvote-worthy.
- guitarbill 7y agoNot a downvoter, but I'll have a go: You might be a dev who isn't very familiar with Javascript, but you still need to fix it. Or you might be having an off day. Or you're writing a critical fix under a lot of pressure and simply forget about the issue. And I'll bet if this code was being reviewed, most devs would still overlook the issue. There are many real world scenarios where it isn't so easy or clear cut. We're all human, and we make mistakes. In other fields, we try and reduce how easy it is to make these mistakes. Some things will always be dangerous like table saws. But a programming language? Anyway, the "deal with it"/"get good" mentality just seems like a lack of empathy. Not to mention the arrogant in-group thing of "oh, you don't know <wart x> of my favourite but flawed language? you must not be a good dev". And the fact that fixing something like this could cumulatively save a huge amount of brainpower for current and future devs.
- wutbrodo 7y agoThe hilarious thing about the get-good arguments is that it's proponents don't realize that they're talking about expending effort _for nothing in return_, especially in cases like the server-side where nobody is forced to use Javascript. You can say the same thing to Pythonistas who are fussed by memory management, but the tradeoff of that intuitiveness is performance (which is being somewhat obviated by newer languages like Rust, which have their own challenges to learn). The actual task you're trying to do is more complex, so the knowledge required is too. In Javascript's case, the thing you're becoming an expert in is the path-dependent history of dumb language decisions by people who never should have been let anywhere near a language. It's beyond me that people don't understand why this would bug some, at the very least because it was so easily avoidable.
- plausibilities 7y agoWhy would you use parseInt over Math.round if you only expect a single arg? Seems like you'd only want to use parseInt if you expect to need radix changes at some point, e.g. converting between hex strings, decimal values, and binary strings ['1', '7', '11'].map(Math.round) // => [1, 7, 11] [["00000001", 2], ["00000111", 2], ["0x0B", 16]].map(x => parseInt(...x)) // => [1, 7, 11]
- paulgb 7y agoTo someone reading the code, parseInt actually describes what your intent is while Math.round just happens to work because it coerces the type.
- bemmu 7y agoIf you want to get terse ['1', '7', '11'].map(x => +x)
- jacobolus 7y agoThis coerces to a number, but not to an integer.
- reaktivo 7y agoI would hate to see it in code that is being shared in a team, but the following works: ['1', '7', '11'].map(x => ~~x)
- plausibilities 7y agoIf I didn't care about rounding I'd just use a primitive constructor ['1', '7', '11'].map(Number)