named arguments, string interpolation, please stop.

H. S. Teoh hsteoh at qfbox.info
Fri Jan 12 01:21:32 UTC 2024


On Fri, Jan 12, 2024 at 12:42:44AM +0000, max haughton via Digitalmars-d wrote:
> On Thursday, 11 January 2024 at 23:44:02 UTC, deadalnix wrote:
> > On Thursday, 11 January 2024 at 19:33:48 UTC, Walter Bright wrote:
> > > On 1/11/2024 5:07 AM, deadalnix wrote:
> > > > such as @nogc, has been a productivity disaster
> > > 
> > > I don't really understand this. Just don't use @nogc?
> > 
> > And don't use any library. Got it.
> 
> The thing with @nogc and ESPECIALLY betterC in a library context is
> that it adds more and more decisions everywhere - O(2^N)? And that's
> before all the attribute spam.

Exactly, it's causing D's already-small ecosystem to be fragmented even
more.

Now instead of one library that works for all D code, you have libraries
that use the GC so they're incompatible with betterC and @nogc projects,
libraries that don't use GC but still use some D feature not in betterC,
so the betterC people are left out, then you have @nogc libraries that
the GC crowd wouldn't use because it requires you to pass allocators and
all the rest of the spam associated with manual memory management.

The only way a library author can deal with this mess is (1) write in
the most restricted language subset, i.e., betterC + @nogc, so that it's
usable by everybody. But the GC crowd will be unlikely to use it,
because it will lack the conveniences they're accustomed to, the API
will have manual memory management paraphrenalia that doesn't fit well
with the rest of user code. Plus this is also a much higher bar for the
library author, so you're further limiting the already small number of
people who are writing D libraries.  Or (2) be opinionated and write a
GC-using library, in which case the betterC / @nogc people won't use it.
Either alternative leads to ecosystem fragmentation. Or write a @nogc
library but the betterC people won't use it.  Etc..

//

Now, this is only at the library level.  When you come down to the
function level it gets worse. Take for example a library that has a
function to register a callback to be triggered when some event occurs:

	void registerCallback(void delegate() cb);

Problem: @safe code can't call this. @nogc code can't call this. BetterC
code can't call it either. What to do? Add the most restrictive
attributes so that everyone can call it:

	extern(C) void registerCallback(void delegate() cb) @safe @nogc;

Oops, BetterC does not support delegates. Guess we have to lose that
subset of D users:

	void registerCallback(void delegate() cb) @safe @nogc;

Still no good. The function will happily take a delegate in the `cb`
parameter, but it can't do anything with it, it cannot be called from
anywhere, the delegate is @system and may allocate.  Next stab:

	void registerCallback(void delegate() @safe @nogc cb) @safe @nogc;

OK, now the function body can actually call `cb`. But wait, now the
function is no longer usable with @system callbacks. Nor with allocating
callbacks.  Solution?  Templatize it and let the compiler figure out the
attribute soup:

	void registerCallback()(void delegate() cb);

Finally, a solution?  Nope, there can only be one instantiation of this
template, and the inferred attributes will be the most restrictive that
still allows the function body to compile.  No matter what attributes
the compiler infers for it, it will exclude *some* use cases. For
example if @safe was inferred, it makes the function unusable with
@system callbacks.  If @nogc was inferred, it cannot be used with
allocating callbacks.  If it was inferred pure, it cannot be used with
an impure callback.  So the only code that can actually call this
function is pure @safe @nogc nothrow.  Meaning that it's useless for any
code that's impure, @system, allocating, or uses Exceptions.

The only way around this is to create 2^N versions of this function, one
with each combination of attributes, so that it's fully generic for all
of its intended audience.

	void registerCallbackSystem(void delegate() @system cb) @system;
	void registerCallbackSafe(void delegate() @safe cb) @safe;
	void registerCallbackNoGc(void delegate() @nogc cb) nogc;
	void registerCallbackSafeNoGc(void delegate() @safe @nogc cb) @safe@ nogc;

Most library authors aren't going to bother doing this; they will just
pick whatever attribute set suits them, and not bother about the rest.
Net result: ecosystem fragmentation.


T

-- 
In theory, there is no difference between theory and practice.


More information about the Digitalmars-d mailing list