On Friday, 18 September 2015 at 20:55:06 UTC, Adam wrote:
Fact: Templates are static!

But templates are still normal functioning code and can actually work dynamically. We can see this by including a D compiler inside an app and have the app re-compile the templates for specific dynamic types. It doesn't need templates to do of course, but it shows that "Templates are static" is not quite as simple as it sounds.

But could D actually create some sort of internal expression of D templates as dynamic objects that can be used in run-time?

If have a template T that only uses 3 types, then one can simple do something like(pseudo):

t(object o)
{
// use dynamic reflection or whatever to get the type of the object o
if (o.type == 'int')
    return T!(int)(o.value, o.unit);
if (o.type == 'float')
    return T!(float)(o.value, o.unit);
return T!(unknown)(o.value, o.unit);
}

etc...

t then is a "dynamic representation" of the static functionality of T.

But my guess is that the compiler could essentially do this for us and allow one to use templates in a dynamic way. Most of the time it may not be of much use but, say, if one is interacting with console and T converts a string to a number. T could convert a number with unit such as "3mm" in to some base representation such as 0.003(m). float's are handled differently than ints(rounding depending on some criteria).

Maybe we use the T internally and its lightning fast. But for the console case, we have write a dynamic version of the template or create something similar to the code above.

But the compiler already knows, at least, some of the times that will be used and it should be able to instantiate the template for each of those types.

e.g., if you use T!(float) in the code, it will know to create the "dynamic wrapper" to include that type in the list. If you don't every use T!(float) explicitly then you can simply create a useless statement like {auto x = T!(float)("3.04mm");} which will be optimized but the compiler will then include float as a type used in the dynamic version of T. I may not be making much sense here, but it's the best I'll do.



The compiler then can do something like assemble the dynamic version of the template into a new function which can be used at compile time on any object. Using a simple special character could inform the compiler to use the dynamic template version.

object u = userInput();
&T(u); // (instead of using t(u)).


Here the compiler does all the work for us. If u has type float then this gets effectively dispatched to T!(float)(cast(float)u). If it's an int, then T!(int)(cast(int)u).

What it mainly does for us is simplify having to do the cast our self along with the string of if checking for all the types or having to code that works dynamically

Or is it impossible for the D compiler to accomplish such a task automatically for us?

I think you could also do this using structs with a type enum inside and a union for the data contents. Then you can use string mixins using traits to create generic runtime functions that dispatch to the appropriate method/free standing function on the underlying type. Take a look at Algebraic and Adam Ruppe's jsvar.

Some of the genericity can be handled at compile time. For example, I have a templated time series entry struct. A time series is a slice of such structs. An entry definitively has a date, and it may have either a bid and ask or (a close and optionally open, high, low, adjusted close). It has a volume, and may have an open interest. The date may be a year/month/day or it might have a time too. I want to store things efficiently in memory and on disk. So I use hasMember!(typeof(pricebar.date),"hour") to find out if it's an intraday date or daily for example. See Andrei's allocator talk, his code, and maybe that for cerealed.

I have a bunch of templated functions that can do useful things with such a time series.

But then I want to pass them around wrapped in an a tagged union and generate versions of these functions that can operate on this untemplated struct. (I will wrap the slices, not the entries). That will make it easier to access my work from a dynamic language like Lua. I haven't written this bit yet, but I have done something similar in another context. A degree of misery in trying to figure out std.traits, but that's a one off cost and it goes quicker if you read others code for inspiration. UDAs help in specifying which functions should have wrapped versions generated etc.

Reply via email to