Goofy code means opportunities in language design

Jacob Carlborg doob at me.com
Fri Sep 18 14:15:18 UTC 2020


On 2020-09-17 16:10, Andrei Alexandrescu wrote:
> Making a pass through Phobos code is very instructive. I find all kinds 
> of goofy code that really means the language doesn't allow people to do 
> what they want to do. So they need to write all sorts of oddities.
> 
> Consider this (from std.algorithm.iteration.cache):
> 
> private struct _Cache(R, bool bidir)
> {
>      ...
>      private R source;
>      static if (isInfinite!R)
>          enum empty = false;
>      else
>          bool empty() @property
>          {
>              return source.empty;
>          }
>      ...
> }
> 
> These lines appear over and over in Phobos in ranges that simply want to 
> "expose source.empty to clients of this type". There should be a 
> mechanism for that, such as:
> 
>      alias empty = source.empty;
> 
> So then whatever source.empty implements would be automatically present 
> in _Cache.
> 
> Now look at this beauty:
> 
>      static if (hasSlicing!R)
>      {
>          enum hasEndSlicing = is(typeof(source[size_t.max .. $]));
> 
>          static if (hasEndSlicing)
>          {
>              private static struct DollarToken{}
>              enum opDollar = DollarToken.init;
> 
>              auto opSlice(size_t low, DollarToken)
>              {
>                  return typeof(this)(source[low .. $]);
>              }
>          }
> 
>          static if (!isInfinite!R)
>          {
>              typeof(this) opSlice(size_t low, size_t high)
>              {
>                  return typeof(this)(source[low .. high]);
>              }
>          }
>          else static if (hasEndSlicing)
>          {
>              auto opSlice(size_t low, size_t high)
>              in
>              {
>                  assert(low <= high, "Bounds error when slicing cache.");
>              }
>              do
>              {
>                  import std.range : takeExactly;
>                  return this[low .. $].takeExactly(high - low);
>              }
>          }
>      }
> 
> Oh boy. That's a really awkward way to say, "do slicing exactly like 
> source does". Should be something like:
> 
>      static if (hasSlicing!R)
>      {
>          static if (hasMember!(R, "opDollar"))
>              alias opDollar = source.opDollar;
>          alias opSlice = source.opSlice;
>      }
> 
> Even better, as it seems common to say "forward if this other guy 
> implements it:
> 
>      try alias opDollar = source.opDollar;
>      try alias opSlice = source.opSlice;
> 

Isn't all this easily solved with opDispatch or `alias this`?

-- 
/Jacob Carlborg


More information about the Digitalmars-d mailing list