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

Carl Sturtivant sturtivant at gmail.com
Thu Feb 8 19:57:52 UTC 2024


On Saturday, 3 February 2024 at 02:14:00 UTC, H. S. Teoh wrote:
> 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.

The above is overtly about implicit conversions as a consequence 
of using `alias this`. I largely agree about that particular 
construct. It can lead to conversions occurring almost anywhere a 
value of a type containing the `alias this` occurs, i.e. 
*pervasive* implicit conversion.

Another place where implicit conversions occur is in 
initialization in a variable declaration, where a single 
parameter constructor of the variable's type may be implicitly 
called. I think this is a good thing, and I haven't seen any 
complaints about this in D despite looking for them. Here 
implicit conversion is confined to only one kind of context. It 
is not pervasive.

> 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.

Perhaps that's because various implicit conversions have often 
been defined dangerously in the languages you have used.

I think having some flexibility to define a single parameter 
constructor of your type to be implicitly called in a narrow 
context only by flagging it in your type's definition with say 
`@implicit` is valuable.

It would only occur when passing a value to a parameter in the 
same way as it would be already be implicitly called when 
initializing a variable of your type to such a value. So the 
context for conversion would be limited, and have the same 
semantics as initialization does now in D.

It would simply turn parameter passing into limited 
initialization for your type. The same limited initialization 
that D already has in variable declarations with initialization.

Furthermore, if the view is that implicit conversion should be 
limited by default, the semantics of variable initialization 
could now be limited, and only constructors annotated with 
`@implicit` could be implicitly called in initializations too.



More information about the Digitalmars-d mailing list