On Monday, 5 January 2015 at 23:48:17 UTC, Joseph Rushton Wakeling via Digitalmars-d wrote:
Here's the rationale. Suppose that I have a bunch of functions that are all intended to be part of the public API of my project. I accidentally forget to tag one of them with the @api attribute,

A more likely scenario is that your library starts small enough not to need the @api attribute, then at some point it gets really, really huge. Then in one fell swoop you decide to "@api:" your whole file so that the public interface won't change so often. I'm picking the most extreme case I can think of, in order to argue the point from a different perspective.

so its attributes will be auto-inferred, but the function is still public, so downstream users will wind up using it.

3 months later, I realize my mistake, and add the @api attribute -- at which point downstream users' code will break if their code was relying on the unintended inferred attributes.

Attribute inference provides convenience, not guarantees. If a user was relying on the purity of a function which was never marked 'pure', it's only convenience which allows him to do it, both on the part of the user, for adding 'pure', and the library writer, for *not* adding it. Adding @api (or 'extern (noinfer)') cancels that convenience for the sake of modularity. It's a tradeoff. The problem itself is solved either by the library writer marking the function 'pure', or the user removing 'pure' from his own function. Without @api, the problem only arises when the library writer actually does something impure, which makes perfect sense. It's @api (and D's existing default, by the way) which adds the artificiality to the process, not my suggested default.

It's quite analogous in this respect to the argument about final vs. virtual by default for class methods.

I don't think so, because of so-called covariance. Final and virtual each have their own advantages and disadvantages, whereas inferring attributes only goes one way. There is no cost to inferring in the general case. My suggestion, (I now prefer 'extern(noinfer)'), does absolutely nothing except to restore D's existing default, for what I think are the rare cases it is needed. I could be wrong about just how rare using extern(noinfer) will actually be, but consider that phobos, for example, just doesn't need it, because it's too small a library to cause trouble if all of a sudden one of its non-templated functions becomes impure. A quick recompile, a new interface file, and now everyone's using the new thing. Even today, it's not even marked up with attributes completely, thus indicating that you never even *could* have used it for all it's worth.

Have I convinced you?

Reply via email to