15 ms·
> xs = ['10', '10', '10'] > xs.map(parseInt) [10, NaN, 2] Javascript is beautiful.
by granttimmerman 13y ago
> xs = ['10', '10', '10']
> xs.map(parseInt)
[10, NaN, 2]
Javascript is beautiful.
- TazeTSchnitzel 13y agoIt's due to parseInt having an optional second parameter, the radix, and map passing the index as the second paramater, hence: xs = [ parseInt('10', 0), parseInt('10', 1), parseInt('10', 2) ]
- jisaacks 13y agoAnd since 0 is falsy we get 10 for base 0.
- TazeTSchnitzel 13y agoWhich is odd. I wonder why they checked for falsiness and not the argument being undefined.
- kevincennis 13y agoIt's not exactly checking for falsy values. Although all falsy values will lead to a radix of 10 being applied. parseInt internally uses the ToInt32 abstract operation on the radix parameter. Once it has that value, it explicitly looks to see if the value is 0. If it is, it uses a radix of 10. https://people.mozilla.org/~jorendorff/es6-draft.html#sec-parseint-string-radix https://people.mozilla.org/~jorendorff/es6-draft.html#sec-pa... Edit: I hope that doesn't come off as pedantic. My point wasn't to disagree as much as it was to just add some further explanation.
- meowface 13y agoThis is HN, there's no such thing as being pedantic. :)
- Thirdegree 13y agoOr rather, there is but it's thoroughly welcome.
- mturmon 13y agoAlthough keep in mind that excessive pedantry is frowned upon.
- octatone2 13y agoIt's not optional if you lint your code :)
- davidkassa 13y agoThank you. I read many comments to find an explanation.
- deleted 13y ago[deleted]
- just2n 13y agoThere are so many good WTFs in JS, but this is not one. parseInt expects 2 arguments and Array.prototype.map provides 3 to the callback it is given. Both of these facts are very well documented and known. var mappableParseInt = function(str){ return parseInt(str, 10); }; ['10', '10', '10'].map(mappableParseInt); I'd suspect this snippet is more a snipe at people who don't know JS very well and expect parseInt to be base-10 only.
- CatMtKing 13y agoYou could say it's a snipe at the weak type system that Javascript has. I dunno, as someone without much experience with Javascript, it is a little odd that arrays return the index alongside the value by default.
- xiaomai 13y agoarrays don't do that, but map() does. Normally in js you can just ignore arguments you don't care about, but it does lead to surprises like this one.
- anaphor 13y agoIt has little to do with the type system. Variadic arguments can be typed given a type system that supports it.
- deleted 13y ago[deleted]
- hcarvalhoalves 13y agoI don't think `parseInt` accepting an optional second argument is the surprising behavior there. The real WTF is `map` passing more than one argument, and the loose behavior of JS regarding argument passing overall.
- briantakita 13y agoIt's only WTF because it's not the same as other implementations of map. Once you can internalize the map implementation, it's no longer WTF & actually makes sense.
- conradk 13y agoJust like with any language, as long as you read the docs of the stuff you use, you don't get this problem (you might get others with automatic type conversion and missing arguments like the speaker says, but not this)... this is just stupid. Try this: int subtract(int b, int a) { return a - b; } int test = subtract(5, 3); // != 2, just read the damn docs Oh, C sucks now ! The talk is quite fun and interesting to watch though. And the end is pretty cool.
- coldtea 13y agoThe thing is, good language design means you don't have to read the docs. The number one thing taught at user interaction / usabillity courses is that users don't read the documentation. Or skim it and go directly to one or two parts they want to check (Sure, some bizarro outliers do read it all). Besides, a golden rule from the UNIX era is the "principle of least surprise". Don't define stupid behavior as default, as in this case (both for parseInt and Map).
- nathansobo 13y agoBoth behaviors make sense in isolation. It's not always so easy.
- gary_bernhardt 13y agoJuggling these interactions is exactly what makes good language design so difficult and time consuming. In the talk, I mention JS' ten-day design time several times for exactly this reason. Language design is hard and ten days just isn't enough time to carefully consider how everything will fit together. Try to imagine a programmer, even a brilliant one, noticing the map/parseInt interaction ten days after starting to learn JS, especially in 1995 when these high level languages were far less common. Seems unlikely!
- tolmasky 13y agoArguably the issue is not with the behavior but rather a deeper design problem within the language itself. Notice that in Obj-C no one would ever get confused regarding the second parameter of parseInt:withRadix:.
- nathansobo 13y agoI just wrote this line about two hours ago and my tests weren't thorough enough to catch the bug it introduced. Just when I thought I knew JavaScript. Thanks for saving me some time.
- iamthepieman 13y agoI'm sure you know this by now but you can keep the syntax and use Number instead xs.parseInt(Number)
- matb33 13y agoI think xs.map(Math.floor) takes the cake if I recall speed tests properly
- bsder 13y agoAlways give the base to parseInt in Javascript. Always. The moment you don't, all kinds of bugs follow. I have to go cry now at the number of times this has bitten me.
- TazeTSchnitzel 13y agoAre there any other problems aside from octal?
- ajanuary 13y agoNot just javascript, a whole bunch of language's parseInt implementation will interpret the base from a leading zero etc.
- _random_ 13y agoAlways remember - it's not a language but a loosely parsable texty thing.
- v413 13y agoYou need: ['10', '10', '10'].map(Number);
- octatone2 13y agovar xs = ['10', '10', '10']; xs.map(function (str) { return parseInt(str, 10); }); > [10, 10, 10] Fixed that for you. Why? map callback params: (value, index, originalArray) parseInt params: (string, radix) Your code is passing the map array index to parseInt's radix.
- ajanuary 13y agoA useful function function overValues(f) { return function(x) { return f(x); } } Then you can do ['10', '10', '10'].map(overValues(parseInt)); However, usually you're going to want to do the equivalent of this ['0101', '032'].map(function(s) { return parseInt(s, 10); }) Because Javascript interprets a leading zero as an indicator of base.
- nollidge 13y agoI think you accidentally a word... > as an indicator of base. As an indicator of base 8 (octal).
- medikoo 13y agoWhere people use parseInt, they usually should use Number: ['10', '10', '10'].map(Number); // [10, 10, 10] ;)