Not defending javascript because I dislike it immensely, but with javascript being a dynamically typed language, and with the way it handles implicit conversions between types, and with trickiness around NaN, Infinity and null objects, there are sufficient edge cases that writing a correct function to test if some variable contains a positive integer is not as trivial as it is with more sane languages, and is likely to trip up even experienced developers if they miss one or more of those edge cases.
Having pre-written modules that account for all edge cases that have been battle-tested by hundreds, thousands, or even millions of users does have merit.
The main problem here is with the Javascript language, which makes code evolve to things like 'is-positive-integer'.
(That's the whole point of using a dynamic language, what '>' actually does depends on the surrounding code. If you want '>' to type check you should be using a type safe language to begin with.)
The issue I have with this is readability. Type '>' and I know exactly what it does, I know what implicit conversions are involved, and how it would react to a null object. Type 'isPositiveInteger' and I need to check. I can not read your code fluently anymore.
What if sometimes I want the overloaded, type relevant '>', and sometimes I want to do '>' if the inputs are positive integers, and raise an exception otherwise?
This seems to be a very common example in educational materials about how to create a function in some programming language. Perhaps they should all be prefaced with "NOTE: you should not actually make such a function, because its triviality means that every time you use it you will be increasing the complexity of your code", or a longer discussion on when abstraction in general is appropriate and when it is not.
Ditto for any other abstraction --- I've found there's too much of an "abstraction is good so use it whenever you can" theme in a lot of programming/software design books and not enough "why abstraction can be bad" sort of discussion, which then leads to the "you can never have too much" mentality and the resultant explosion of monstrous complexity. Apparently, trusting the reader to think about the negatives and exercise discretion didn't work so well...
Of course we have a number of packages that are truly trivial and should probably be inlined. Npm is a completely open platform. Anyone can upload any module they feel like. That doesn't mean anyone else will feel the need to use them.
I think you'll find that the vast majority of small modules that are widely used are ones that also cover obscure corner cases and do benefit from widespread use and testing.
You don't have to be widely used to be widely used, though. I bet there are tons of developers who would never dream of using left-pad or is-positive-integer, but nevertheless have copies of them (multiple copies?) on their computers due to transitive dependencies.
WRONG. Typical junior developer mistake. Even if we disregard trivial problems such as non-letter input or empty input, this will only work with English and a few other languages. This will TOTALLY fail with e.g. Turkish input (I ı vs İ i).
Not really. (string[0] == string[0].toUpperCase() && string[0] != string[0].toLowerCase()) is the correct way to approach this problem. If toUpperCase() and toLowerCase() don't handle Turkish letters, then that's a BUG in those methods, which should be reported and someone should freaking take responsibility for them and fix them.
Adding another module with a method does not fix the original problem, it just creates more problems for other people to solve.
If "true" is not a valid answer, what would've been one?
Similar code in C# returns the same. E.g. Console.WriteLine("שלום".ToUpperInvariant()=="שלום") returns true.
Hebrew doesn't have upper and lower case, so the question "is this hebrew character capital" is meaningless. So, the function in question should not return just a boolean value; it should have a way to return a third option. (Whether it's nil, a C-style return code, an exception, an enum or something else is irrelevant here.)
Actually, it just means that if you're wondering "if this word starts with a capital", you're asking a wrong question. Instead, you should be asking "if this word is a valid generic name", or "is this word a start of a new sentence", and implement these semantic queries in a language-specific way.
That's true, but I don't think that sofits should be viewed as capital/not-capital letters: they're not semantically altering the meaning of the word in wider context, like capital letters do.
/\p{Lt}/.test(str) would be much more compact, but Unicode properties still aren't available in Javascript regular expressions. It doesn't look like they will be anytime soon. I guess they have some staging system and it's still at stage 0 (https://github.com/tc39/ecma262/blob/master/stage0.md), grouped with lookbehind assertions, named captures, and mode modifiers.
Maybe F1axs knows that at this particular spot the string will never be empty? There are two philosophies in libraries; one is to check for every possible error in the lib function, the other is to state the pre-conditions in the documentation.
> Not that I agree with micro modules (I would rather see a set of js core libs)
Why not both? If you just want one part of a module, you can just import the dependency directly, if you want a whole core lib, you can do that.
Some people really like underscore and import that. I use ES6/7 functions for the most part, but underscore has some useful things I can import on their own.
The three cases you state aren't nearly as hairy as determining whether something is a positive integer.
Someone might do something like ~~n to truncate a float. That works fine until you go above 32 bits. Math.trunc should be used instead. Someone might do something like n >>> 0 === n, and using any bitwise operators will always bake in the assumption that the number is 32 bits. Do you treat negative 0 as a negative integer? Detecting negative 0 is hairy. So, to avoid bad patterns, it makes sense.
For is-bigger-than-5(x), x > 5 is not hairy. For add-1-to-a-number(n), n + 1 is not hairy.
For word-starts-with-capital-letter(word)? That one is actually pretty hairy. There are programmers that would write a regular expression /^[A-Z]/, or check the charCode of the first character being within the A-Z range, amongst other solutions. An appropriate solution, however, would be (typeof word == "string" && word.length && word[0] == word[0].toUpperCase() && word[0].toUpperCase() != word[0].toLowerCase()), because the toUpperCase and toLowerCase methods are unicode-aware, and presently you can't access unicode properties using Javascript's flavor of regular expressions.
People have started to point out the existence of modules in this very vein. And, of course, write them. With two such together, you can probably get is-maybe-5 .
How does that even remotely applies to the "is positive integer" test, and even more so to "it's positive" and "it's integer"?
What's next? is-bigger-than-5? word-starts-with-capital-letter? add-1-to-a-number?