TypeFunction example: ImplictConvTargets

Adam D. Ruppe destructionator at gmail.com
Wed Oct 7 03:12:46 UTC 2020


On Wednesday, 7 October 2020 at 01:27:17 UTC, claptrap wrote:
> IE. Whats the learning curve like?

It is hard to say right now because this is a brand new 
technique. It has been possible in D ... basically forever, these 
language features are all quite aged, but to my knowledge, nobody 
has tried it this way before.

> See the point is even even though I understand that, it took me 
> a while to grep it, and I couldn't just rattle that off the top 
> of my head, it'd take me a fair while to figure out how to do 
> that. (Maybe i wouldn't even be able to on my own)

That might just be because you've never seen a combination of 
patterns like that before... and that's OK, I made up that 
particular thing just a few hours ago. (Though it is based on 
some ideas Andrei and I have been bouncing back and forth.)

But with a little library refinement and some tutorials, maybe it 
would prove to be easy to learn and to use.

The usage of a string lambda reminded me of the early days of 
std.functional and std.algorithm. Back then, a function literal 
looked like `(args) { return thing; }`. They shortened to strings 
since they liked the shortness and that's what we had, but it 
wasn't great.

Right now, a template lambda doesn't exist. We don't even have a 
short form literal like delegates did. So I'm using a string 
there. Maybe we are walking down the same path.

> But with Type Functions it'd be something like this...
>
> // assuming type is synonym for alias or whatever.
>
> type convTargets(type[] args)
> {
>     assert(args.length > 0);
>     type result = void; // IIRC void.sizeof == 1?
>     foreach(t; args)
>         if (t.size > result.sizeof) result = t;
>     return result;
> }

You could have also written that:

// normal boilerplate
template biggest(args...) {
     int helper() {
       // this stuff is really similar between the two!
       assert(args.length > 0);
       size_t result;
       size_t bestSize; // just store the answer and the size 
separate
       foreach(idx, t; args)
          if(t.sizeof > bestSize) {
              result = idx;
              bestSize = t;
          }
       return result;
     }
     // then this part always follows the same pattern again
     alias biggest = args[helper];
}

That pattern btw is very useful to know regardless of if this 
technique works out - it is also the same idea I used for 
user-defined literals in D ages ago.

Anyway, that's where my young library constructs are coming from 
- trying to recognize and abstract this pattern a little. But the 
core of it IS just regular D code: just it returns indexes into 
the array instead of the item itself because compiler tuples are 
weird. (I've been telling Stefan in a separate chat if type 
functions become compiler tuple functions, able to work with that 
`args...` thing to its full potential, we'd have something 
compelling in new functionality, not just speed. That can replace 
some of the super-ugly string mixins in my jsvar and jni that 
transform runtime argument lists! But idk if that will prove 
possible yet. He's exploring it, though.)

The major problem with this pattern so far is it is slow. I was 
actually going to abandon it after Phobos' existing 
implementations and the typefunctions prototype both blew it out 
of the water in speed terms.

But some people say using regular std.algorithm stuff is more 
important to them than speed. So I'm still toying with it for 
that sake.


More information about the Digitalmars-d mailing list