What is the reasoning behind the lack of conversions when passing parameters

H. S. Teoh hsteoh at qfbox.info
Sat Feb 3 02:14:00 UTC 2024


On Fri, Feb 02, 2024 at 06:27:55PM -0700, Jonathan M Davis via Digitalmars-d wrote:
> On Friday, February 2, 2024 4:49:21 PM MST Carl Sturtivant via Digitalmars-d 
[...]
> > Why is `alias this` conversion permitted with parameter passing?
> > Why isn't the no conversion restriction applied there? Your 'not
> > onerous' argument below could be applied, and the name from the
> > `alias this` declaration could have to be explicitly used. And
> > that would affect only types that have alias this, not
> > *everything* which is what the current restriction affects. Seems
> > like the wrong decision.
> 
> Well, personally, I'd actually be in favor of removing alias this
> entirely, because I think that implicit conversions like it are
> usually a mistake (and they definitely cause problems with templated
> code), but I'm sure that there would be complaints about it, since
> there are cases where it can be useful, and some folks like being able
> to do it. However, my experience in general is that implicit
> conversions are a source of bugs and best avoided, much as they can
> occasionally be useful.
[...]

I agree.  In my early D code I also used a ton of `alias this` - it's
very convenient, and lets me drop in replacements for existing types
without a lot of tedious refactoring work.  After a lot of experience
working with it, though, I've come to think that in the long term it's
not a good idea.  While `alias this` lets you pretend that type T is
type U, in the end it's still type T, and there comes a point where the
distinction becomes important.

In one of my larger D codebases where I liberally used `alias this` for
a handful of very frequently-used types, it got to a point where I had 3
different types for representing exactly the same thing. It really
should have been 1 type, but I had a wrapper type for the underlying
static array using `alias this`, then an extension over this wrapper
some additional functionality.  But (no) thanks to alias this, these
types could interconvert, so for the most part things Just Worked(tm).
Except sometimes they can't, then it's a head-scratching exercise of
asking "now which of the 3 types is being used here, and which one
should it have been?!". This question is a lot harder than it looks when
stuff is being passed between templated generic code, where it's not
obvious which concrete type is actually at work. And of course, there's
the risk of instantiating the same template with 3 different types that
ultimately represent exactly the same thing.  Needless template bloat.

I really should have just refactored the code to use a single,
consistent type throughout.

And in general, my experience has been that implicit conversions tend to
do more harm than good. They're really tempting in the short term
because of the convenience. But in the long term they're really more
trouble than they're worth.  Living without implicit conversions is
inconvenient, but in the long term it helps keep code easier to
understand and more maintainable.


T

-- 
Never trust an operating system you don't have source for! -- Martin Schulze


More information about the Digitalmars-d mailing list