+1.
On supplementing %
The a % b == 0
idiom is familiar to programmers. That’s not necessarily a good thing: it clouds our judgement. Familiarity bias is (IMO) the primary factor in our opinions about language features; we’re simply not as objective as we like to imagine.
Does familiarity cover up a problem here? I say yes: % b = 0
isn’t as fluent or as self-evident to newer programmers as .isMultiple(of: b)
. Then there’s also the issue of trapping on zero, an easily overlooked source of bugs. And the pitfall of using % 2 == 1
instead of % 2 != 0
or & 1 == 1
to test for oddness is a mistake I’m sure I’ve made at some point.
Mathematicians are a few centuries ahead of us on the question of whether divisibility needs its own special notation, and they long ago decided that the answer is definitively yes: number theorists write a | b, even though they already have the notation a ≣ 0 (mod b). The rationale for that (readability + the pernicious b = 0 case) was the same in math as it is in programming.
Swift has not been shy about departing from longstanding idioms in the name of improving readability and preventing errors — even in ways unprecedented in related languages. Consider the C-style for loop. The language shouldn’t be shy here either.
On the threshold for inclusion
I'm a fan of ergonomic conveniences like this for readability reasons alone; when they avoid bugs (trap on zero; % 2 == 1
fails to handle odd negative numbers), I’m doubly a fan. But there is still a high standard for adding methods like this to a commonly used type in the stdlib:
- Would the method actually be used in the wild?
- To a reader not familiar with the method, is its meaning self-evident upon reading in context — or at least not prone to misinterpretation?
- Does the name potentially clash with other possible meanings we might also want to add to the type?
Would the method actually be used in the wild?
Well, I certainly would have had occasion in the past use all three of the proposed methods.
I might be lulled into thinking they’re not necessary if I’m working on widget-y apps and web sites for a while … but come the next game, graphics app, or number-crunching task, it all comes rushing back.
To a reader not familiar with the method, is its meaning self-evident upon reading in context — or at least not prone to misinterpretation?
Clearly yes. We all know the words “even,” “odd,” and “multiple.”
Here is my minor quibble: in mathematics, for the assertion “there exists some integer k such that a=kb,” the most widely used terminology is “a is divisible by b.” The word “divisible” means exactly what the proposal says (including always being true when a=0). That’s the term people use in math class from roughly middle school algebra on. It bothers me slightly to be abandoning the preferred term of art for a well-known concept, contrary to the API guidelines.
However, “multiple” is also widely understood; if it’s less prone to misinterpretation, so be it!
Does the name potentially clash with other possible meanings we might also want to add to the type?
It is hard for me to imagine methods with any of these three names have a different meaning that is also correct.
Does this matter enough to bother with?
Swift certainly has bigger fish to fry. The gaps in generic types and reflection are far larger problems.
Why bother with this battle, then? Swift is a language whose design can accommodate little stdlib niceties like these. Having worked in languages both many ergonomic conveniences and few, I’ve come to land squarely in favor of them when they are well designed.
These proposed methods are simple to understand and easy to implement. They prevent errors. Their greatest cost for the language and the community is this discussion thread. If we get too persnickety about including simple, nice things in Swift, then 5 or 10 years down the road, working with the resulting language will be neither simple nor nice.