auto: useful, annoying or bad practice?

H. S. Teoh hsteoh at quickfur.ath.cx
Fri May 4 16:54:16 UTC 2018


On Fri, May 04, 2018 at 12:12:09AM -0400, Nick Sabalausky (Abscissa) via Digitalmars-d wrote:
[...]
> The problem with structural typing is that it's unable to distinguish
> between intended matches and accidental, unintended matches. This is
> because it doesn't REQUIRE types/functions/etc to clearly state, "Yes,
> I *intend* to be implementing interface XYZ". Or perhaps more
> accurately: "Yes, I *intend* for this to satisfy isXYZ!T". (Where
> "isXYZ" might be something like "isInputRange" or "isInfiniteRange",
> or both, etc.)
> 
> Note the all-caps "REQUIRE" in the paragraph above. That is to say,
> it's not enough for the developer of struct Foo to toss in...
> 
> static assert(isXYZ!Foo);
> 
> ...because the problem doesn't lie with the "intended matches". The
> problem lies with the "unintended matches". And that static assert
> does nothing to help isXYZ figure out that some other type, Bar, from
> some other package, is NOT deliberately designed to satisfy isXYZ even
> if it just happens to *look* like it satisfies it purely by chance.

This is a good point.  However, I'm failing to see it as a big problem,
because for it to be a problem in the first place, you have to have
*deliberately* passed an object of said type into a function that
expects that particular concept.  Using your previous example, if
somebody declared a JackInTheBox type that "accidentally" has .front,
.popFront, .empty but not actually intending to be an input range, this
is not a problem until you *explicitly* pass a JackInTheBox to something
that expects an input range.  Just because JackInTheBox happens to
accidentally implement the input range API without intending to have
input range semantics, doesn't by itself cause any problem.  As long as
you don't try passing it off as an input range, there's nothing to worry
about.

And even when this explicit passing is done, what's the worst that could
happen?  The JackInTheBox wouldn't actually implement input range
functionality and would cause a bug.  So you'd just debug it like you
would debug any other problem.

I'm not saying it's ideal, but it doesn't seem to be the huge big
problem that people are making it out to be.


[...]
> So back you your question: How else would you do DoI?
> 
> Answer: By making isXYZ!T reject all T which DO NOT satisfy a
> deliberate, cannot-be-an-accident, condition of isXYZ's choosing.
> 
> Thus, type T *cannot* satisfy isXYZ without T's developer saying "Yes,
> I hereby certify it is my deliberate intention that T satisfies isXYZ
> and that, if it does satisfy, it is by my own intention and not by
> coincidental happenstance."
> 
> The exact details of this condition aren't terribly important, but I
> like Neia's suggestion of utilizing UDAs for this purpose. An old idea
> I had before UDAs existed was to require a dummy member enum named
> something like _satisfies_module_foo_bar_isXYZ, which of course would
> be abstracted away by something more convenient...a mixin or such (but
> nobody seemed remotely interested). But I like the UDA idea better.

Yeah, the UDA idea is a pretty good one.  I might even adopt it in my
code. :-)


T

-- 
Fact is stranger than fiction.


More information about the Digitalmars-d mailing list