Discussion Thread: DIP 1032--Function pointers and Delegate Parameters...--Community Review Round 1

H. S. Teoh hsteoh at quickfur.ath.cx
Wed Jul 29 16:30:50 UTC 2020


On Wed, Jul 29, 2020 at 01:11:43AM -0700, Walter Bright via Digitalmars-d wrote:
> On 7/28/2020 9:45 PM, H. S. Teoh wrote:
[...]
> > It's basically the same idea as inout: as far as the function body
> > is concerned, it's pure (resp. const); but to the caller, it could
> > be pure or impure (resp. immutable/mutable) depending on what was
> > passed in. I argue that this would be much more useful than what
> > this DIP proposes.
> 
> The only time you'd need fewer attributes on delegate is if the
> function never actually calls it. I submit that this is a relatively
> rare case, and can be handled other ways (like making the function a
> template and letting it infer its attributes).

It's not a rare case at all in generic code.  For instance, you're
implementing iteration over some container with a callback for
user-supplied operations to be run on each element.  You'd like the code
to be maximally reusable, regardless of what attributes the
user-supplied callback may have.  The function body itself is pure /
@nogc / whatever, besides that single call to the user-supplied
callback.  You'd like for the compiler to enforce purity / @nogc / etc.
in the function body as a safeguard in case you screw up.

But currently, the only way to achieve this is to template the code,
which means 2^N copies of *exactly the same generated code* where N is
the number of attributes you'd like to support. It's just like inout:
you *could* in theory do without it, just templatize the function and
let it create a new instance per combination of attributes, even though
the generated code is instruction-by-instruction identical. But having
inout allows you to reduce this template bloat.

Furthermore, currently you cannot actually write *any* attributes on
your function at all, because as soon as you write, say, 'pure' on your
function, it's no longer usable from impure code (the user can no longer
pass in an impure delegate, even though, as far as your function's body
is concerned, the purity of the delegate is completely irrelevant). The
only way to get the compiler to enforce purity checks is to use this
workaround:

	auto myFunc(D)(D callback)
		if (is(D == delegate))
		{ ...  }

	pure unittest {	// N.B. unittest is marked pure
		auto dg = ... // some pure callback

		// force compiler error if myFunc is impure in spite of
		// dg being pure
		auto result = myFunc(dg);
	}

This hack is widely used in Phobos code precisely because there is
currently no way to express that "this function's purity depends on the
purity of the callback argument".

And it's not even a foolproof workaround, because if you don't compile
with -unittest, the check is skipped.


T

-- 
To err is human; to forgive is not our policy. -- Samuel Adler


More information about the Digitalmars-d mailing list