www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - CT/RT annoyance

reply Bart <Bart gmail.com> writes:
Consider

void foo(string A = "")(string B = "")
{
     static if (A != "")
        do(A);
     else
        do(B);
}

foo!("x");

foo("x");


This is necessary because D's templating and meta programming 
system is frail.

While CTFE should take care of such things, it does not, consider 
import(file) vs readText(file).

If do loads such a file then one must use tricks as above:


auto load(string n = "")(string n2 = "")
{
     static if (n != "")
         enum x = import(n);
     else
         auto x = readText(n2);
}

auto load2(string n)
{
        enum x = import(n);
        string y = import(n);
}


load2 fails to compile SIMPLY because n is a RT parameter.

Even if ctfe were to kick in, such as 
load2("LiteralFileName.txt"), it is irrelevant because we can't 
compile the code.

So tricks as in load are used, but it is very hacky and verbose 
to do something very simple and natural.

This is precisely because readText cannot be used at compile time 
since it dispatches to the OS's reading routines rather than 
using import. This is not necessarily bad since we generally do 
not want to import files in to the application at compile time, 
but when we do it creates somewhat of a mess to unify code under 
ctfe.

For example, if I create a function that loads a file and 
processes it at RT then that code will not compile when used in 
CTFE. If I modify it to import the text at CT then it does not 
work at RT... even though the single point of breakage is the 
import/readText line.


auto importOrReadText(string n)
{
     if (__ctfe)
     {
         auto x = import(n);
     } else
     {
         auto x = readText(n);
     }
}

Fails for the same reasons above.

There is no way to get out of this conundrum(and therefor it is a 
contradiction). It thin requires kicking the can down the street 
and not read files at all but take text.

My suggestion is for someone to fix this. I'm not sure of the 
solution.


maybe something like

auto importOrReadText(string n)
{
     if (__ctfe)
     {
         auto x = import(ctfeFix(n));
     } else
     {
         auto x = readText(n);
     }
}

ctfeFix would be a special compiler semantic that takes a RT-like 
variable and converts it to CT. It does this because it actually 
can. It knows that n is ctfe'able and therefore n is actually a 
string literal and will do some "magic" trick the compiler in to 
seeing n for what it really is.

importOrReadText(rtFilename); // uses readText
importOrReadText("x.txt"); // uses import


Unfortunately __ctfe doesn't seem to actually work well... so I 
suggest further

auto importOrReadText(string n)
{
     static if (isKACT(n))
     {
         auto x = import(n);
         // or auto x = import(ctfeFix(n));
     } else
     {
         auto x = readText(n);
     }
}

isKACT determines if n is actually known at compile time and 
marks it n as essentially a CT constant as if it were passed as a 
template parameter(internally it would probably just convert it 
to a template parameter as if it were passed as such).


There may be other solutions.
Jun 16 2019
parent user1234 12.de <b2.temp gmx.com> writes:
On Monday, 17 June 2019 at 05:04:50 UTC, Bart wrote:
 Consider

 void foo(string A = "")(string B = "")
 {
     static if (A != "")
        do(A);
     else
        do(B);
 }

 [...]
I see the annoyance but D clearly separates what is CT and RT so such a change would require a DIP. I don't even know if this is technically possible. About what you want to achieve, note that import() is more used to include code, import lookup tables and this kind of things. It must not be seen as a CT way of reading files.
Jun 17 2019