Re: Testing for template argument being result of takeExactly
On Sun, Sep 23, 2012 at 1:54 AM, Jonathan M Davis wrote: > I'm trying to test whether a template argument is the type returned by > takeExactly, and I haven't been able to sort out the template voodoo required > yet. It would be a lot easier if I had a variable to work with, but I just > have the type, and the fancy is expression required to pull it off is fancy > enough that I haven't been able to sort it out yet. Seeing that takeExactly returns itself when its input is a takeExactly, I used this: import std.range; import std.stdio; template Hello(R) { static if (is(typeof(R._input)) // Is using R._input OK? && is(typeof(takeExactly(typeof(R._input),0)) == R )) // Does applying takeExactly on R gives R back? alias typeof(R._input) Hello; // Extract the original range type else alias void Hello; } void main() { auto str = "hello"; auto t = takeExactly(str, 3); writeln(t); writeln(Hello!(typeof(t)).stringof); // "string" } Transforming it into a predicate template is easy, I just wanted to show that R._input is accessible. Caution: takeExactly returns a slice when the range is slice-able. You should test for hasSlicing on R first. As for Voldemort (Nameless One, Dark Lord, whatever) types, I find them more annoying than useful, personally. Philippe
Re: Testing for template argument being result of takeExactly
On 09/23/2012 01:54 AM, Jonathan M Davis wrote: I'm trying to test whether a template argument is the type returned by takeExactly, and I haven't been able to sort out the template voodoo required yet. It would be a lot easier if I had a variable to work with, but I just have the type, and the fancy is expression required to pull it off is fancy enough that I haven't been able to sort it out yet. At present, I have this: import std.range; import std.stdio; template Hello(R) if(is(R r == U, V, V w, U = typeof(takeExactly(w, 1 { alias R Hello; } void main() { auto str = "hello"; auto t = takeExactly(str, 3); writeln(t); Hello!(typeof(t)) h = t; writeln(h); } I need Hello to instatiate if R is the type returned by takeExactly and fail to instantiate otherwise. At present, the code gives these compilation errors: q.d(15): Error: template instance Hello!(Result) Hello!(Result) does not match template declaration Hello(R) if (is(R r == U,V,V w,U = typeof(takeExactly(w,1 q.d(15): Error: Hello!(Result) is used as a type q.d(16): Error: template std.stdio.writeln does not match any function template declaration q.d(16): Error: template std.stdio.writeln(T...) cannot deduce template function from argument types !()(_error_) So, clearly I don't have the is expression right, and this is seriously pushing the edge of my knowledge of is expressions. So, any help would be appreciated. Thanks. - Jonathan M Davis import std.range, std.traits; import std.stdio; template Hello(R) if(is(typeof(R._input.takeExactly(2)) == R)){ alias R Hello; } void main(){ auto str = "hello"; auto t = takeExactly(str, 3); writeln(t); Hello!(typeof(t)) h = t; writeln(h); }
Re: Testing for template argument being result of takeExactly
On 9/23/12 8:47 AM, Timon Gehr wrote: import std.range, std.traits; import std.stdio; template Hello(R) if(is(typeof(R._input.takeExactly(2)) == R)){ alias R Hello; } That's the nicest. Regarding availability of "_input", I meant to make it available systematically as "input" for ranges where the notion makes sense. Andrei
Re: Passing associative array to another thread
On 2012-09-22 13:50, Johannes Pfau wrote: 1. Declare it as "shared" There's also __gshared. Yeah, forgot about that one. -- /Jacob Carlborg
Re: Testing for template argument being result of takeExactly
On 09/23/2012 03:48 PM, Andrei Alexandrescu wrote: On 9/23/12 8:47 AM, Timon Gehr wrote: import std.range, std.traits; import std.stdio; template Hello(R) if(is(typeof(R._input.takeExactly(2)) == R)){ alias R Hello; } That's the nicest. Well, I noticed it is not entirely correct as takeExactly special cases sliceable inputs. Therefore, the guard also passes for ranges that have a sliceable member called _input of the same range type. The correct guard therefore would be: if(hasSlicing!R || is(typeof(R._input.takeExactly(2)) == R)) or if(!hasSlicing!R && is(typeof(R._input.takeExactly(2)) == R)) depending on what the goal is. Regarding availability of "_input", I meant to make it available systematically as "input" for ranges where the notion makes sense. Andrei This seems to be reasonable.
educational graphics library for D
Hi, I'm evaluating D as a language for my computer science classses. Can you recommend a graphics library which can be used for simple graphic programming like logo, turtle or processing.org? Regards, Thomas Koch
Re: educational graphics library for D
Thomas Koch: I'm evaluating D as a language for my computer science classses. Can you recommend a graphics library which can be used for simple graphic programming like logo, turtle or processing.org? What is the age/experience of your students? D is simpler to learn than C++, but it's not as simple to learn as Python. A turtle geometry library is probably quite short and easy to do, so even if it doesn't exist in D, it's not too much work to create it, on top of some GUI/graphics toolkit. Regarding graphics there are several options, including full GUI toolkits like: http://www.dsource.org/projects/gtkd There is also a library for plotting numerical data. Maybe others will give you more links. Bye, bearophile
alias to a property as an argument to a mixin template
For this program I'm getting an "Error: need 'this' to access member x" at line (*). Does that mean that we cannot alias a property as an argument of a template mixin? import std.stdio; mixin template T(alias a) { void f() { writeln(a); // (*) } } struct S { int x; } void main() { auto s = S(4); mixin T!(s.x); f(); } If I change main() as follows, I still get the same error: void main1() { auto s = S(4); with (s) { mixin T!(x); f(); } } But now, I can get it working by this trick: import std.stdio; mixin template T(alias a) { void f() { mixin("writeln(" ~ a.stringof ~ ");"); } } struct S { int x; } void main() { auto s = S(4); with (s) { mixin T!(x); f(); } } // prints 4 So, using string mixins works, but explicit alias to the property name seems not to. Why is that and is there any other way of achieving the result witout using template mixins?
Re: alias to a property as an argument to a mixin template
On Sunday, 23 September 2012 at 18:48:14 UTC, comco wrote: For this program I'm getting an "Error: need 'this' to access member x" at line (*). Does that mean that we cannot alias a property as an argument of a template mixin? import std.stdio; mixin template T(alias a) { void f() { writeln(a); // (*) } } struct S { int x; } void main() { auto s = S(4); mixin T!(s.x); f(); } If I change main() as follows, I still get the same error: void main1() { auto s = S(4); with (s) { mixin T!(x); f(); } } But now, I can get it working by this trick: import std.stdio; mixin template T(alias a) { void f() { mixin("writeln(" ~ a.stringof ~ ");"); } } struct S { int x; } void main() { auto s = S(4); with (s) { mixin T!(x); f(); } } // prints 4 So, using string mixins works, but explicit alias to the property name seems not to. Why is that and is there any other way of achieving the result witout using template mixins? I think it is normal behavior. Keep in mind what you are instantiating your template with (something know at compile time), and how you are using it. When you write "T!(s.x)", the compiler understands it as "S.x" (in D, you may use an instance when you could use a type). Of course, when trying to use the mixed-in in T, you get: void f() { writeln(S.x); } To which the compiler replies: "Who's x?" (eg: I need "this"). EG: as the title implies, you parametrized your template on a property, but there is no associated instance. What you are really trying to do, is parametrize your template on a variable *name*, so you were right taking your mixin approach. However, I think this is more like what you want: import std.stdio; //ss is the variable name mixin template T(alias ss) { void f() { mixin("writeln(" ~ ss ~ ");"); } } struct S { int x; } void main() { auto s = S(4); mixin T!"s.x"; //mix with the variable "s.x" f(); } On a side note, if the alias was named "s", the compiler would have gotten confused, because of the conflict with the mixed'd in s. THAT however, I think is a bug.
Re: alias to a property as an argument to a mixin template
monarch_dodra already answered, but since, I typed this, I may as well post it :) On Sun, Sep 23, 2012 at 8:49 PM, comco wrote: > For this program I'm getting an "Error: need 'this' to access member x" at > line (*). Does that mean that we cannot alias a property as an argument of a > template mixin? By using s.x, you're not referencing the property, but directly the value s.x, which is known only at runtime: it cannot be a template argument. If x where a static member, you could probably use it, hence the error message (need 'this', ...). > So, using string mixins works, but explicit alias to the property name seems > not to. Why is that? a.stringof can be obtained for any symbol a, so s.x (or with(s) ... x) just gives "s.x", which can be mixed in. It's transformed into a string, transformation for which there is no need for 'this'. > and is there any other way of achieving the result > witout using template mixins Sorry but... what result? Referencing a member inside a template? Remember templates can be in another module, written years ago. If you really want a template to act on a local value, either use a mixin template, as you did, or reference the member by its name as a string: import std.stdio; mixin template T(string member) { void f() { mixin("writeln(" ~ member ~ ");"); } } struct S { int x; } void main() { auto s = S(4); mixin T!("s.x"); f(); } // prints 4 I see monarch proposed exactly the same way to do it...
Re: alias to a property as an argument to a mixin template
On 09/23/2012 11:49 AM, comco wrote: For this program I'm getting an "Error: need 'this' to access member x" at line (*). Does that mean that we cannot alias a property as an argument of a template mixin? import std.stdio; mixin template T(alias a) { void f() { writeln(a); // (*) } } struct S { int x; } void main() { auto s = S(4); mixin T!(s.x); f(); } If I change main() as follows, I still get the same error: void main1() { auto s = S(4); with (s) { mixin T!(x); f(); } } But now, I can get it working by this trick: import std.stdio; mixin template T(alias a) { void f() { mixin("writeln(" ~ a.stringof ~ ");"); } } struct S { int x; } void main() { auto s = S(4); with (s) { mixin T!(x); f(); } } // prints 4 So, using string mixins works, but explicit alias to the property name seems not to. Why is that and is there any other way of achieving the result witout using template mixins? There is also delegates: import std.stdio; struct S { int x; } void main() { auto s = S(4); auto f = { return s.x; }; f(); } Ali
Re: Testing for template argument being result of takeExactly
On 09/23/2012 12:02 PM, monarch_dodra wrote: > On Saturday, 22 September 2012 at 23:53:28 UTC, Jonathan M Davis wrote: >> I'm trying to test... >> [SNIP] >> - Jonathan M Davis > > I *kind of* see what you are doing with U, V, W, but what's wrong with > just doing: > > > import std.range; > > template Hello(R) > if(is(typeof(R == typeof(takeExactly(R, 1) > { > alias R Hello; > } > > struct S; > > void main( ) { > Hello!(int[]) a; //OK > Hello!S b; //FAIL > } > > ? > > It seems to work for me..., but I'm not 100% sure there isn't something > illegal/unsafe in there. The goal is to "test whether a template argument is the type returned by takeExactly." Your solution (I think) is looking at a container and determining whether the type of that container can be compared to the return type of takeExactly(). (Note that typeof(X == Y) is used for checking whether that expression itself is valid.) Also, I think your code should have passed a range like R.init to takeExactly, not R, which is a type: takeExactly(R.init, 1) I don't know why your code compiles. Ali
Re: Testing for template argument being result of takeExactly
On Sunday, 23 September 2012 at 20:56:42 UTC, Ali Çehreli wrote: On 09/23/2012 12:02 PM, monarch_dodra wrote: > On Saturday, 22 September 2012 at 23:53:28 UTC, Jonathan M Davis wrote: >> I'm trying to test... >> [SNIP] >> - Jonathan M Davis > > I *kind of* see what you are doing with U, V, W, but what's wrong with > just doing: > > > import std.range; > > template Hello(R) > if(is(typeof(R == typeof(takeExactly(R, 1) > { > alias R Hello; > } > > struct S; > > void main( ) { > Hello!(int[]) a; //OK > Hello!S b; //FAIL > } > > ? > > It seems to work for me..., but I'm not 100% sure there isn't something > illegal/unsafe in there. The goal is to "test whether a template argument is the type returned by takeExactly." Your solution (I think) is looking at a container and determining whether the type of that container can be compared to the return type of takeExactly(). (Note that typeof(X == Y) is used for checking whether that expression itself is valid.) Good point. My bad then. Also, I think your code should have passed a range like R.init to takeExactly, not R, which is a type: takeExactly(R.init, 1) I don't know why your code compiles. That did seem fishy to me too actually, but it does compile. Ali In that case, what about: import std.range; template Hello(R) if(is(typeof(takeExactly(R.init, 1))) && is(R == typeof(takeExactly(R.init, 1 { alias R Hello; } struct S{}; void main( ) { Hello!(int[]) a; //OK Hello!S b; //FAIL (again) } ---
Re: alias to a property as an argument to a mixin template
On Sunday, 23 September 2012 at 19:53:26 UTC, Philippe Sigaud wrote: monarch_dodra already answered, but since, I typed this, I may as well post it :) On Sun, Sep 23, 2012 at 8:49 PM, comco wrote: For this program I'm getting an "Error: need 'this' to access member x" at line (*). Does that mean that we cannot alias a property as an argument of a template mixin? By using s.x, you're not referencing the property, but directly the value s.x, which is known only at runtime: it cannot be a template argument. If x where a static member, you could probably use it, hence the error message (need 'this', ...). So, using string mixins works, but explicit alias to the property name seems not to. Why is that? a.stringof can be obtained for any symbol a, so s.x (or with(s) ... x) just gives "s.x", which can be mixed in. It's transformed into a string, transformation for which there is no need for 'this'. and is there any other way of achieving the result witout using template mixins Sorry but... what result? Referencing a member inside a template? Remember templates can be in another module, written years ago. If you really want a template to act on a local value, either use a mixin template, as you did, or reference the member by its name as a string: import std.stdio; mixin template T(string member) { void f() { mixin("writeln(" ~ member ~ ");"); } } struct S { int x; } void main() { auto s = S(4); mixin T!("s.x"); f(); } // prints 4 I see monarch proposed exactly the same way to do it... Thank you for the answers. Passing a string does the job, but the result I wanted to achieve is: the client of the mixin template to use it without strings. Here's the motivating example: when implementing algorithms for linked data structures, a common pattern is such a chain of assignments: a1 = a2; a2 = a3; a3 = a4 ... For example, take a rotation of a binary tree: struct node { node* left, right; } void rotate(node* u) { auto v = u.right; u.right = v.left; v.left = u; } For this pattern, we may design a template function like this: void reassign(A...)(ref A a) { static if (A.length > 1) { a[0] = a[1]; reassign(a[1 .. $]); } } Now we can implement our rotate in terms of reassign: void rotate(node* u) { auto v = u.right; reassign(u.right, v.left, u); } This works and is general enough, but notice the duplication of u.right. I don't like it - this may become an arbitrary large expression. But the naive attempt fails: void rotate(node* u) { node* v; reassign(v, u.right, v.left, u); // runtime error at v.left } That's because v is not initialized when we call the function. So what we really want is to pass a list of symbols (and I thought `v.left` qualifies as a symbol) to the function, not references to value. But this means we'll need template mixins, because you can pass symbols by alias to them. Since alias arguments for templates are classified as symbolic arguments, I was expecting that you can pass "u.right" as an atomic symbol, without using strings. So, then my strange rotate would look like this: void rotate(node* u) { node* v; mixin ReassignMixin!(v, u.right, v.left, u); reassign(); } See how the client code looks nicer when the template arguments are not wrapped as strings. So, I thought of template mixins as a too-much-as-macros as they are. Still, why is `u` "more symbolic" than, say `u.left
Re: alias to a property as an argument to a mixin template
On Sunday, 23 September 2012 at 21:42:54 UTC, comco wrote: On Sunday, 23 September 2012 at 19:53:26 UTC, Philippe Sigaud wrote: monarch_dodra already answered, but since, I typed this, I may as well post it :) On Sun, Sep 23, 2012 at 8:49 PM, comco wrote: For this program I'm getting an "Error: need 'this' to access member x" at line (*). Does that mean that we cannot alias a property as an argument of a template mixin? By using s.x, you're not referencing the property, but directly the value s.x, which is known only at runtime: it cannot be a template argument. If x where a static member, you could probably use it, hence the error message (need 'this', ...). So, using string mixins works, but explicit alias to the property name seems not to. Why is that? a.stringof can be obtained for any symbol a, so s.x (or with(s) ... x) just gives "s.x", which can be mixed in. It's transformed into a string, transformation for which there is no need for 'this'. and is there any other way of achieving the result witout using template mixins Sorry but... what result? Referencing a member inside a template? Remember templates can be in another module, written years ago. If you really want a template to act on a local value, either use a mixin template, as you did, or reference the member by its name as a string: import std.stdio; mixin template T(string member) { void f() { mixin("writeln(" ~ member ~ ");"); } } struct S { int x; } void main() { auto s = S(4); mixin T!("s.x"); f(); } // prints 4 I see monarch proposed exactly the same way to do it... Thank you for the answers. Passing a string does the job, but the result I wanted to achieve is: the client of the mixin template to use it without strings. Here's the motivating example: when implementing algorithms for linked data structures, a common pattern is such a chain of assignments: a1 = a2; a2 = a3; a3 = a4 ... For example, take a rotation of a binary tree: struct node { node* left, right; } void rotate(node* u) { auto v = u.right; u.right = v.left; v.left = u; } For this pattern, we may design a template function like this: void reassign(A...)(ref A a) { static if (A.length > 1) { a[0] = a[1]; reassign(a[1 .. $]); } } Now we can implement our rotate in terms of reassign: void rotate(node* u) { auto v = u.right; reassign(u.right, v.left, u); } This works and is general enough, but notice the duplication of u.right. I don't like it - this may become an arbitrary large expression. But the naive attempt fails: void rotate(node* u) { node* v; reassign(v, u.right, v.left, u); // runtime error at v.left } That's because v is not initialized when we call the function. So what we really want is to pass a list of symbols (and I thought `v.left` qualifies as a symbol) to the function, not references to value. But this means we'll need template mixins, because you can pass symbols by alias to them. Since alias arguments for templates are classified as symbolic arguments, I was expecting that you can pass "u.right" as an atomic symbol, without using strings. So, then my strange rotate would look like this: void rotate(node* u) { node* v; mixin ReassignMixin!(v, u.right, v.left, u); reassign(); } See how the client code looks nicer when the template arguments are not wrapped as strings. So, I thought of template mixins as a too-much-as-macros as they are. Still, why is `u` "more symbolic" than, say `u.left Sorry for the last line.
Re: Testing for template argument being result of takeExactly
On Sunday, September 23, 2012 14:47:27 Timon Gehr wrote: > template Hello(R) if(is(typeof(R._input.takeExactly(2)) == R)){ > alias R Hello; > } Thanks. That does the trick quite cleanly, though you'd think that it would be possible to test whether a template argument is the result of takeExactly without caring or knowing about the guts of takeExactly. So, this isn't a general purpose solution at all, when I think that there should be one. Still, I don't need a general purpose one for what I'm doing, so this should work just fine. - Jonathan M Davis
Re: Testing for template argument being result of takeExactly
On 09/23/2012 10:57 PM, Ali Çehreli wrote: ... Also, I think your code should have passed a range like R.init to takeExactly, not R, which is a type: takeExactly(R.init, 1) I don't know why your code compiles. See discussion here: http://d.puremagic.com/issues/show_bug.cgi?id=8220
Re: Testing for template argument being result of takeExactly
On Sunday, September 23, 2012 13:55:04 Philippe Sigaud wrote: > Transforming it into a predicate template is easy, I just wanted to > show that R._input is accessible. I was trying to test it without checking its internals (which should be possible IMHO), but if I have to check its internals, I have to check its internals. Actually, it hadn't occured to me to check its internals, but I would have wanted to avoid it (and still do), but this will work for now. Thanks. > Caution: takeExactly returns a slice when the range is slice-able. You > should test for hasSlicing on R first. Actually, I'm messing with hasSlicing, so I have to be _very_ careful here. Per a discussion on github, I'm changing it to require that the return type of opSlice for finite ranges returns a type which can be assigned to the original type and that for infinite ranges it be the result of takeExactly. The changes to opSlice themselves seem straightforward enough but the side effects on take and takeExactly have gotten a bit hairy, since they reference hasSlicing. I don't think that it'll take many changes, but getting it right has been hard. > As for Voldemort (Nameless One, Dark Lord, whatever) types, I find > them more annoying than useful, personally. Due to how they affect the init property and some other stuff, they may have to be axed (there's a bug report discussing some of those issues somewhere, but I don't remember it's number), but we still have them for the moment. The idea is cool, but the ultimate result is definitely problematic. - Jonathan M Davis
memory de-allocation?
Given: void main () { system("rdmd prog_one.d"); //... output from prog_one system("rdmd prog_two.d"); //... output again from prog_one and new output from prog_two. } Any suggestions for getting rid of the ghost of prog_one?
Re: Testing for template argument being result of takeExactly
On Sunday, 23 September 2012 at 21:52:23 UTC, Timon Gehr wrote: On 09/23/2012 10:57 PM, Ali Çehreli wrote: ... Also, I think your code should have passed a range like R.init to takeExactly, not R, which is a type: takeExactly(R.init, 1) I don't know why your code compiles. See discussion here: http://d.puremagic.com/issues/show_bug.cgi?id=8220 Interesting. Thanks. On Sunday, 23 September 2012 at 21:53:20 UTC, Jonathan M Davis wrote: On Sunday, September 23, 2012 14:47:27 Timon Gehr wrote: template Hello(R) if(is(typeof(R._input.takeExactly(2)) == R)){ alias R Hello; } Thanks. That does the trick quite cleanly, though you'd think that it would be possible to test whether a template argument is the result of takeExactly without caring or knowing about the guts of takeExactly. So, this isn't a general purpose solution at all, when I think that there should be one. Still, I don't need a general purpose one for what I'm doing, so this should work just fine. - Jonathan M Davis What is wrong with my proposed solution? import std.range; template Hello(R) if ( is(typeof(takeExactly(R.init, 1))) && is(R == typeof(takeExactly(R.init, 1))) ) { alias R Hello; } struct R { enum empty = false; @property int front(); void popFront(); } struct S{} void main( ) { Hello!(int[]) a; //OK Hello!R b; //Fails second Check: R == typeof(...) Hello!S c; //Fails first check: is(typeof(takeExactly(...))) } Forgive me again if there is something wrong with it, but this time, I think it is correct...?
Re: Testing for template argument being result of takeExactly
On Monday, 24 September 2012 at 06:20:57 UTC, monarch_dodra wrote: What is wrong with my proposed solution? I think I forgot this test, when R is already a type returned by takeExactly: void main( ) { alias typeof(takeExactly(R.init, 5)) G; Hello!G g; } Which also works.
Re: Testing for template argument being result of takeExactly
On Monday, 24 September 2012 at 06:29:25 UTC, monarch_dodra wrote: On Monday, 24 September 2012 at 06:20:57 UTC, monarch_dodra wrote: What is wrong with my proposed solution? I think I forgot this test, when R is already a type returned by takeExactly: void main( ) { alias typeof(takeExactly(R.init, 5)) G; Hello!G g; } Which also works. Er, sorry for triple post, no edit button. This is R: struct R { enum empty = false; @property int front(); void popFront(); } I meant when "Hello' R is already the result of a Take exactly", sorry for the confusion.