digitalmars.D.learn - Accessing mutable data that isn't
- Spott (52/52) Nov 20 2013 I've been screwing around with templates lately, and I'm
- Jesse Phillips (8/22) Nov 20 2013 const here is redundant, probably wanted const(auto) which isn't
- qznc (6/62) Nov 20 2013 No answer, but two notes.
- Jonathan M Davis (8/10) Nov 20 2013 Really? I find it annoying when people do that unless the code is quite ...
- bearophile (8/14) Nov 21 2013 I agree with Jonathan. External sites should be avoided unless
- Spott (10/85) Nov 25 2013 intermediateValue is a structure that ideally should only exist
- Jonathan M Davis (17/81) Nov 20 2013 pure functions can only access their arguments and global/static constan...
- Spott (4/102) Nov 25 2013 Why is rhs a purely runtime argument? I would think it would be
- Jonathan M Davis (34/36) Nov 25 2013 Function arguments are runtime entities, not compile-time entities and
I've been screwing around with templates lately, and I'm attempting to figure out why the following won't compile: struct value { int a; const auto opBinary(string op, T)(in T rhs) const pure { static if (op == "+") return intermediateValue!(value.plus,this,rhs)(); } ref value opAssign(T)( in T t ) { a = t.a; return this; } static int plus(T1, T2)(in T1 x, in T2 y) pure { return x.a + y.a; } } struct intermediateValue(alias Op, alias A, alias B) { auto opBinary(string op, T)(in T rhs) const pure { static if (op == "+") return intermediateValue!(value.plus,this,rhs)(); } property auto a() const pure { return Op(A, B); } } void main() { value a = value(2); value b = value(3); value c; c = a + b; } The error is: d_playground.d(34): Error: pure nested function 'a' cannot access mutable data 'this' d_playground.d(34): Error: pure nested function 'a' cannot access mutable data 'this' d_playground.d(10): Error: template instance d_playground.value.opBinary!("+", value).opBinary.intermediateValue!(plus, this, rhs) error instantiating d_playground.d(44): instantiated from here: opBinary!("+", value) d_playground.d(44): Error: template instance d_playground.value.opBinary!("+", value) error instantiating What is going on? Why is 'a' not allowed to "access" mutable data (even though it isn't modifying it)? How do I tell the compiler to pass "this" in a const fashion?
Nov 20 2013
On Wednesday, 20 November 2013 at 22:49:42 UTC, Spott wrote:I've been screwing around with templates lately, and I'm attempting to figure out why the following won't compile: struct value { int a; const auto opBinary(string op, T)(in T rhs) const pure { static if (op == "+") return intermediateValue!(value.plus,this,rhs)(); }const here is redundant, probably wanted const(auto) which isn't valid syntax. The function being const may already be returning a const type.What is going on? Why is 'a' not allowed to "access" mutable data (even though it isn't modifying it)? How do I tell the compiler to pass "this" in a const fashion?I'm not seeing an issue with the declarations. The function being declared as const is what make 'this' const. Probably should file as a bug if you don't get any confirmation soon. And reply with the bug entry.
Nov 20 2013
On Wednesday, 20 November 2013 at 22:49:42 UTC, Spott wrote:I've been screwing around with templates lately, and I'm attempting to figure out why the following won't compile: struct value { int a; const auto opBinary(string op, T)(in T rhs) const pure { static if (op == "+") return intermediateValue!(value.plus,this,rhs)(); } ref value opAssign(T)( in T t ) { a = t.a; return this; } static int plus(T1, T2)(in T1 x, in T2 y) pure { return x.a + y.a; } } struct intermediateValue(alias Op, alias A, alias B) { auto opBinary(string op, T)(in T rhs) const pure { static if (op == "+") return intermediateValue!(value.plus,this,rhs)(); } property auto a() const pure { return Op(A, B); } } void main() { value a = value(2); value b = value(3); value c; c = a + b; } The error is: d_playground.d(34): Error: pure nested function 'a' cannot access mutable data 'this' d_playground.d(34): Error: pure nested function 'a' cannot access mutable data 'this' d_playground.d(10): Error: template instance d_playground.value.opBinary!("+", value).opBinary.intermediateValue!(plus, this, rhs) error instantiating d_playground.d(44): instantiated from here: opBinary!("+", value) d_playground.d(44): Error: template instance d_playground.value.opBinary!("+", value) error instantiating What is going on? Why is 'a' not allowed to "access" mutable data (even though it isn't modifying it)? How do I tell the compiler to pass "this" in a const fashion?No answer, but two notes. First, use dpaste for such code snippets: http://dpaste.dzfl.pl/f2f39b32 Second, what are you trying to do? intermediateValue is a struct without members. I am not sure what 'this' means in such a case.
Nov 20 2013
On Thursday, November 21, 2013 07:48:34 qznc wrote:First, use dpaste for such code snippets: http://dpaste.dzfl.pl/f2f39b32Really? I find it annoying when people do that unless the code is quite long. It's much easier to have it just be in the message IMHO. Also, it has the benefit of not having to worry about the link not being valid in the future, potentially rendering the message impossible to understand. I have no idea how long dpaste links stick around; a while I expect, but there's no guarantee that they'll be around as long as the forum or its archives will be. - Jonathan M Davis
Nov 20 2013
Jonathan M Davis:I find it annoying when people do that unless the code is quite long. It's much easier to have it just be in the message IMHO. Also, it has the benefit of not having to worry about the link not being valid in the future,I agree with Jonathan. External sites should be avoided unless the code is very long. (And you can even attach files in the D newsgroups when the code is a little longer). On Bugzilla code you have to always avoid code external sites (unless it's GitHub, etc). Bye, bearophile
Nov 21 2013
On Thursday, 21 November 2013 at 06:48:40 UTC, qznc wrote:On Wednesday, 20 November 2013 at 22:49:42 UTC, Spott wrote:intermediateValue is a structure that ideally should only exist at compile time. Theoretically, (at least in my head), opAssign will traverse the expression and reduce it to the addition that it is inside opAssign. I'm attempting to create a vector DSL (similar to blaze-lib: https://code.google.com/p/blaze-lib/), but starting with just a plain number. Mostly it is for fun, it is a way of working on my understanding of the compile time primitives and template system.I've been screwing around with templates lately, and I'm attempting to figure out why the following won't compile: struct value { int a; const auto opBinary(string op, T)(in T rhs) const pure { static if (op == "+") return intermediateValue!(value.plus,this,rhs)(); } ref value opAssign(T)( in T t ) { a = t.a; return this; } static int plus(T1, T2)(in T1 x, in T2 y) pure { return x.a + y.a; } } struct intermediateValue(alias Op, alias A, alias B) { auto opBinary(string op, T)(in T rhs) const pure { static if (op == "+") return intermediateValue!(value.plus,this,rhs)(); } property auto a() const pure { return Op(A, B); } } void main() { value a = value(2); value b = value(3); value c; c = a + b; } The error is: d_playground.d(34): Error: pure nested function 'a' cannot access mutable data 'this' d_playground.d(34): Error: pure nested function 'a' cannot access mutable data 'this' d_playground.d(10): Error: template instance d_playground.value.opBinary!("+", value).opBinary.intermediateValue!(plus, this, rhs) error instantiating d_playground.d(44): instantiated from here: opBinary!("+", value) d_playground.d(44): Error: template instance d_playground.value.opBinary!("+", value) error instantiating What is going on? Why is 'a' not allowed to "access" mutable data (even though it isn't modifying it)? How do I tell the compiler to pass "this" in a const fashion?No answer, but two notes. First, use dpaste for such code snippets: http://dpaste.dzfl.pl/f2f39b32 Second, what are you trying to do? intermediateValue is a struct without members. I am not sure what 'this' means in such a case.
Nov 25 2013
On Wednesday, November 20, 2013 23:49:42 Spott wrote:I've been screwing around with templates lately, and I'm attempting to figure out why the following won't compile: struct value { int a; const auto opBinary(string op, T)(in T rhs) const pure { static if (op == "+") return intermediateValue!(value.plus,this,rhs)(); } ref value opAssign(T)( in T t ) { a = t.a; return this; } static int plus(T1, T2)(in T1 x, in T2 y) pure { return x.a + y.a; } } struct intermediateValue(alias Op, alias A, alias B) { auto opBinary(string op, T)(in T rhs) const pure { static if (op == "+") return intermediateValue!(value.plus,this,rhs)(); } property auto a() const pure { return Op(A, B); } } void main() { value a = value(2); value b = value(3); value c; c = a + b; } The error is: d_playground.d(34): Error: pure nested function 'a' cannot access mutable data 'this' d_playground.d(34): Error: pure nested function 'a' cannot access mutable data 'this' d_playground.d(10): Error: template instance d_playground.value.opBinary!("+", value).opBinary.intermediateValue!(plus, this, rhs) error instantiating d_playground.d(44): instantiated from here: opBinary!("+", value) d_playground.d(44): Error: template instance d_playground.value.opBinary!("+", value) error instantiating What is going on? Why is 'a' not allowed to "access" mutable data (even though it isn't modifying it)? How do I tell the compiler to pass "this" in a const fashion?pure functions can only access their arguments and global/static constants. a's only argument is its invisible this pointer. Op, A, and B are aliases to stuff outside of a. I suppose that an argument could be made that because the're template arguments to the type that a is a part of that they should be considered to be arguments to a like the this pointer is, but you are essentially trying to have it access data which is not one of its arguments and that violates purity. But all in all, I find your code quite bizarre and difficult to understand - particularly your use of aliases - so it's kind of hard for me to say how valid it is. I'm surprised that you can get away with feeding a purely runtime argument to a template as an alias (namely rhs). I wouldn't have thought that that would be valid. In most cases, all template alias parameters get used for is passing in predicates to functions (which are almost invariably delegates or lambdas). So, clearly my understanding of how alias template parameters work is too limited. - Jonathan M Davis
Nov 20 2013
On Thursday, 21 November 2013 at 07:23:09 UTC, Jonathan M Davis wrote:On Wednesday, November 20, 2013 23:49:42 Spott wrote:Why is rhs a purely runtime argument? I would think it would be known at compile time.I've been screwing around with templates lately, and I'm attempting to figure out why the following won't compile: struct value { int a; const auto opBinary(string op, T)(in T rhs) const pure { static if (op == "+") return intermediateValue!(value.plus,this,rhs)(); } ref value opAssign(T)( in T t ) { a = t.a; return this; } static int plus(T1, T2)(in T1 x, in T2 y) pure { return x.a + y.a; } } struct intermediateValue(alias Op, alias A, alias B) { auto opBinary(string op, T)(in T rhs) const pure { static if (op == "+") return intermediateValue!(value.plus,this,rhs)(); } property auto a() const pure { return Op(A, B); } } void main() { value a = value(2); value b = value(3); value c; c = a + b; } The error is: d_playground.d(34): Error: pure nested function 'a' cannot access mutable data 'this' d_playground.d(34): Error: pure nested function 'a' cannot access mutable data 'this' d_playground.d(10): Error: template instance d_playground.value.opBinary!("+", value).opBinary.intermediateValue!(plus, this, rhs) error instantiating d_playground.d(44): instantiated from here: opBinary!("+", value) d_playground.d(44): Error: template instance d_playground.value.opBinary!("+", value) error instantiating What is going on? Why is 'a' not allowed to "access" mutable data (even though it isn't modifying it)? How do I tell the compiler to pass "this" in a const fashion?pure functions can only access their arguments and global/static constants. a's only argument is its invisible this pointer. Op, A, and B are aliases to stuff outside of a. I suppose that an argument could be made that because the're template arguments to the type that a is a part of that they should be considered to be arguments to a like the this pointer is, but you are essentially trying to have it access data which is not one of its arguments and that violates purity. But all in all, I find your code quite bizarre and difficult to understand - particularly your use of aliases - so it's kind of hard for me to say how valid it is. I'm surprised that you can get away with feeding a purely runtime argument to a template as an alias (namely rhs). I wouldn't have thought that that would be valid. In most cases, all template alias parameters get used for is passing in predicates to functions (which are almost invariably delegates or lambdas). So, clearly my understanding of how alias template parameters work is too limited. - Jonathan M Davis
Nov 25 2013
On Monday, November 25, 2013 18:34:30 Spott wrote:Why is rhs a purely runtime argument? I would think it would be known at compile time.Function arguments are runtime entities, not compile-time entities and therefore cannot be used in places where a compile-time entity is required. e.g. this is illegal auto foo(int i)(int j) { return i * j; } auto bar(int k) { return foo!k(5); } because k is not known at compile time. Yes, it's true that if a function is used during CTFE, then its function arguments would technically be known at compile time, as the compiler is in the middle of compiling your program, however, from the function's perspective, it's runtime. It just so happens that it's being run at compile time. e.g. auto foo(int i) { return i; } enum f = foo(5); f must be known at compile time, so foo is called and run at compile time, but from foo's perspective, it's being run, not compiled. So, it can only do the things that it could do at runtime (plus whatever additional restrictions CTFE imposes - e.g. no I/O). Template parameters are compile-time entities and thus must be known at compile time. However, aliases are a bit funny in that they alias the symbol rather than using its value, so apparently, under some set of circumstances, a template alias parameter can accept a runtime argument, because it's the symbol that gets used and not its value, meaning that its value is not calculated until runtime, so it works. But any normal template parameter's value must be known at compile time. - Jonathan M Davis
Nov 25 2013