www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Compile-time constness is waaay to strict!

reply asd <a sd.invalid> writes:
I've got D2 code:

 template ObjcMethodSelectorCheck(string sel, A...) {
	const n = countMethodArguments(sel);

and: pure static uint countMethodArguments(string name) { if (name.length == 0) return 0; if (name[0] == ':') return 1+countMethodArguments(name[1..$]); return countMethodArguments(name[1..$]); } Original version of this method was pure too, but used count++. Fine, maybe compiler wasn't smart enough to understand that, but now I've rewritten it in purely functional style, and it's still not "constant" enough! objc/method.d(54): Error: cannot evaluate countMethodArguments(ToSetterSelector) at compile time objc/method.d(57): Error: expression 1u != countMethodArguments(ToSetterSelector) is not constant or does not evaluate to a bool
Jul 24 2009
next sibling parent reply Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Fri, Jul 24, 2009 at 8:27 PM, asd<a sd.invalid> wrote:
 I've got D2 code:

 template ObjcMethodSelectorCheck(string sel, A...) {
 =A0 =A0 =A0 const n =3D countMethodArguments(sel);

and: pure static uint countMethodArguments(string name) { =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (name.length =3D=3D 0) return 0; =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (name[0] =3D=3D ':') return 1+countMeth=

 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return countMethodArguments(name[1..$]);
 =A0 =A0 =A0 =A0}

 Original version of this method was pure too, but used count++. Fine, may=

it in purely functional style, and it's still not "constant" enough!
 objc/method.d(54): Error: cannot evaluate countMethodArguments(ToSetterSe=

 objc/method.d(57): Error: expression 1u !=3D countMethodArguments(ToSette=

I think something else is going on. I can't reproduce any problems: pure static uint countMethodArguments(string name) { if(name.length =3D=3D 0) return 0; if(name[0] =3D=3D ':') return 1 + countMethodArguments(name[1 .. $]); return countMethodArguments(name[1 .. $]); } template Temp(string sel) { const Temp =3D countMethodArguments(sel); } void main() { writeln(Temp!("foo:bar:")); // prints 2 } Can you post more of your code?
Jul 24 2009
parent reply asd <a s.d> writes:
Jarrett Billingsley Wrote:

 Can you post more of your code?

I've reduced it to this: bool isEmptyString(string str) { static if (str == "") return true; return false; } void main() { static if (isEmptyString("")) { int x = 1; } } test.d(5): Error: expression str == "" is not constant or does not evaluate to a bool test.d(11): Error: cannot evaluate isEmptyString("") at compile time test.d(11): Error: expression isEmptyString("") is not constant or does not evaluate to a bool DMD v2.031 on OS X
Jul 24 2009
next sibling parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Jarrett Billingsley wrote:
 On Fri, Jul 24, 2009 at 11:03 PM, asd<a s.d> wrote:
 Jarrett Billingsley Wrote:

 Can you post more of your code?

bool isEmptyString(string str) { static if (str == "") return true;

It works if you use 'if' instead of 'static if', oddly.
        return false;
 }

 void main()
 {
        static if (isEmptyString(""))
        {
                int x = 1;
        }
 }


 test.d(5): Error: expression str == "" is not constant or does not evaluate to
a bool
 test.d(11): Error: cannot evaluate isEmptyString("") at compile time
 test.d(11): Error: expression isEmptyString("") is not constant or does not
evaluate to a bool

Be sure to report this on Bugzilla: http://d.puremagic.com/issues/

I don't think this is a bug in DMD. It can't execute it at compile-time because it CANNOT COMPILE IT. str is a run-time argument. static if requires a compile-time expression. You can't feed runtime constructs to compile-time ones. Evaluating a function at compile time doesn't change that.
Jul 25 2009
parent reply asd <a sd.invalid> writes:
Daniel Keep Wrote:

 bool isEmptyString(string str) {
        static if (str == "") return true;

It works if you use 'if' instead of 'static if', oddly.
        return false;
 }

 void main()
 {
        static if (isEmptyString(""))
        {
                int x = 1;
        }
 }


 test.d(5): Error: expression str == "" is not constant or does not evaluate to
a bool
 test.d(11): Error: cannot evaluate isEmptyString("") at compile time
 test.d(11): Error: expression isEmptyString("") is not constant or does not
evaluate to a bool

Be sure to report this on Bugzilla: http://d.puremagic.com/issues/

I don't think this is a bug in DMD. It can't execute it at compile-time because it CANNOT COMPILE IT. str is a run-time argument. static if requires a compile-time expression. You can't feed runtime constructs to compile-time ones. Evaluating a function at compile time doesn't change that.

That's a shame. This distinction doesn't make sense to me -- it is clearly possible to know value of this function at compile time and there's no way to change the result at run time. If it's not a bug, I've filed it as feature request then: http://d.puremagic.com/issues/show_bug.cgi?id=3209
Jul 25 2009
parent reply KennyTM~ <kennytm gmail.com> writes:
asd wrote:
 Daniel Keep Wrote:
 
 bool isEmptyString(string str) {
        static if (str == "") return true;

        return false;
 }

 void main()
 {
        static if (isEmptyString(""))
        {
                int x = 1;
        }
 }


 test.d(5): Error: expression str == "" is not constant or does not evaluate to
a bool
 test.d(11): Error: cannot evaluate isEmptyString("") at compile time
 test.d(11): Error: expression isEmptyString("") is not constant or does not
evaluate to a bool


It can't execute it at compile-time because it CANNOT COMPILE IT. str is a run-time argument. static if requires a compile-time expression. You can't feed runtime constructs to compile-time ones. Evaluating a function at compile time doesn't change that.

That's a shame. This distinction doesn't make sense to me -- it is clearly possible to know value of this function at compile time and there's no way to change the result at run time. If it's not a bug, I've filed it as feature request then: http://d.puremagic.com/issues/show_bug.cgi?id=3209

It makes sense. A compile-time function must be executable in run time as well. Which means both of the following must be meaningful. void main () { auto s = readln(); if (isEmptyString(s)) { ... } // Run time executed } void main2 () { static if (isEmptyString("")) { ... } // Compile time executed } If you use static if in isEmptyString, the run time counterpart is meaningless.
Jul 25 2009
parent asd <asd none.invalid> writes:
KennyTM~ Wrote:

 It makes sense. A compile-time function must be executable in run time 
 as well. Which means both of the following must be meaningful.
 
 void main () {
    auto s = readln();
    if (isEmptyString(s)) { ... } // Run time executed
 }
 
 void main2 () {
    static if (isEmptyString("")) { ... } // Compile time executed
 }
 
 If you use static if in isEmptyString, the run time counterpart is 
 meaningless.

Ah, now I see it. Thanks!
Jul 25 2009
prev sibling parent "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
asd wrote:
 Jarrett Billingsley Wrote:
 
 Can you post more of your code?

I've reduced it to this: bool isEmptyString(string str) { static if (str == "") return true; return false; } void main() { static if (isEmptyString("")) { int x = 1; } } test.d(5): Error: expression str == "" is not constant or does not evaluate to a bool test.d(11): Error: cannot evaluate isEmptyString("") at compile time test.d(11): Error: expression isEmptyString("") is not constant or does not evaluate to a bool DMD v2.031 on OS X

This is definitely not a bug. You are mixing two different things here: templates and compile-time function evaluation (CTFE). If you know you'll only need the isEmptyString functionality (or whatever it's representing) at compile time, you can write it as a template. str is then a template parameter which we can be sure is known at compile time, and we can use "static if" to check its value: template isEmptyString(string str) { static if (str == "") enum bool isEmptyString = true; else enum bool isEmptyString = false; } If isEmptyString is meant to be a function which can be executed at both compile and run time, you have to write it as an ordinary run-time function. You must then use an ordinary if, since it's impossible to know beforehand whether str is going to be set at run time or at compile time. bool isEmptyString(string str) { if (str == "") return true; return false; } Hope this helps, -Lars
Jul 25 2009
prev sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Fri, Jul 24, 2009 at 11:03 PM, asd<a s.d> wrote:
 Jarrett Billingsley Wrote:

 Can you post more of your code?

I've reduced it to this: bool isEmptyString(string str) { =A0 =A0 =A0 =A0static if (str =3D=3D "") return true;

It works if you use 'if' instead of 'static if', oddly.
 =A0 =A0 =A0 =A0return false;
 }

 void main()
 {
 =A0 =A0 =A0 =A0static if (isEmptyString(""))
 =A0 =A0 =A0 =A0{
 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0int x =3D 1;
 =A0 =A0 =A0 =A0}
 }


 test.d(5): Error: expression str =3D=3D "" is not constant or does not ev=

 test.d(11): Error: cannot evaluate isEmptyString("") at compile time
 test.d(11): Error: expression isEmptyString("") is not constant or does n=

Be sure to report this on Bugzilla: http://d.puremagic.com/issues/
Jul 24 2009