Blog post: What D got wrong

Jonathan M Davis newsgroup.d at jmdavisprog.com
Thu Dec 13 01:28:44 UTC 2018


On Wednesday, December 12, 2018 3:49:51 PM MST H. S. Teoh via Digitalmars-d-
announce wrote:
> If the delegate property thing is the only real use case for @property,
> it seems quite out-of-proportion that an entire @-identifier in the
> language is dedicated just for this purpose. One would've thought D
> ought to be better designed than this...

Originally, the idea was to restrict property syntax to functions marked
with @property, which would mean no more lax parens. If it's a property
function, then it must be called like one, and if it's not, then it must be
called as a function (i.e. with parens), whereas right now, we have this
mess where folks can use parens or not however they feel like. That doesn't
work well with being able to swap between property functions and public
variables, and it makes generic code harder, because in general, you can't
rely on whether something is called with parens or not, meaning that the
symbol in question has to be an actual function (where parens are optional)
instead of being allowed to be a different kind of callable (which requires
parens) or be a variable (which can't have parens). @property would have
fixed all of that by forcing functions to either be called with or without
parens based on what they're used for, allowing generic code to rely on more
than convention ensuring that symbols are called consistently with or
without parens (and thus allow symbols other than functions to be reliably
used in place of functions where appropriate). So, as originally envisioned,
@property was anything but useless.

However, all of that became extremely unpopular once UFCS became a thing,
because most folks didn't like having an empty set of parens when calling a
templated function that had a template argument that used parens, and as
such, they wanted to be able to continue to drop the parens, which goes
against the core idea behind @property. So, the end result is that the
original plans for @property got dropped, and plenty of folks would be very
unhappy if we went in that direction now - but it's still the case that
@property was supposed to solve a very real problem, and that problem
remains unsolved.

As things stand, you have to be _very_ careful when using anything other
than a function in a generic context that normally uses a function, because
there's no guarantee that using something other than a function will work
due to the lack of guarantee of whether parens will be used or not. It tends
to work better with variables than with callables, because dropping parens
is so popular, and callables aren't, but it's still a problem. Anyone who
wants to use a callable instead of a function in generic code is almost
certainly in for a world of hurt unless they're in control of all of the
code involved - and that's without even getting into the issue of property
functions that return callables (those simply don't work at all).

Template constraints combat this to an extent in that they end up requiring
that the construct in question either be callable with parens or usable
without them, but that places no restrictions on the code that actually uses
the symbols, making it easy for code to use parens when it shouldn't or not
use parens when it should and then run into problems when it's given a type
that conforms to the template constraint, but the code didn't use the symbol
in the same way as the constraint. The only thing things that really prevent
this from be a much bigger problem than it is is that many folks do follow
the conventions set forth by the template constraint (e.g. always calling
front without parens) and the fact that in most cases, it's the lack of
parens which is required, and using variables instead of functions is far
more popular than using callables instead of functions. So, convention is
really all that prevents this from being a bigger problem, and the end
result is that callables in generic code are borderline useless.

On example of trying to work around this problem is that not all that long
ago, isInputRange was actually changed to use popFront without parens just
so that folks could rely on being able to call it without parens, since
previously it was possible to use a delegate or other callable for popFront
instead of a function, which would then not have worked with any code where
folks didn't bother to put parens on popFront when calling it.

All in all though, I think that the fact that we aren't strict about parens
usage mostly kills the use of callables in generic code except in cases
where you're in control of all of the code involved. It could be argued that
callables are desirable infrequently enough that being able to drop parens
when calling functions for whatever syntactic beauty supposedly comes with
outweighs the loss, but that doesn't mean that the problem isn't there, just
that many folks don't care and think that the tradeoff is worth it.

- Jonathan M Davis





More information about the Digitalmars-d-announce mailing list