Rant: Date and Time fall short of simplicity in D

Jonathan M Davis jmdavisProg at gmx.com
Fri Mar 29 15:08:28 PDT 2013


On Friday, March 29, 2013 17:36:37 Steven Schveighoffer wrote:
> On Fri, 29 Mar 2013 17:17:58 -0400, Jonathan M Davis <jmdavisProg at gmx.com>
> 
> wrote:
> > But std.conv.to is the standard way to convert things, and I don't see
> > how
> > changing how std.conv.to determines how to do the conversion would help
> > us
> > any. Whether there was a to function on the type or opCast really makes
> > no
> > difference if you're using std.conv.to, and if you're not, then the way
> > that
> > the language provides to covert types - casting - works.
> > 
> > Unless you're arguing for using something other than std.conv.to to
> > convert
> > types, I really don't see the problem, and arguably, because std.conv.to
> > is
> > really the standard way to convert stuff, it's what should be used. So,
> > I could
> > see a definite argument for using std.conv.to in code rather than
> > opCast, but I
> > don't see much point in avoiding defining opCast on types, especially if
> > code
> > is then generally using std.conv.to rather than casting directly.
> 
> When I say "cast(Duration)time is ugly and dangerous" you say, "use
> std.conv.to instead." Why?
> 
> It seems you are using std.conv.to as part of the API of core.time types.
> I can't really understand the point of this. There exists a safe and
> necessary conversion (since both provide different features) from a
> TickDuration to a Duration. Why would that be an obscure part of the
> API? Why would the preferable interface be to use a cast? Why does
> std.conv.to have to be involved to get something readable that doesn't
> contain the red-flag cast operator? Both TickDuration and Duration know
> about each other, there is no reason to make this a dangerous operation
> (and yes, casts are dangerous and should be avoided).
> 
> It looks to me like the only reason a cast was chosen over a
> property/method is *so* it will work with std.conv.to. I contend that it
> would be better of std.conv.to was not able to convert these types than to
> have to use cast on it to get this behavior.

std.conv.to is the standard way to convert one type to another. I see no 
reason to introduce stuff specific to core.time or std.datetime to do 
conversions. It should just hook into the standard stuff for that. If 
everything uses std.conv.to for coverting between types, then you don't have 
to worry about figuring out how a particular programmer decided that their API 
should do it - be it with casts or asOtherType toOtherType or whatever. 
std.conv.to is specifically designed so that any type can hook their own 
conversions into it, and then you can just always use std.conv.to for 
converting types.

> If std.conv.to cannot work on type-defined conversions without opCast,
> then it is poorly implemented. There needs to be a better mechanism.

I don't see why. std.conv.to specifically checks for opCast, not just that it 
can cast. So, there's nothing unsafe about it. Having it look for a function 
named convert wouldn't be any safer.

The only reason I see to object to opCast being used is that it's then 
possible to use cast(Type) rather than to!Type, and if you object to casts 
being used that way, then having std.conv.to use opCast makes it more likely 
that cast(Type) will work, because people will define it on their types so that 
they'll work with std.conv.to.

But since opCast is really just syntactic sugar that allows you to use the 
cast operator, and casting rarely works on user-defined types without opCast 
anyway (aside from converting between classes in an inheritance hierarchy), I 
really don't agree that opCast is particularly dangerous. If opCast isn't 
defined, odds are the cast won't work. And if it is, then there's really no 
difference between using the cast operator and an explicit function except that 
by using the cast operator, you're plugging into the language's conversion 
mechanism syntactically, and std.conv.to will then work for your type. And if 
you prefer std.conv.to to casting, then just use std.conv.to.

But the built-in casts are restricted enough on user-defined types, that I 
really don't see any problem with using opCast on user-defined types and then 
casting, and std.conv.to goes the extra mile of only using the cast if opCast 
is explicitly defined, so it won't use any dangerous casts even if there are 
any.

- Jonathan M Davis


More information about the Digitalmars-d mailing list