SE-0246: Generic Math(s) Functions

Swift already has free functions for the most common mathematical functions, they even get their own special status as operators. I am talking about plus, multiply, divide, modulo etc. There is therefore precedent for treating certain ubiquitous, unambiguous, and established functions as special and giving them more compact representation, especially seeing as they often end up getting repeated multiple times on the same line. I think to a person who writes numeric code the elementary functions are essentially "operators". Having these as free functions seems perfectly "Swifty" to me.

4 Likes

A key difference (imo) here is that the operators operate on two arguments, neither of which can be said to be the "main" argument. Both sides of an add, mul, ... are equally important, and a.add(b) wouldn't really reflect that.

But for something like a sinus, that is not the case. And if we write "the name of the user" as user.name, why not write "the sine of x" as x.sin? I'm not necessarily saying that's how it should be, but I think there are interesting alternatives to consider here.

2 Likes
English Deutsch
the sinus die Nebenhöhle
the sine der Sinus
2 Likes

It's a valid class of functions in math with some nice behaviour, although I'm not sure how consistent the definition is across different textbooks/authors. But there should be some reasonable agreement about stuff that is obviously in this class (e.g. polynomials) and stuff that obviously isn't (like erf and gamma). Of course that name might be somewhat opaque to non-mathematicians, but I'm not sure what a better name would be.

1 Like

Well, an easy alternative would be ElementaryMathFunctions. Just like Real/RealNumber - not everybody is thinking in a numerics context all the time. It's kind of rude to just gobble up such broad English words for domain-specific purposes.

If it is important to keep the exact name ElementaryFunctions, that's the kind of thing which should be namespaced. It's a very generic term which would be confusing to non-numerics programmers.

Protocol namespacing is actually pretty trivial to implement. We could do that and call this protocol Math.ElementaryFunctions.

Both are much better than leaving this very vague name floating around the standard library.

1 Like

Respectfully, I'm not a numeric programmer and am not confused by it.
As I am not confused by Real. Anyone who spent a bit of time programming would know that it refers to numbers and not strings.

3 Likes

I believe the authors are planning to revise this again to remove the Math namespace, so I'm extending this review until Monday. I'll make sure the thread is notified when those revisions are live.

8 Likes

The proposal has been updated.

Specifically:

I have dropped the .Math pseudo-namespace associatedtype from the protocols. In earlier versions of the proposal, the static functions were spelled Float.Math.sin(x) . This was motivated by a desire to avoid "magic" underscore-prefixed implementation trampolines, while still grouping these functions together under a single .Math in autocompletion lists. Whatever stylistic benefits this might have were judged to be not worth the extra layer of machinery that would be fixed into the ABI even if we get a "real" namespace mechanism at some future point. These functions now appear simply as Float.sin(x) .

3 Likes

Looks good to me, i fully support it as is.

One question remains tho — now that the function names have been shortened to T.sin(x), (or in most type contexts, .sin(x)), do we really think it’s still worth the effort to vend a whole Math module just to get rid of the leading dot?

// available everywhere 
let x = .cos(phi) * .cos(theta)

// so many conciser 
let x = cos(phi) * cos(theta)
1 Like

The dot is frankly pretty ugly.

More seriously and more importantly, the Math module lets us obsolete the concrete free functions defined by the Platform module while maintaining source stability.

Having the dotless free functions also allows users more flexibility with whitespace:

2*.cos(phi) // syntax error 
2*cos(phi)  // OK!

and, as @Nevin noted, helps autocomplete.

6 Likes

Right, and it is to be noted that accomplishing this--maintaining source stability (without introducing pervasive ambiguities) while vending generic global functions--can only be done in a first-party library through Swift Evolution. If we don't do that here, no third party can do so, because none can remove the existing free functions.

4 Likes

There’s no autocomplete while typing the dot-prefixed static functions in the line you wrote. There is for the free functions.

2 Likes

I have a slight worry that Math is a bit too broad as a module name. I work on a maths-related product and although we don't currently have any internal module called Math (and probably won't), I could imagine that we did or that other projects might. Of course, ultimately this is a namespacing problem, but I wonder if picking something more along the lines of SwiftMath wouldn't be slightly safer.

Apart from that minor concern, the updated proposal seems much easier to understand and quite sensible. So +1 from me.

3 Likes

I don't know that Swift has a firm policy about this as a language, but I would definitely recommend against ever using generic names for non-language-provided libraries. There should always be something of a "brand" in your module names, even internal ones — that brand can be a company name or an open-source project name or even just your own given name, but there should be something distinctive about the library name that makes it unlikely that anybody else would choose it. Naming a library something like Math or System or Database is frankly a little presumptuous for a project without community blessing (it'd be fine for, say, the server working group to pick such a name, although even they should consider whether the base language might want it eventually).

4 Likes

This is a fair point, but I wouldn't assume that such a policy exists as of yet. For example, IBM-Swift has packages with names such as Health or, particularly bad, Configuration. There is a dependency we use that is called OrderedDictionary, even though it is quite conceivable that other implementations of ordered dictionaries might exist. One can easily find dozens of examples of popular packages that use very generic names, such as Algorithm, Presentation, Cache, etc. It would be nice if everyone abided to certain naming standards, but especially if they're not official or semi-official (like e.g. Java's reverse-DNS package naming conventions), I doubt the problem will just solve itself. (There's even BaseMath, currently, and at least a repository that is called Math, even though the module name itself is fortunately SGLMath.)

Apparently, this problem has been discussed before.

1 Like

I'll raise it to the rest of the Core Team; we may want to make a policy statement about it.

4 Likes

Swift should be enhanced with better options for module aliasing and disambiguation rather than forcing the community to regress to prefix naming.

5 Likes

I misread john's statement, he was specifically referring to module names. deleted my post

SE-0246 has been accepted with modifications. Any discussion of module namespacing as a general language feature should be taken to a dedicated thread in the Evolution > Discussion category. Any other discussion of this proposal should continue in the acceptance announcement thread.

As always, thank you for contributing to Swift.

5 Likes