@api: One attribute to rule them All

Zach the Mystic via Digitalmars-d digitalmars-d at puremagic.com
Mon Jan 5 19:29:37 PST 2015


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?


More information about the Digitalmars-d mailing list