SE-0246: Generic Math(s) Functions


(^) #41

I’m a little late to this, but I have a few opinions on this proposal.

  • I agree with a lot of the other people here that the .Math namespace is detrimental and unnecessary. This feels like namespacing for namespacing’s sake, and just adds meaningless noise to source code. It’s also inconsistent with the current homes of Float.pi and Double.e, and despite what some people are suggesting, we are not getting rid of those anytime soon, considering how widely used they are.

  • I’m gonna come out and say that I think the Math module providing the free functions just doesn’t make a lot of sense. It’s kind of pointless to import a whole module just to get access to abbreviated function names. I can see myself asking myself “will I be using sin enough in this project to justify importing Math, or should I just stick to the standard library Double.(Math.)sin(_:) function?” which doesn’t seem ideal
    The circumstances also seem pretty contrived,, the whole justification for free functions comes from the fact that Double.Math.cos(x) is so long to type, but that’s an argument for getting rid of the .Math namespace, not for introducing a whole new redundant module.

  • I see a lot of people bikeshedding the log vs ln name. I personally prefer ln but do y’all really use it often enough for it to make sense for it to dominate this much of the conversation?


(Steve Canon) #42

This doesn't exist.

The expectation is that these names will not generally be used in source code. The free functions are the preferred spellings, these are implementation hooks to get customization, and an escape valve when you don't want to transitively export Math. I would underscore them, but the community has shown a pretty clear dislike of "magic" underscored trampolines in the past, so grouping them together under .Math seems like the best option to keep autocomplete lists clear.


(Robert Muckle-Jones) #43

I really like this improvement to Swift. I strongly approve of these elementary functions being available as free functions by importing Math. Compact notation is very important for ergonomics and readability in scientific/mathematical code. The video on the home page of julialang.org talks about exactly this and shows some great examples. Good ergonomics for scientific/mathematical code has traditionally been the domain of scripting languages but I see no reason why this has to be the case - Swift has the opportunity to unite these ergonomics with a full featured strongly typed application development language.


(Xiaodi Wu) #44

Honestly, I would prefer underscored trampolines over another namespace if it came down to the two. But there just aren’t that many static functions on these numeric types, so I really don’t see what we’d be clogging up.


(Joe Groff) #45

I'd be concerned about us having too many different mechanisms for ad-hoc namespacing, because if we ever do get real namespacing, it'll become harder to migrate all the different ways we've found to express namespaces to the proper mechanism. Using an associated type as a namespace also feels particularly problematic to me because it has runtime ABI impact; the associated type needs an entry in the parent protocol's witness table, necessitates the existence of a second protocol and parallel set of conformances, and makes dispatching to functions defined on the associated type require an extra two steps to fetch the associated type then dispatch to the implementation on the associated type.


(Steve Canon) #46

Isn't the alternative that all the implementation hooks need entries in the parent protocol's witness table, though? Is that better?

Can you clarify what you mean here? It requires a second protocol, but the conformances mostly only show up on that second protocol.

In practice, these get specialized and lowered to direct calls to the underlying libm functions. If you manage to construct a context where specialization doesn't occur, you're already dead because addition is a call; an extra layer or two of indirection for a call to exp( ) will be the least of you worries.


(Joe Groff) #47

Performance isn’t really my primary concern. As you noted, the conformances are primarily intended to be used for specialization; nonetheless, the runtime data structures must exist. That’s my bigger concern—yes, the witness table entry must live somewhere, but if you’re breaking this up across two conformances, you’re paying twice as much fixed overhead for the protocol and conformance metadata. Furthermore, since this becomes part of the ABI, we can’t ever take it away completely if we have a better namespacing mechanism in the future.


(Steve Canon) #48

I don't see how you get to "twice as much" (feel free to explain offline if we're wandering into the weeds here).


(Joe Groff) #49

Instead of one protocol and one conformance per type, you now have two protocols and two conformances per type, and therefore an extra protocol descriptor and a conformance descriptor plus witness table header of overhead per conforming type.


(Steve Canon) #50

Isn't that O(1) cost dominated by the O(n) individual functions?


(Joe Groff) #51

Yes, but all I’m saying is that there is an additional, permanent cost.


(^) #52

oh rip. if you really think about it then though, it would make a lot of sense to add it, and phi to the standard library, and it would suck if pi lived in Double, but e and phi lived in Double.Math.


(Zak Barlow) #53

This proposal looks really good to me. I have a preference for ln over log (from my Physics background) but I would be more than happy to have both included, which I think gets the best of both worlds. Those of us who use ln would be able to do so, and vice versa.


(Svein Halvor Halvorsen) #54

I think this is far worse. I’d much rather have a single canonical name, than confusingly using two names for the same function. Even if that one name is log (shudders)


(Lukas Stabe 🙃) #55

I don't really care where the functions live, but constants like this should imo be on the type itself, so we can use the leading-dot shorthand to refer to them.


(Steve Canon) #56

Hi all --

I pushed some updates to the proposal and implementation based on feedback received so far. These changes are mainly around the division of API between ElementaryFunctions and Real:

  • atan2 , erf , erfc , gamma , and logGamma have been moved from ElementaryFunctions onto Real . The rationale for this is threefold: atan2 never made much sense for non-real arguments. Implementations of erf , erfc , gamma and logGamma are not available for complex types on all platforms. Finally, those four functions are not actually "elementary", so the naming is more accurate following this change.

  • hypot has been added to Real. I would still like to have a better pattern for this functionality in the future, but it's a sufficiently useful function that there's no reason not to provide it now.

Three requested changes that I haven't made, with rationale:

  • I have not made any change to the spelling of log. I was more or less neutral between the two names (ln is more precise, but loses the semantic grouping of the log prefix shared by all other logarithms), but @nevin's observation that ln is confusable with in in many fixed-width fonts tips the balance back towards log for me. In any event, this is a change that could be made post-review if the core team feels strongly in favor of ln.

  • I have also not added new constants. The only constant that I could make a totally clear-cut case for including is e, and spelling here becomes important. The leading-dot shorthand makes .e possibly too terse if defined on the type itself. .Math.e would be clearer, but doesn't actually compile presently (I think that's a bug, which I'll follow up on). I'm definitely not opposed to adding this once these issues are resolved.

  • I'm keeping the .Math prefix on the implementation hooks for now. The proposal can be made to work either way without any major technical issues, so this is mainly a question of style: "do we want to encourage static-member namespaces?"--and that's really a question for the core team.

As a reminder, review runs through next Wednesday. Please don't hesitate to ask if you have any questions about these changes.