Re: retro() on a `string` creates a range of `dchar`, causing array() pains
On Tuesday, 17 April 2012 at 15:18:49 UTC, bearophile wrote: Jakob Ovrum: return array(strippedTail); } The type of the return expression is dstring, not string. What is the most elegant way or correct way to solve this friction? (Note: the function is used in CTFE) Try "text" instead of "array". Bye, bearophile Thanks, that did it :) (I also forgot to retro() a second time to make it build the array in the original direction, before anyone points it out)
Re: retro() on a `string` creates a range of `dchar`, causing array() pains
On Tuesday, 17 April 2012 at 15:36:39 UTC, Ali Çehreli wrote: The reason is, a sequence of UTF-8 code units are not a valid UTF-8 when reversed (or retro'ed :p). But a dchar array can be reversed. Ali It is absolutely possible to walk a UTF-8 string backwards. The problem here is that arrays of char are ranges of dchar; hence you can't go the regular generic path and have to use text() instead.
Re: Not-so-unpredictable seed?
On Wednesday, 18 April 2012 at 05:05:20 UTC, Joseph Rushton Wakeling wrote: On 18/04/12 06:43, jerro wrote: According to the comment the call to prime() is necessary so that the result doesn't always start with the same element. But prime() uses the gen member which is only assigned after the constructor completes. So at the time when prime() is called the gen member is in some default state, so the prime() call in the constructor always does the same thing. The fix would be to either modify the constructor to take random generator as a parameter if Random type parameter is not void, or to move the call to prime() out of constructor and into all the randomSample functions. In the ones that have a random generator parameter, the call to prime should come after gen is asigned. Ahhh, clear. I should have worked that out from the code, brain not working right today. :-P It still looks like a serious bug to me, so I've filed a report. http://d.puremagic.com/issues/show_bug.cgi?id=7936 Well, off course it's a bug :D. I opened a pull request: https://github.com/D-Programming-Language/phobos/pull/542
Re: Not-so-unpredictable seed?
On 18/04/12 06:43, jerro wrote: According to the comment the call to prime() is necessary so that the result doesn't always start with the same element. But prime() uses the gen member which is only assigned after the constructor completes. So at the time when prime() is called the gen member is in some default state, so the prime() call in the constructor always does the same thing. The fix would be to either modify the constructor to take random generator as a parameter if Random type parameter is not void, or to move the call to prime() out of constructor and into all the randomSample functions. In the ones that have a random generator parameter, the call to prime should come after gen is asigned. Ahhh, clear. I should have worked that out from the code, brain not working right today. :-P It still looks like a serious bug to me, so I've filed a report. http://d.puremagic.com/issues/show_bug.cgi?id=7936
Re: Not-so-unpredictable seed?
On Wednesday, 18 April 2012 at 03:47:31 UTC, Joseph Rushton Wakeling wrote: Can anyone explain to me why, when I compile & run this code, the two samples seeded with the unpredictableSeed always come out with the same starting value? // import std.random, std.range, std.stdio; void main() { auto s = randomSample(iota(0, 100), 5); foreach(uint i; s) writeln(i); writeln(); auto s2 = randomSample(iota(0, 100), 5); foreach(uint i; s2) writeln(i); writeln(); auto urng3 = Random(unpredictableSeed); auto s3 = randomSample(iota(0, 100), 5, urng3); foreach(uint i; s3) writeln(i); writeln(); auto urng4 = Random(unpredictableSeed); auto s4 = randomSample(iota(0, 100), 5, urng4); foreach(uint i; s4) writeln(i); } // In fact it's not just the unpredictable seed -- no matter what seed I pass, so long as an RNG is passed to the randomSample function, the first entry is always the same. Note that this is Phobos' randomSample, not my tweaked implementation. Anyone got any ideas? When you pass in your own random generator, you use this function: auto randomSample(R, Random)(R r, size_t n, Random gen) if (isInputRange!R && hasLength!R && isUniformRNG!Random) { auto ret = RandomSample!(R, Random)(r, n, r.length); ret.gen = gen; return ret; } which calls this constructor: this(R input, size_t howMany, size_t total) { _input = input; _available = total; _toSelect = howMany; enforce(_toSelect <= _available); // we should skip some elements initially so we don't always // start with the first prime(); } According to the comment the call to prime() is necessary so that the result doesn't always start with the same element. But prime() uses the gen member which is only assigned after the constructor completes. At the time when prime() is called the gen member is in some default state, so the prime() call in the constructor always does the same thing. The fix would be to either modify the constructor to take random generator as a parameter if Random type parameter is not void, or to move the call to prime() out of constructor and into all the randomSample functions. In the ones that have a random generator parameter, the call to prime should come after gen is asigned.
Re: appending newly initialized struct to array
On 04/17/2012 02:00 PM, simendsjo wrote: > Sounds like a bug. C style initializers work in other cases: I try not to use them. I think they have this 'feature' of leaving unspecified members uninitialized: struct S { int i; double d; } void main() { S s = { 42 }; // <-- no initializer for S.d assert(s.i == 42); assert(s.d == double.nan); // <-- fails (may work for you) } Is that a bug or a feature? I might have opened it but I don't remember now. :) Ali
Re: Not-so-unpredictable seed?
On Wednesday, 18 April 2012 at 03:47:31 UTC, Joseph Rushton Wakeling wrote: Can anyone explain to me why, when I compile & run this code, the two samples seeded with the unpredictableSeed always come out with the same starting value? // import std.random, std.range, std.stdio; void main() { auto s = randomSample(iota(0, 100), 5); foreach(uint i; s) writeln(i); writeln(); auto s2 = randomSample(iota(0, 100), 5); foreach(uint i; s2) writeln(i); writeln(); auto urng3 = Random(unpredictableSeed); auto s3 = randomSample(iota(0, 100), 5, urng3); foreach(uint i; s3) writeln(i); writeln(); auto urng4 = Random(unpredictableSeed); auto s4 = randomSample(iota(0, 100), 5, urng4); foreach(uint i; s4) writeln(i); } // In fact it's not just the unpredictable seed -- no matter what seed I pass, so long as an RNG is passed to the randomSample function, the first entry is always the same. Note that this is Phobos' randomSample, not my tweaked implementation. Anyone got any ideas? When you pass in your own random generator, you use this function: auto randomSample(R, Random)(R r, size_t n, Random gen) if (isInputRange!R && hasLength!R && isUniformRNG!Random) { auto ret = RandomSample!(R, Random)(r, n, r.length); ret.gen = gen; return ret; } which calls this constructor: this(R input, size_t howMany, size_t total) { _input = input; _available = total; _toSelect = howMany; enforce(_toSelect <= _available); // we should skip some elements initially so we don't always // start with the first prime(); } According to the comment the call to prime() is necessary so that the result doesn't always start with the same element. But prime() uses the gen member which is only assigned after the constructor completes. So at the time when prime() is called the gen member is in some default state, so the prime() call in the constructor always does the same thing. The fix would be to either modify the constructor to take random generator as a parameter if Random type parameter is not void, or to move the call to prime() out of constructor and into all the randomSample functions. In the ones that have a random generator parameter, the call to prime should come after gen is asigned.
Not-so-unpredictable seed?
Can anyone explain to me why, when I compile & run this code, the two samples seeded with the unpredictableSeed always come out with the same starting value? // import std.random, std.range, std.stdio; void main() { auto s = randomSample(iota(0, 100), 5); foreach(uint i; s) writeln(i); writeln(); auto s2 = randomSample(iota(0, 100), 5); foreach(uint i; s2) writeln(i); writeln(); auto urng3 = Random(unpredictableSeed); auto s3 = randomSample(iota(0, 100), 5, urng3); foreach(uint i; s3) writeln(i); writeln(); auto urng4 = Random(unpredictableSeed); auto s4 = randomSample(iota(0, 100), 5, urng4); foreach(uint i; s4) writeln(i); } // In fact it's not just the unpredictable seed -- no matter what seed I pass, so long as an RNG is passed to the randomSample function, the first entry is always the same. Note that this is Phobos' randomSample, not my tweaked implementation. Anyone got any ideas?
Re: appending newly initialized struct to array
On Tuesday, 17 April 2012 at 21:00:55 UTC, simendsjo wrote: On Tue, 17 Apr 2012 22:28:31 +0200, maarten van damme wrote: Just for fun I decided to complete some codejam challenges in D. At some point I wanted to add structs to an array but I got a compiler error. What am I doing wrong? code: struct test{ int x; int y; } void main(){ test[] why; why~={3,5}; } error: wait.d(7): found '}' when expecting ';' following statement wait.d(8): found 'EOF' when expecting ';' following statement wait.d(8): found 'EOF' when expecting '}' following compound statement Is there any reason a why this wouldn't work? Sounds like a bug. C style initializers work in other cases: struct S { int i; } void main() { S[] arr; S s = { 1 }; arr ~= S(1); // But the following barfs //arr ~= { 1 }; //arr ~= { i:1 }; //arr[0] = { 1 }; } No, it is designed. {3,5} is struct initializer: http://dlang.org/declaration.html#StructInitializer And it is only allowed in initializer of variable declarations. why~={3,5}; This is concat assign expression, so you should use test(3,5) instead of {3,5}. That is StructLiteral: http://dlang.org/struct.html#StructLiteral and it is an expression. Bye. Kenji Hara
Re: Sampling algorithms for D
On 13/04/12 10:04, Dmitry Olshansky wrote: OK, I'll see what I can do. I'd like to discuss and refine the design a bit further before making any pull request -- should I take things over to the Phobos mailing list for this ... ? I'm no authority but there is this d.D newsgroup which is perfectly fine for this kind of thing. A lot of nice people just don't (have time to) mess with unwashed masses in D.learn :) Tweaked version, an revision of RandomSample from std.random, is available from https://github.com/WebDrake/RandomSample Feedback on code details and on tests would be very welcome. It seems about 10% slower than the original code I wrote, which I guess is down to factors in the design of the RandomSample struct.
Re: Aquivalent References as in C++?
Namespace: Another idea: instead scope, "in" can get a new functionality. Instead as a synonym for "const" it could mean "not null" for objects. Note that currently in D2 "in" means "scope const". Bye, bearophile
Re: Aquivalent References as in C++?
Another idea: instead scope, "in" can get a new functionality. Instead as a synonym for "const" it could mean "not null" for objects.
Re: appending newly initialized struct to array
simendsjo: Sounds like a bug. C style initializers work in other cases: D language is so much irregular, so many special cases that don't work :-) Bye, bearophile
Re: appending newly initialized struct to array
On Tue, 17 Apr 2012 22:28:31 +0200, maarten van damme wrote: Just for fun I decided to complete some codejam challenges in D. At some point I wanted to add structs to an array but I got a compiler error. What am I doing wrong? code: struct test{ int x; int y; } void main(){ test[] why; why~={3,5}; } error: wait.d(7): found '}' when expecting ';' following statement wait.d(8): found 'EOF' when expecting ';' following statement wait.d(8): found 'EOF' when expecting '}' following compound statement Is there any reason a why this wouldn't work? Sounds like a bug. C style initializers work in other cases: struct S { int i; } void main() { S[] arr; S s = { 1 }; arr ~= S(1); // But the following barfs //arr ~= { 1 }; //arr ~= { i:1 }; //arr[0] = { 1 }; }
Re: appending newly initialized struct to array
On Tue, Apr 17, 2012 at 10:28:31PM +0200, maarten van damme wrote: > Just for fun I decided to complete some codejam challenges in D. At > some point I wanted to add structs to an array but I got a compiler > error. What am I doing wrong? > > code: > struct test{ > int x; > int y; > } > void main(){ > test[] why; > why~={3,5}; > } > > error: > wait.d(7): found '}' when expecting ';' following statement > wait.d(8): found 'EOF' when expecting ';' following statement > wait.d(8): found 'EOF' when expecting '}' following compound statement > > Is there any reason a why this wouldn't work? Try this: why ~= test(3,5); T -- Tell me and I forget. Teach me and I remember. Involve me and I understand. -- Benjamin Franklin
Re: Metaprogramming work around
On Tuesday, 17 April 2012 at 12:46:28 UTC, Kenji Hara wrote: On Tuesday, 17 April 2012 at 12:04:44 UTC, Erèbe wrote: [snip] There is something I still don't understand : mixin template Foo( T... ) { //Code here } mixin Foo!( "Hello", "Word" ); < Good T is TemplateTypeParameter, and matches any kind of template arguments - types, values, and symbols. The both arguments "Hello" and "World" are values, so you can bind them with T. http://dlang.org/template.html#TemplateTupleParameter "mixin template Foo( A, T... ) { //code here } mixin Foo!( "Hello", "Word" ); <--- Fail ! mixin Foo!( string, "Word" ); < Good 'A' is TemplateTypeParameter, and it matches only types. In the first instantiation of Foo, A doesn't match with the value "hello". In the second instantiation, string is type, and T matches with it. http://dlang.org/template.html#TemplateTypeParameter mixin template Foo( alias A, T... ) { //code here } mixin Foo!( "Hello", "world" ); <--- Good mixin Foo!( string, "world" ); <--- Fail ! - 'alias A' is TemplateAliasParameter, and it matches both symbols and values. Then A matches with the value "Hello", but doesn't with the type string. (string is an aliased name of immutable(char)[], and it is built-in array type.) http://dlang.org/template.html#TemplateAliasParameter Kenji Hara Thanks a lot Kenji Hara, I have a better understanding of it now !
Re: retro() on a `string` creates a range of `dchar`, causing array()
Ali Çehreli: Agreed. But I am not that sure about this particular function anymore because for the function to be not 'strongly exception safe', the input string must be invalid UTF-8 to begin with. I am not sure how bad it is to not preserve the actual invalidness of the string in that case. :) I see. This is a matter of design. I see some possible solutions: 1) Do nothing, assume input is well-formed UTF-8, otherwise output will be wrong (or it will throw an exception unsafely). This is what Phobos may be doing in this case. 2) Put a UTF validate inside the function pre-condition if the input is a narrow string. This will slow down code in non-release mode, maybe too much. 3) Use a stronger type system, that enforces pre-conditions and post-conditions in a smarter way. This means if the return value of a function that has 'validate' inside its post-condition is given as input to a function that has 'validate' inside its pre-condition, the validate is run only once even in non-release mode. Generally if you use many string functions this leads to the saving of lot of 'validate' functions. This solution is appreciated by Eiffel languages. 4) Use two different types, one for validated UTF-8 and one for unvalidated UTF-8. Unless you have bad bugs in your code this will avoid most calls to 'validate'. This solution is very simple because it doesn't require a smart compiler, and it's appreciated in languages like Haskell (example, see: http://www.yesodweb.com/ ). Bye, bearophile
appending newly initialized struct to array
Just for fun I decided to complete some codejam challenges in D. At some point I wanted to add structs to an array but I got a compiler error. What am I doing wrong? code: struct test{ int x; int y; } void main(){ test[] why; why~={3,5}; } error: wait.d(7): found '}' when expecting ';' following statement wait.d(8): found 'EOF' when expecting ';' following statement wait.d(8): found 'EOF' when expecting '}' following compound statement Is there any reason a why this wouldn't work?
Re: Aquivalent References as in C++?
On Tuesday, 17 April 2012 at 19:56:11 UTC, Timon Gehr wrote: On 04/17/2012 09:16 PM, Namespace wrote: But C++ does not do that either. Are you asking for a full-blown non-null type system? Yes, but of course only with a special Keyword/Storage class. If it is not the default, how would you enforce it at the caller side? By the compiler who throws an error message or a warning. A warning or a better error message would help also, if a null-reference was in use. But only the message "Access violation" without any information isn't enough, imo. It seems that not-null references wouldn't be a part of D in near future.
Re: retro() on a `string` creates a range of `dchar`, causing array()
On 04/17/2012 12:57 PM, bearophile wrote: >> The algorithm >> above is not exception-safe because stride() may throw. But this way off >> topic on this thread. :) > > You can't expect Phobos to be perfect, it needs to be improved > iteratively. If you think that's not exception safe and and there are simple > means to do it, then please add this in Bugzilla. Being formally aware of a > problem is the second step toward improving the situation. Agreed. But I am not that sure about this particular function anymore because for the function to be not 'strongly exception safe', the input string must be invalid UTF-8 to begin with. I am not sure how bad it is to not preserve the actual invalidness of the string in that case. :) Ali
Re: retro() on a `string` creates a range of `dchar`, causing array()
Ali: > The algorithm is smart. The basic idea for that algorithm was mine, and Andrei was very gentle to implement it, defining it a "Very fun exercise" :-) http://d.puremagic.com/issues/show_bug.cgi?id=7086 > The algorithm > above is not exception-safe because stride() may throw. But this way off > topic on this thread. :) You can't expect Phobos to be perfect, it needs to be improved iteratively. If you think that's not exception safe and and there are simple means to do it, then please add this in Bugzilla. Being formally aware of a problem is the second step toward improving the situation. Bye, bearophile
Re: Aquivalent References as in C++?
On 04/17/2012 09:16 PM, Namespace wrote: But C++ does not do that either. Are you asking for a full-blown non-null type system? Yes, but of course only with a special Keyword/Storage class. If it is not the default, how would you enforce it at the caller side?
Re: Hacking on Phobos
On 17.04.2012 23:27, Joseph Rushton Wakeling wrote: On 17/04/12 20:29, Dmitry Olshansky wrote: First things first - development of phobos is done with dmd. Just because gdc is (logically so) somewhat behind dmd and new compiler features are still coming with every release. Fair enough. I've followed the instructions here: https://xtzgzorex.wordpress.com/2011/07/31/d-building-dmd-and-phobos-on-linux/ I suggest to just modify phobos sources directly. It's DVCS after all so you always have a luxury of commit/revert. I want to do some side-by-side tests of current and new, so it makes sense to just have a myrandom.d. and rdmd --main -unittest /path/to/std/random.d works wonders in development cycle. Oddly enough building rdmd with my newly-build dmd results in error: Just feed it -d switch ;) Still somebody has to step up and upgrade rdmd to use the new way of Phobos. -- Dmitry Olshansky
Re: Hacking on Phobos
On 17/04/12 20:47, H. S. Teoh wrote: The convention is to create a branch for making changes, this way it's very easy to generate pull requests on github if you ever wanted to contribute your code to the official codebase. Branches are super-cheap in git anyway, and you can edit source files to your heart's content since you can easily switch back to master if you mess something up. Yea, I know; normally I would, but I want to do some side-by-side tests of the new and old RandomSample class, and it seems like a PITA to have to go through checkout-compile-copy to /usr/local/lib/-etc.etc. to do comparisons. Yes, there are unittests and (once I compile rdmd successfully:-) I can probably use these, but in the short term it seems simpler to just make a new file containing the bits I need and tweak it there.
Re: Hacking on Phobos
On 17/04/12 20:29, Dmitry Olshansky wrote: First things first - development of phobos is done with dmd. Just because gdc is (logically so) somewhat behind dmd and new compiler features are still coming with every release. Fair enough. I've followed the instructions here: https://xtzgzorex.wordpress.com/2011/07/31/d-building-dmd-and-phobos-on-linux/ I suggest to just modify phobos sources directly. It's DVCS after all so you always have a luxury of commit/revert. I want to do some side-by-side tests of current and new, so it makes sense to just have a myrandom.d. and rdmd --main -unittest /path/to/std/random.d works wonders in development cycle. Oddly enough building rdmd with my newly-build dmd results in error: rdmd.d(197): Error: function std.path.rel2abs!().rel2abs is deprecated /usr/local/include/d2/std/algorithm.d(4226): Error: template std.algorithm.endsWith does not match any function template declaration /usr/local/include/d2/std/algorithm.d(4184): Error: template std.algorithm.endsWith cannot deduce template function from argument types !("a == b")(string,string,string,string,string) /usr/local/include/d2/std/algorithm.d(4226): Error: template instance endsWith!("a == b") errors instantiating template /usr/local/include/d2/std/algorithm.d(4226): Error: template std.algorithm.endsWith does not match any function template declaration /usr/local/include/d2/std/algorithm.d(4184): Error: template std.algorithm.endsWith cannot deduce template function from argument types !("a == b")(string,string,string,string,string) /usr/local/include/d2/std/algorithm.d(4226): Error: template instance endsWith!("a == b") errors instantiating template /usr/local/include/d2/std/algorithm.d(4226): Error: template std.algorithm.endsWith does not match any function template declaration /usr/local/include/d2/std/algorithm.d(4184): Error: template std.algorithm.endsWith cannot deduce template function from argument types !("a == b")(string,string,string,string,string) /usr/local/include/d2/std/algorithm.d(4226): Error: template instance endsWith!("a == b") errors instantiating template /usr/local/include/d2/std/algorithm.d(4226): Error: template std.algorithm.endsWith does not match any function template declaration /usr/local/include/d2/std/algorithm.d(4184): Error: template std.algorithm.endsWith cannot deduce template function from argument types !("a == b")(string,string,string,string,string) /usr/local/include/d2/std/algorithm.d(4226): Error: template instance endsWith!("a == b") errors instantiating template /usr/local/include/d2/std/algorithm.d(4226): Error: template std.algorithm.endsWith does not match any function template declaration /usr/local/include/d2/std/algorithm.d(4184): Error: template std.algorithm.endsWith cannot deduce template function from argument types !("a == b")(string,string,string,string,string) /usr/local/include/d2/std/algorithm.d(4226): Error: template instance endsWith!("a == b") errors instantiating template
Re: Aquivalent References as in C++?
But C++ does not do that either. Are you asking for a full-blown non-null type system? Yes, but of course only with a special Keyword/Storage class.
Re: Aquivalent References as in C++?
On 04/17/2012 08:40 PM, Namespace wrote: Define 'ensure'. Guarantee, that the given object parameter isn't a null reference. But C++ does not do that either. Are you asking for a full-blown non-null type system?
Re: Hacking on Phobos
On Tue, Apr 17, 2012 at 10:29:24PM +0400, Dmitry Olshansky wrote: > On 17.04.2012 22:10, Joseph Rushton Wakeling wrote: > >Hello all, > > > >As per earlier discussion I'm trying to hack on Phobos to update the > >random sampling code. > > > >To do this I've just copied random.d into a new file, randomsample.d, > >which I'm modifying and messing around with; I'm trying to build against > >a local copy of the GitHub Phobos sources. > > > >When I try and compile, > > > >gdc -nophoboslib -I../phobos/ -o randomsample randomsample.d > > > > First things first - development of phobos is done with dmd. Just > because gdc is (logically so) somewhat behind dmd and new compiler > features are still coming with every release. > > The process usually involves git cloning dmd, druntime and phobos. > Then building all of them in the order of dmd, druntime, phobos. > The the tricky part is replacing older binaries and library. You can just edit /etc/dmd.conf to that effect (if it conflicts with your stable version of dmd, you could try to change the git dmd source to look for dmd.conf in a different place, say /usr/src/d-devel/dmd.conf or something, and so you can completely isolate the two installations). > After fresh cutting phobos edge builts make sure Phobos unittests > all pass (make -fposix.mak unittest). > I suggest to just modify phobos sources directly. It's DVCS after > all so you always have a luxury of commit/revert. The convention is to create a branch for making changes, this way it's very easy to generate pull requests on github if you ever wanted to contribute your code to the official codebase. Branches are super-cheap in git anyway, and you can edit source files to your heart's content since you can easily switch back to master if you mess something up. T -- My program has no bugs! Only unintentional features...
Re: Aquivalent References as in C++?
Define 'ensure'. Guarantee, that the given object parameter isn't a null reference.
Re: Templates in classes => what is wrong?
On Tuesday, 17 April 2012 at 18:25:21 UTC, Ali Çehreli wrote: On 04/17/2012 11:13 AM, Xan wrote: > The idea is behind this https://gist.github.com/2407923 > But I receive: > > $ gdmd-4.6 algorisme_code.d > algorisme_code.d:22: Error: variable codi cannot be read at compile time > algorisme_code.d:22: Error: argument to mixin must be a string, not (codi) mixin is about code generation. For that reason the string that is given to it must be available at compile time. Upon analyzing the code, that is the case in your example, but because mixin() appears inside the constructor, it cannot use a string parameter. That's why I had used a template parameter for the function string. There may be a number of solutions but only you can decide on what to do. One solution is to mixin the delegate outside of the constructor and pass as an argument along with its string representation: // Untested code this(... Funcio funcio, string funcioText) { ... } In main: enum funcioText = "..."; auto funcio = mixin(funcioText); ... new Algorisme(..., funcio, funcioText); Ali What is change is this code? Is it the same as this https://gist.github.com/2407923 (I revise the code)? With my (v. 2) code I receive the errors: $ gdmd-4.6 algorisme_code.d algorisme_code.d:44: Error: variable codi cannot be read at compile time algorisme_code.d:44: Error: argument to mixin must be a string, not (codi) algorisme_code.d:45: Error: constructor algorisme_code.Algorisme!(int,int).Algorisme.this (string nom, uint versio, int function(int) funcio, string codi) is not callable using argument types (string,int,_error_,string) Why the string is not given at compile code? I don't understand it! Xan.
Re: Hacking on Phobos
On 17.04.2012 22:10, Joseph Rushton Wakeling wrote: Hello all, As per earlier discussion I'm trying to hack on Phobos to update the random sampling code. To do this I've just copied random.d into a new file, randomsample.d, which I'm modifying and messing around with; I'm trying to build against a local copy of the GitHub Phobos sources. When I try and compile, gdc -nophoboslib -I../phobos/ -o randomsample randomsample.d First things first - development of phobos is done with dmd. Just because gdc is (logically so) somewhat behind dmd and new compiler features are still coming with every release. The process usually involves git cloning dmd, druntime and phobos. Then building all of them in the order of dmd, druntime, phobos. The the tricky part is replacing older binaries and library. After fresh cutting phobos edge builts make sure Phobos unittests all pass (make -fposix.mak unittest). I suggest to just modify phobos sources directly. It's DVCS after all so you always have a luxury of commit/revert. and rdmd --main -unittest /path/to/std/random.d works wonders in development cycle. Thanks & best wishes, -- Joe -- Dmitry Olshansky
Re: Templates in classes => what is wrong?
On 04/17/2012 11:13 AM, Xan wrote: > The idea is behind this https://gist.github.com/2407923 > But I receive: > > $ gdmd-4.6 algorisme_code.d > algorisme_code.d:22: Error: variable codi cannot be read at compile time > algorisme_code.d:22: Error: argument to mixin must be a string, not (codi) mixin is about code generation. For that reason the string that is given to it must be available at compile time. Upon analyzing the code, that is the case in your example, but because mixin() appears inside the constructor, it cannot use a string parameter. That's why I had used a template parameter for the function string. There may be a number of solutions but only you can decide on what to do. One solution is to mixin the delegate outside of the constructor and pass as an argument along with its string representation: // Untested code this(... Funcio funcio, string funcioText) { ... } In main: enum funcioText = "..."; auto funcio = mixin(funcioText); ... new Algorisme(..., funcio, funcioText); Ali
Re: Hacking on Phobos
On Tuesday, April 17, 2012 20:10:51 Joseph Rushton Wakeling wrote: > Hello all, > > As per earlier discussion I'm trying to hack on Phobos to update the random > sampling code. > > To do this I've just copied random.d into a new file, randomsample.d, which > I'm modifying and messing around with; I'm trying to build against a local > copy of the GitHub Phobos sources. > > When I try and compile, > > gdc -nophoboslib -I../phobos/ -o randomsample randomsample.d > > I get a huge list of errors, beginning with: > > /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): > relocation 0 has invalid symbol index 10 > /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): > relocation 1 has invalid symbol index 11 > /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): > relocation 2 has invalid symbol index 2 > /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): > relocation 3 has invalid symbol index 2 > /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): > relocation 4 has invalid symbol index 10 > /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): > relocation 5 has invalid symbol index 12 > /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): > relocation 6 has invalid symbol index 12 > /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): > relocation 7 has invalid symbol index 12 > /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): > relocation 8 has invalid symbol index 2 > /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): > relocation 9 has invalid symbol index 2 You need to link in librt. core.time requires it. - Jonathan M Davis
Re: Aquivalent References as in C++?
On 04/17/2012 08:10 PM, Namespace wrote: > Best of all solutions would be that a > special keyword, for example scope, ensure that lvalues would except but > _no_ null-references. Yes, the keyword would be a little shorter than the assert() or enforce() above but D already has very many keywords. :) Yes, but scope is an unused storage keyword, isn't it? It is used. So it could be an idea to avoid speed losses with the current method and ensure that the object is not null, if it's intentional. Define 'ensure'.
Re: Aquivalent References as in C++?
> Best of all solutions would be that a > special keyword, for example scope, ensure that lvalues would except but > _no_ null-references. Yes, the keyword would be a little shorter than the assert() or enforce() above but D already has very many keywords. :) Yes, but scope is an unused storage keyword, isn't it? So it could be an idea to avoid speed losses with the current method and ensure that the object is not null, if it's intentional.
Re: Templates in classes => what is wrong?
On Tuesday, 17 April 2012 at 18:00:55 UTC, Xan wrote: On Tuesday, 17 April 2012 at 15:59:25 UTC, Ali Çehreli wrote: On 04/17/2012 08:42 AM, Xan wrote: > How to get the "code" of a function or delegate > > |___string toString() { > |___|___return format("%s (versió %s): Domini -> Recorregut, %s(x) = > %s", nom, versio, nom, &funcio); > > |___} > > does not produce the desired result and &funcio without ampersand > produces me an error. > > So, my doubts are: > given a function: > > - how can I get the domain > - how can I get the range I did not understand those. :( Domain is the set of values that we pass to the function and Range is the set of Values which are returned by function. V delegate (U) f; f has Domain U and Range V I want to "print" the type of "U" and "V". Something like: class Algorisme(U,V) { string nom; uint versio; alias V delegate (U) Funcio; Funcio funcio; this(string nom, uint versio, Funcio funcio) { this.nom = nom; this.versio = versio; this.funcio = funcio; } string toString() { return format("%s (versió %s): %s -> %s, %s(x) = %s", nom, versio, V, U, nom, &funcio); } } but I receive algorisme.d:24: Error: type int has no value algorisme.d:24: Error: type int has no value when I call with Algorisme!(int, int) intead of receiving "int" and "int" as Domain and Range > - how can I get the code of the function? > > See https://gist.github.com/2394274 > I don't think D has any help there. You can keep the function as a string yourself and convert to actual code at compile time with a string mixin. For that to happen, the function text may be an additional template parameter: import std.conv, std.stdio, std.stream, std.string; import std.socket, std.socketstream; import std.datetime; class Algorisme(U,V,string funcioText) { string nom; uint versio; alias V delegate (U) Funcio; Funcio funcio; this(string nom, uint versio) { this.nom = nom; this.versio = versio; this.funcio = mixin(funcioText); } string toString() { return format("%s (versió %s): Domini -> Recorregut, %s(x) = %s", nom, versio, nom, funcioText); } } alias Algorisme!(int, int, "(int a) { return 2 * a; }") AlgorismeEnters; void main(string [] args) { auto alg = new AlgorismeEnters("Doblar", 1); writeln(alg); } Ali It's ugly code. I think I could call some procedure like f.code (f is a function) to obtain the "code" how f is defined. But stricly in mathematical thinking it's not adequate, because more codes could result in the same (mathematical function): x + x is the double of x; and 2*x is too. Perhaps if I change Algorisme and add the string field "code" and if there is any procedure to copy the 3rd argument in the constructor and pass as string in the 4th argument (in the constructor) class Algorisme(U,V) { |___string nom; |___uint versio; |___alias V delegate (U) Funcio; |___Funcio funcio; |___string code; |___this(string nom, uint versio, Funcio funcio) { |___|___this.nom = nom; |___|___this.versio = versio; |___|___this.funcio = funcio; this.code = funcio.WHAT PROCEDURE?; |___} Regards, Xan. The idea is behind this https://gist.github.com/2407923 But I receive: $ gdmd-4.6 algorisme_code.d algorisme_code.d:22: Error: variable codi cannot be read at compile time algorisme_code.d:22: Error: argument to mixin must be a string, not (codi) What can I do? Thanks, Xan.
Hacking on Phobos
Hello all, As per earlier discussion I'm trying to hack on Phobos to update the random sampling code. To do this I've just copied random.d into a new file, randomsample.d, which I'm modifying and messing around with; I'm trying to build against a local copy of the GitHub Phobos sources. When I try and compile, gdc -nophoboslib -I../phobos/ -o randomsample randomsample.d I get a huge list of errors, beginning with: /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 0 has invalid symbol index 10 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 1 has invalid symbol index 11 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 2 has invalid symbol index 2 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 3 has invalid symbol index 2 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 4 has invalid symbol index 10 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 5 has invalid symbol index 12 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 6 has invalid symbol index 12 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 7 has invalid symbol index 12 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 8 has invalid symbol index 2 /usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_info): relocation 9 has invalid symbol index 2 ... and continuing on with a huge number of undefined reference errors. To check if it was the source of the problem, I tried downloading and building a local copy of the latest druntime, but the build process fails: $ make -f posix.mak MODEL=64 [lots of successful stuff, followed by ...] src/object_.d(237): Error: function object.TypeInfo.toHash of type @trusted ulong() overrides but is not covariant with object.Object.toHash of type nothrow @trusted ulong() src/object_.d(237): Error: function object.TypeInfo.toHash does not override any function src/object_.d(347): Error: function object.TypeInfo_Vector.getHash of type ulong(const(void*) p) overrides but is not covariant with object.TypeInfo.getHash of type nothrow @trusted ulong(const(void*) p) src/object_.d(347): Error: function object.TypeInfo_Vector.getHash does not override any function I can't find any easy or friendly "get started hacking on Phobos" page, so can anyone advise how to get set up correctly? Thanks & best wishes, -- Joe
Re: Range returned by iota and const
On Tuesday, April 17, 2012 19:22:30 André Stein wrote: > Hi, > > I'm trying to pass the range returned by iota to a function accepting > the parameter as const. I got compilation errors when trying to use the > index operator and after some investigation it turned out that opSlice > of iota.Result isn't declared as const. > > The function body of opSlice of iota.Result doesn't seem to mutate the > range so is there any special reason why it isn't declared as such? (the > same holds for opSlice). Very little on ranges ends up being marked const, because const ranges tend to be useless (since you can't iterate over them). There are a few cases where you could use a range function even if the range is const (this at least appears to be one of them), but const typically gets forgotten simply because const ranges are generally useless. You can open an enhancement request ( d.puremagic.com/issues ) for this though. - Jonathan M Davis
Re: Templates in classes => what is wrong?
On Tuesday, 17 April 2012 at 18:00:55 UTC, Xan wrote: On Tuesday, 17 April 2012 at 15:59:25 UTC, Ali Çehreli wrote: On 04/17/2012 08:42 AM, Xan wrote: > How to get the "code" of a function or delegate > > |___string toString() { > |___|___return format("%s (versió %s): Domini -> Recorregut, %s(x) = > %s", nom, versio, nom, &funcio); > > |___} > > does not produce the desired result and &funcio without ampersand > produces me an error. > > So, my doubts are: > given a function: > > - how can I get the domain > - how can I get the range I did not understand those. :( Domain is the set of values that we pass to the function and Range is the set of Values which are returned by function. V delegate (U) f; f has Domain U and Range V I want to "print" the type of "U" and "V". Something like: class Algorisme(U,V) { string nom; uint versio; alias V delegate (U) Funcio; Funcio funcio; this(string nom, uint versio, Funcio funcio) { this.nom = nom; this.versio = versio; this.funcio = funcio; } string toString() { return format("%s (versió %s): %s -> %s, %s(x) = %s", nom, versio, V, U, nom, &funcio); } } but I receive algorisme.d:24: Error: type int has no value algorisme.d:24: Error: type int has no value Solved with typeid: string toString() { |___|___return format("%s (versió %s): %s -> %s, %s(x) = %s", nom, versio, typeid(V), typeid(U), nom, &funcio); |___}
Re: Aquivalent References as in C++?
On 04/17/2012 10:37 AM, Namespace wrote: >> Yes, you must because whetheer obj is null is only known at runtime. > > Yes, but if i forget the assert i get an Access Violation error with no > more informations. Problem is nobody knows _why_ he gets this error, > because the error message gives no information. In order to get a meaningful error, the compiler would have to inject code that checked every access through a class reference. Unfortunately that would bring too much overhead and not be acceptable in a system language. But it could be a part of the non-release builds. I don't have any idea how slow program would become if every class dereferencing would be checked against null like that. (?) > So it must be a better solution then to write in every method > "assert(obj_param !is null");". Not in every method, but only in methods that actually dereference that pointer. Intermediate functions that simply pass the parameter to another function need not check the condition. In the end, null references are a part of D. The code must be written in a way to accept it. As an aside, enforce() may be more suitable and a little shorter: enforce(obj_param, "Even with a message"); Whether to use assert() or enforce() depends on the function. > Best of all solutions would be that a > special keyword, for example scope, ensure that lvalues would except but > _no_ null-references. Yes, the keyword would be a little shorter than the assert() or enforce() above but D already has very many keywords. :) Finally, actually it is possible to have bugs of the same sort even with references in C++: // C++ code struct S { int i; S(int param_i) : i(param_i) {} }; S * make_S(int i) { return (i == 42) ? new S(i) : 0; } void use_S(const S & s) { int i = s.i; } int main() { use_S(*make_S(100)); } The output is the same as in D: Segmentation fault So, as you see, neither C++ provide any help here. C++'s references have these meanings: * On the parameter list: "I would like to have a real object please." As seen above, it is so easy to violate that. The caller of use_S() realizes that a reference is needed and just dereferences the pointer at hand. See, the caller must ensure even in C++ that the pointer that is available is not NULL. * On the return type: "What I give you is an alias to an existing object." Even this is a false promise without tool support, because the reference may be of an automatic local object. Ali
Re: Templates in classes => what is wrong?
On Tuesday, 17 April 2012 at 15:59:25 UTC, Ali Çehreli wrote: On 04/17/2012 08:42 AM, Xan wrote: > How to get the "code" of a function or delegate > > |___string toString() { > |___|___return format("%s (versió %s): Domini -> Recorregut, %s(x) = > %s", nom, versio, nom, &funcio); > > |___} > > does not produce the desired result and &funcio without ampersand > produces me an error. > > So, my doubts are: > given a function: > > - how can I get the domain > - how can I get the range I did not understand those. :( Domain is the set of values that we pass to the function and Range is the set of Values which are returned by function. V delegate (U) f; f has Domain U and Range V I want to "print" the type of "U" and "V". Something like: class Algorisme(U,V) { string nom; uint versio; alias V delegate (U) Funcio; Funcio funcio; this(string nom, uint versio, Funcio funcio) { this.nom = nom; this.versio = versio; this.funcio = funcio; } string toString() { return format("%s (versió %s): %s -> %s, %s(x) = %s", nom, versio, V, U, nom, &funcio); } } but I receive algorisme.d:24: Error: type int has no value algorisme.d:24: Error: type int has no value when I call with Algorisme!(int, int) intead of receiving "int" and "int" as Domain and Range > - how can I get the code of the function? > > See https://gist.github.com/2394274 > I don't think D has any help there. You can keep the function as a string yourself and convert to actual code at compile time with a string mixin. For that to happen, the function text may be an additional template parameter: import std.conv, std.stdio, std.stream, std.string; import std.socket, std.socketstream; import std.datetime; class Algorisme(U,V,string funcioText) { string nom; uint versio; alias V delegate (U) Funcio; Funcio funcio; this(string nom, uint versio) { this.nom = nom; this.versio = versio; this.funcio = mixin(funcioText); } string toString() { return format("%s (versió %s): Domini -> Recorregut, %s(x) = %s", nom, versio, nom, funcioText); } } alias Algorisme!(int, int, "(int a) { return 2 * a; }") AlgorismeEnters; void main(string [] args) { auto alg = new AlgorismeEnters("Doblar", 1); writeln(alg); } Ali It's ugly code. I think I could call some procedure like f.code (f is a function) to obtain the "code" how f is defined. But stricly in mathematical thinking it's not adequate, because more codes could result in the same (mathematical function): x + x is the double of x; and 2*x is too. Perhaps if I change Algorisme and add the string field "code" and if there is any procedure to copy the 3rd argument in the constructor and pass as string in the 4th argument (in the constructor) class Algorisme(U,V) { |___string nom; |___uint versio; |___alias V delegate (U) Funcio; |___Funcio funcio; |___string code; |___this(string nom, uint versio, Funcio funcio) { |___|___this.nom = nom; |___|___this.versio = versio; |___|___this.funcio = funcio; this.code = funcio.WHAT PROCEDURE?; |___} Regards, Xan.
Re: Aquivalent References as in C++?
Yes, you must because whetheer obj is null is only known at runtime. Yes, but if i forget the assert i get an Access Violation error with no more informations. Problem is nobody knows _why_ he gets this error, because the error message gives no information. So it must be a better solution then to write in every method "assert(obj_param !is null");". Best of all solutions would be that a special keyword, for example scope, ensure that lvalues would except but _no_ null-references.
Range returned by iota and const
Hi, I'm trying to pass the range returned by iota to a function accepting the parameter as const. I got compilation errors when trying to use the index operator and after some investigation it turned out that opSlice of iota.Result isn't declared as const. The function body of opSlice of iota.Result doesn't seem to mutate the range so is there any special reason why it isn't declared as such? (the same holds for opSlice). Regards, André
Re: Aquivalent References as in C++?
For that, you have static if contitions, and indeed you can make it a compile-time error. Can you show me this as code? And are there any plans to realize non-null references or strategies to avoid such things? Otherwise there would really be something important missing in D.
Re: retro() on a `string` creates a range of `dchar`, causing array() pains
On 04/17/2012 09:12 AM, Timon Gehr wrote: > On 04/17/2012 06:09 PM, Ali Çehreli wrote: >> The algorithm must be building a local string. > It does not have to build a local string, see > http://dlang.org/phobos/std_utf.html#strideBack I never said otherwise. :p I was too lazy to locate where 2.059's algorithm.d was placed under. Apparently it is here: /usr/include/x86_64-linux-gnu/dmd/phobos/std/algorithm.d The algorithm is smart. It reverses individual Unicode characters in-place first and then reverses the whole string one last time: void reverse(Char)(Char[] s) if (isNarrowString!(Char[]) && !is(Char == const) && !is(Char == immutable)) { auto r = representation(s); for (size_t i = 0; i < s.length; ) { immutable step = std.utf.stride(s, i); if (step > 1) { .reverse(r[i .. i + step]); i += step; } else { ++i; } } reverse(r); } Ali P.S. Being a C++ programmer, exception-safety is always warm in my mind. Unfortunately the topic does not come up much in D forums. The algorithm above is not exception-safe because stride() may throw. But this way off topic on this thread. :)
Re: retro() on a `string` creates a range of `dchar`, causing array() pains
On 04/17/2012 06:09 PM, Ali Çehreli wrote: On 04/17/2012 08:58 AM, bearophile wrote: > Ali Çehreli: > >> The reason is, a sequence of UTF-8 code units are not a valid UTF-8 >> when reversed (or retro'ed :p). > > But reversed(char[]) now works :-) That's pretty cool. :) (You meant reverse()). Interesting, because there could be no other way anyway because reverse() is in-place. Iterating by dchar without damaging the other end must have been challenging because the first half of the string may have been all multi-bype UTF-8 code units and all of the rest of single-bytes. The algorithm must be building a local string. > Bye, > bearophile Ali It does not have to build a local string, see http://dlang.org/phobos/std_utf.html#strideBack
Re: retro() on a `string` creates a range of `dchar`, causing array() pains
On 04/17/2012 08:58 AM, bearophile wrote: > Ali Çehreli: > >> The reason is, a sequence of UTF-8 code units are not a valid UTF-8 >> when reversed (or retro'ed :p). > > But reversed(char[]) now works :-) That's pretty cool. :) (You meant reverse()). Interesting, because there could be no other way anyway because reverse() is in-place. Iterating by dchar without damaging the other end must have been challenging because the first half of the string may have been all multi-bype UTF-8 code units and all of the rest of single-bytes. The algorithm must be building a local string. > Bye, > bearophile Ali
Re: Templates in classes => what is wrong?
On 04/17/2012 08:42 AM, Xan wrote: > How to get the "code" of a function or delegate > > |___string toString() { > |___|___return format("%s (versió %s): Domini -> Recorregut, %s(x) = > %s", nom, versio, nom, &funcio); > > |___} > > does not produce the desired result and &funcio without ampersand > produces me an error. > > So, my doubts are: > given a function: > > - how can I get the domain > - how can I get the range I did not understand those. :( > - how can I get the code of the function? > > See https://gist.github.com/2394274 > I don't think D has any help there. You can keep the function as a string yourself and convert to actual code at compile time with a string mixin. For that to happen, the function text may be an additional template parameter: import std.conv, std.stdio, std.stream, std.string; import std.socket, std.socketstream; import std.datetime; class Algorisme(U,V,string funcioText) { string nom; uint versio; alias V delegate (U) Funcio; Funcio funcio; this(string nom, uint versio) { this.nom = nom; this.versio = versio; this.funcio = mixin(funcioText); } string toString() { return format("%s (versió %s): Domini -> Recorregut, %s(x) = %s", nom, versio, nom, funcioText); } } alias Algorisme!(int, int, "(int a) { return 2 * a; }") AlgorismeEnters; void main(string [] args) { auto alg = new AlgorismeEnters("Doblar", 1); writeln(alg); } Ali
Re: retro() on a `string` creates a range of `dchar`, causing array() pains
Ali Çehreli: The reason is, a sequence of UTF-8 code units are not a valid UTF-8 when reversed (or retro'ed :p). But reversed(char[]) now works :-) Bye, bearophile
Re: Aquivalent References as in C++?
On 04/17/2012 08:49 AM, Ali Çehreli wrote: > That fails because null is a compile time value and you have a special > template code for that that fails the compilation. Scratch the 'template' part. You don't have templates there but what I said is still valid. Basically, you have some code that fails at compile time. Ali
Re: Aquivalent References as in C++?
On 04/17/2012 02:39 AM, Namespace wrote: >> Bar b = new Bar(42); >> >> new Foo(b); // works >> new Foo(null); // compiler error That fails because null is a compile time value and you have a special template code for that that fails the compilation. >> new Foo(Bar(23)); // works >> new Foo(Bar(25)); // works > > > But if I write > > Bar bn; > new Foo(bn); > > it works also and doesn't throw a compiler error. There, bn is a variable that has it's own life at runtime. Although the compiler can analyze the code to determine that bn never becomes anything but null, we may not want it to be too smart. Imagine that there are lines after Bar bn; that you have just commented out: Bar bn; // bn = foo(); new Foo(bn); Now the compilation would failure would be an annoyance. That's part of the reason why the compiler does not go that deep in its analysis. > To avoid this, I have to write an assert(obj !is null); again. Yes, you must because whetheer obj is null is only known at runtime. > This really sucks. If anybody else works with my Code and puts a null > reference to any method he gets no compiler error and wonder why he gets > a runtime error instead. > Thats very annoying... Ali
Re: retro() on a `string` creates a range of `dchar`, causing array() pains
On 04/17/2012 08:12 AM, Jakob Ovrum wrote: > Consider this simple function: > > private string findParameterList(string typestr) > { > auto strippedHead = typestr.find("(")[1 .. $]; > auto strippedTail = retro(strippedHead).find(")"); > > strippedTail.popFront(); // slice off closing parenthesis > > return array(strippedTail); > } > > The type of the return expression is dstring, not string. The reason is, a sequence of UTF-8 code units are not a valid UTF-8 when reversed (or retro'ed :p). But a dchar array can be reversed. Ali
Re: Templates in classes => what is wrong?
On Tuesday, 17 April 2012 at 15:30:36 UTC, Ali Çehreli wrote: On 04/17/2012 08:17 AM, Xan wrote: Off-topic, could can I define toString having this structure: (versió ): -> , ? (For example, in https://gist.github.com/2394274 I want that Doblar displays as: Doblar (versió 1): int -> int, { return 2 * a; } Thanks a lot, Xan. std.string.format is easy: format("%s%s", 42, "hello"); Ali How to get the "code" of a function or delegate |___string toString() { |___|___return format("%s (versió %s): Domini -> Recorregut, %s(x) = %s", nom, versio, nom, &funcio); |___} does not produce the desired result and &funcio without ampersand produces me an error. So, my doubts are: given a function: - how can I get the domain - how can I get the range - how can I get the code of the function? See https://gist.github.com/2394274
Re: Aquivalent References as in C++?
On Tuesday, 17 April 2012 at 09:39:10 UTC, Namespace wrote: On Tuesday, 17 April 2012 at 08:02:02 UTC, Namespace wrote: Now i have something like this. It works and manipulates lvalues so that i can pass my objects by ref to except null. But is this smart? class Bar { public: int x; static ref Bar opCall(int x) { static Bar b; b = new Bar(x); return b; } this(int x) { this.x = x; } } class Foo { private: Bar _bar; public: int y; this() { } this(ref Bar b) { //assert(b !is null); writefln("B.x %d", b.x); } } Bar b = new Bar(42); new Foo(b); // works new Foo(null); // compiler error new Foo(Bar(23)); // works new Foo(Bar(25)); // works But if I write Bar bn; new Foo(bn); it works also and doesn't throw a compiler error. To avoid this, I have to write an assert(obj !is null); again. This really sucks. If anybody else works with my Code and puts a null reference to any method he gets no compiler error and wonder why he gets a runtime error instead. Thats very annoying... For that, you have static if contitions, and indeed you can make it a compile-time error.
Re: Templates in classes => what is wrong?
On 04/17/2012 08:17 AM, Xan wrote: Off-topic, could can I define toString having this structure: (versió ): -> , ? (For example, in https://gist.github.com/2394274 I want that Doblar displays as: Doblar (versió 1): int -> int, { return 2 * a; } Thanks a lot, Xan. std.string.format is easy: format("%s%s", 42, "hello"); Ali
Re: "shared" status
On Saturday, 14 April 2012 at 10:48:16 UTC, Luis Panadero Guardeño wrote: What is the status of "shared" types ? I try it with gdmd v4.6.3 And I not get any warring/error when I do anything over a shared variable without using atomicOp. It's normal ? shared ushort ram[ram_size]; ram[i] = cast(ushort) (bytes[0] | bytes[1] << 8); Shared is crucial for concurrency/parallelism since the switch to the thread local storage as default storage. Immutable values are IMPLICITLY SHARED while for your mutable data you have to explicitly use "shared" keyword. This basically means that SHARED data are used everywhere in D applications nowadays.
Re: Templates in classes => what is wrong?
On Tuesday, 17 April 2012 at 15:21:30 UTC, Dejan Lekic wrote: On Tuesday, 17 April 2012 at 14:57:18 UTC, Xan wrote: On Tuesday, 17 April 2012 at 01:31:43 UTC, Kenji Hara wrote: On Monday, 16 April 2012 at 18:48:52 UTC, Xan wrote: On Sunday, 15 April 2012 at 19:30:27 UTC, Ali Çehreli wrote: On 04/15/2012 11:39 AM, Xan wrote: > On Sunday, 15 April 2012 at 11:23:37 UTC, John Chapman > wrote: >> On Sunday, 15 April 2012 at 11:16:43 UTC, Xan wrote: >>> >>> int main(string [] args) >>> { >>> auto alg = Algorisme!(int,int); >> >> Should be: >> auto alg = new Algorisme!(int, int); >> >>> alg.nom = "Doblar"; >>> alg.versio = 1; >>> alg.funcio = (int a) {return 2*a}; >> >> Should be: >> alg.funcio = (int a) { return 2 * a; }; >> or: >> alg.funcio = a => 2 * a; >> >>> } > > > It does not work: > > $ gdmd-4.6 algorisme.d > algorisme.d:18: Error: variable algorisme.main.alg voids > have no value > algorisme.d:18: Error: expression class Algorisme is void > and has no value > > with the code https://gist.github.com/2394274 > > What fails now? > > Thanks, > Xan. Your code is still missing 'new': auto alg = new Algorisme!(int, int); With only this change, I receive this error: $ gdmd-4.6 algorisme.d algorisme.d:21: Error: cannot implicitly convert expression (__dgliteral1) of type int delegate(int a) pure nothrow to int function(int) Unrelated recommendations: - Return 0 from main() for successful exit, anything else by convention means some sort of error. - Take advantage of constructors (and 'alias') to simplify syntax and risk of bugs: import std.conv, std.stdio, std.stream, std.string; import std.socket, std.socketstream; import std.datetime; class Algorisme(U,V) { string nom; uint versio; alias V function (U) Funcio; Funcio funcio; this(string nom, uint versio, Funcio funcio) { this.nom = nom; this.versio = versio; this.funcio = funcio; } } int main(string [] args) { alias Algorisme!(int, int) MeuAlgorism; auto alg = new MeuAlgorism("Doblar", 1, (int a) { return 2 * a; }); return 0; } Ali With all of your suggestion [https://gist.github.com/2394274], I get: $ gdmd-4.6 algorisme.d algorisme.d:30: Error: constructor algorisme.Algorisme!(int,int).Algorisme.this (string nom, uint versio, int function(int) funcio) is not callable using argument types (string,int,int delegate(int a) pure nothrow) algorisme.d:30: Error: cannot implicitly convert expression (__dgliteral1) of type int delegate(int a) pure nothrow to int function(int) algorisme.d:27: Error: function D main has no return statement, but is expected to return a value of type int What fails? PS: Thanks for your recommendations... PPS: By the other hand, I see you have learned catalan ("MeuAlgorisme"?) ;-) Problem may be here: alg.funcio = (int a) { return 2 * a; }; 2.057 and earlier (You may use gdc 2.057 and command line wrapper gdmd), function literal always deduced as 'delegate'. So this expression raises an error about type mismatching Lhs of 'int function(int)' and Rhs of 'int delegate(int) pure nothrow'. Then, specifying explicit 'function' will resolve issue: alg.funcio = function(int a) { return 2 * a; }; Bye. Kenji Hara Thanks, Kenji. If I change function to delegate in declaration of field, it works too. What do you recommend to have delegates or functions? What are the benefits and ... Thanks, Xan. For an example, you can't use function-pointer to access non-static methods, while with delegates you can. You can see some examples on http://www.dlang.org (Languate Reference). So, I deduce it's better to use delegater than function?
Re: Templates in classes => what is wrong?
On Tuesday, 17 April 2012 at 14:57:18 UTC, Xan wrote: On Tuesday, 17 April 2012 at 01:31:43 UTC, Kenji Hara wrote: On Monday, 16 April 2012 at 18:48:52 UTC, Xan wrote: On Sunday, 15 April 2012 at 19:30:27 UTC, Ali Çehreli wrote: On 04/15/2012 11:39 AM, Xan wrote: > On Sunday, 15 April 2012 at 11:23:37 UTC, John Chapman > wrote: >> On Sunday, 15 April 2012 at 11:16:43 UTC, Xan wrote: >>> >>> int main(string [] args) >>> { >>> auto alg = Algorisme!(int,int); >> >> Should be: >> auto alg = new Algorisme!(int, int); >> >>> alg.nom = "Doblar"; >>> alg.versio = 1; >>> alg.funcio = (int a) {return 2*a}; >> >> Should be: >> alg.funcio = (int a) { return 2 * a; }; >> or: >> alg.funcio = a => 2 * a; >> >>> } > > > It does not work: > > $ gdmd-4.6 algorisme.d > algorisme.d:18: Error: variable algorisme.main.alg voids > have no value > algorisme.d:18: Error: expression class Algorisme is void > and has no value > > with the code https://gist.github.com/2394274 > > What fails now? > > Thanks, > Xan. Your code is still missing 'new': auto alg = new Algorisme!(int, int); With only this change, I receive this error: $ gdmd-4.6 algorisme.d algorisme.d:21: Error: cannot implicitly convert expression (__dgliteral1) of type int delegate(int a) pure nothrow to int function(int) Unrelated recommendations: - Return 0 from main() for successful exit, anything else by convention means some sort of error. - Take advantage of constructors (and 'alias') to simplify syntax and risk of bugs: import std.conv, std.stdio, std.stream, std.string; import std.socket, std.socketstream; import std.datetime; class Algorisme(U,V) { string nom; uint versio; alias V function (U) Funcio; Funcio funcio; this(string nom, uint versio, Funcio funcio) { this.nom = nom; this.versio = versio; this.funcio = funcio; } } int main(string [] args) { alias Algorisme!(int, int) MeuAlgorism; auto alg = new MeuAlgorism("Doblar", 1, (int a) { return 2 * a; }); return 0; } Ali With all of your suggestion [https://gist.github.com/2394274], I get: $ gdmd-4.6 algorisme.d algorisme.d:30: Error: constructor algorisme.Algorisme!(int,int).Algorisme.this (string nom, uint versio, int function(int) funcio) is not callable using argument types (string,int,int delegate(int a) pure nothrow) algorisme.d:30: Error: cannot implicitly convert expression (__dgliteral1) of type int delegate(int a) pure nothrow to int function(int) algorisme.d:27: Error: function D main has no return statement, but is expected to return a value of type int What fails? PS: Thanks for your recommendations... PPS: By the other hand, I see you have learned catalan ("MeuAlgorisme"?) ;-) Problem may be here: alg.funcio = (int a) { return 2 * a; }; 2.057 and earlier (You may use gdc 2.057 and command line wrapper gdmd), function literal always deduced as 'delegate'. So this expression raises an error about type mismatching Lhs of 'int function(int)' and Rhs of 'int delegate(int) pure nothrow'. Then, specifying explicit 'function' will resolve issue: alg.funcio = function(int a) { return 2 * a; }; Bye. Kenji Hara Thanks, Kenji. If I change function to delegate in declaration of field, it works too. What do you recommend to have delegates or functions? What are the benefits and ... Thanks, Xan. For an example, you can't use function-pointer to access non-static methods, while with delegates you can. You can see some examples on http://www.dlang.org (Languate Reference).
Re: retro() on a `string` creates a range of `dchar`, causing array() pains
Jakob Ovrum: return array(strippedTail); } The type of the return expression is dstring, not string. What is the most elegant way or correct way to solve this friction? (Note: the function is used in CTFE) Try "text" instead of "array". Bye, bearophile
Re: Templates in classes => what is wrong?
Off-topic, could can I define toString having this structure: (versió ): -> , ? (For example, in https://gist.github.com/2394274 I want that Doblar displays as: Doblar (versió 1): int -> int, { return 2 * a; } Thanks a lot, Xan.
Re: "No stack address"
On 4/17/12, Somedude wrote: > Do you have any idea where this is explained rdmd --help
retro() on a `string` creates a range of `dchar`, causing array() pains
Consider this simple function: private string findParameterList(string typestr) { auto strippedHead = typestr.find("(")[1 .. $]; auto strippedTail = retro(strippedHead).find(")"); strippedTail.popFront(); // slice off closing parenthesis return array(strippedTail); } The type of the return expression is dstring, not string. What is the most elegant way or correct way to solve this friction? (Note: the function is used in CTFE)
Re: Templates in classes => what is wrong?
On Tuesday, 17 April 2012 at 01:31:43 UTC, Kenji Hara wrote: On Monday, 16 April 2012 at 18:48:52 UTC, Xan wrote: On Sunday, 15 April 2012 at 19:30:27 UTC, Ali Çehreli wrote: On 04/15/2012 11:39 AM, Xan wrote: > On Sunday, 15 April 2012 at 11:23:37 UTC, John Chapman > wrote: >> On Sunday, 15 April 2012 at 11:16:43 UTC, Xan wrote: >>> >>> int main(string [] args) >>> { >>> auto alg = Algorisme!(int,int); >> >> Should be: >> auto alg = new Algorisme!(int, int); >> >>> alg.nom = "Doblar"; >>> alg.versio = 1; >>> alg.funcio = (int a) {return 2*a}; >> >> Should be: >> alg.funcio = (int a) { return 2 * a; }; >> or: >> alg.funcio = a => 2 * a; >> >>> } > > > It does not work: > > $ gdmd-4.6 algorisme.d > algorisme.d:18: Error: variable algorisme.main.alg voids > have no value > algorisme.d:18: Error: expression class Algorisme is void > and has no value > > with the code https://gist.github.com/2394274 > > What fails now? > > Thanks, > Xan. Your code is still missing 'new': auto alg = new Algorisme!(int, int); With only this change, I receive this error: $ gdmd-4.6 algorisme.d algorisme.d:21: Error: cannot implicitly convert expression (__dgliteral1) of type int delegate(int a) pure nothrow to int function(int) Unrelated recommendations: - Return 0 from main() for successful exit, anything else by convention means some sort of error. - Take advantage of constructors (and 'alias') to simplify syntax and risk of bugs: import std.conv, std.stdio, std.stream, std.string; import std.socket, std.socketstream; import std.datetime; class Algorisme(U,V) { string nom; uint versio; alias V function (U) Funcio; Funcio funcio; this(string nom, uint versio, Funcio funcio) { this.nom = nom; this.versio = versio; this.funcio = funcio; } } int main(string [] args) { alias Algorisme!(int, int) MeuAlgorism; auto alg = new MeuAlgorism("Doblar", 1, (int a) { return 2 * a; }); return 0; } Ali With all of your suggestion [https://gist.github.com/2394274], I get: $ gdmd-4.6 algorisme.d algorisme.d:30: Error: constructor algorisme.Algorisme!(int,int).Algorisme.this (string nom, uint versio, int function(int) funcio) is not callable using argument types (string,int,int delegate(int a) pure nothrow) algorisme.d:30: Error: cannot implicitly convert expression (__dgliteral1) of type int delegate(int a) pure nothrow to int function(int) algorisme.d:27: Error: function D main has no return statement, but is expected to return a value of type int What fails? PS: Thanks for your recommendations... PPS: By the other hand, I see you have learned catalan ("MeuAlgorisme"?) ;-) Problem may be here: alg.funcio = (int a) { return 2 * a; }; 2.057 and earlier (You may use gdc 2.057 and command line wrapper gdmd), function literal always deduced as 'delegate'. So this expression raises an error about type mismatching Lhs of 'int function(int)' and Rhs of 'int delegate(int) pure nothrow'. Then, specifying explicit 'function' will resolve issue: alg.funcio = function(int a) { return 2 * a; }; Bye. Kenji Hara Thanks, Kenji. If I change function to delegate in declaration of field, it works too. What do you recommend to have delegates or functions? What are the benefits and ... Thanks, Xan.
Re: arrays and foreach
On 04/17/2012 12:42 AM, Somedude wrote: Sorry for hijacking this thread, but since you're around, I hope you'll see this message. As a D beginner, I'm browsing through your book. I wanted to tell you that there is something essential missing in it: how to compile. It's actually quite hard to find it in the official website, and since the first chapters are targetted at complete beginners, I thought it would be nice to add a few lines or pages about compilation, linking, debugging, etc. What do you think ? Thank you very much for the feedback. I will do something about that. Although there is no hello world compilation, the dmd command line appears multiple times throughout the chapters. The 'assert and enforce' chapter shows it for the -release compiler switch and coincidentally I am on the 'Unit Testing' chapter as we speak, which includes the -unittest switch. :) But you are right, both dmd and rdmd command lines must appear earlier. Thank you, Ali
Re: "shared" status
On 04/17/2012 06:05 AM, Luis wrote: Thanks! It's very useful. Ali Çehreli wrote: synchronized (job) { *job.slice ~= appendValue; } So shared, at least share data across threads. And using synchronized( ) I could do lock-based access to shared data. Yes. I've used the same Job object there but any class is a lock. (This has been a new concept for me. The "lock part" of the object is called the monitor.) Ali
Re: "shared" status
Thanks! It's very useful. Ali Çehreli wrote: > synchronized (job) { > *job.slice ~= appendValue; > } So shared, at least share data across threads. And using synchronized( ) I could do lock-based access to shared data.
Re: "No stack address"
Le 17/04/2012 09:30, Somedude a écrit : > Anyway, I think I'll add this simple piece of info somewhere in the > wiki. I've already cleaned it up a little. Ok, here it is: http://prowiki.org/wiki4d/wiki.cgi?HowTo/UnitTests
Re: Metaprogramming work around
On Tuesday, 17 April 2012 at 12:04:44 UTC, Erèbe wrote: [snip] There is something I still don't understand : mixin template Foo( T... ) { //Code here } mixin Foo!( "Hello", "Word" ); < Good T is TemplateTypeParameter, and matches any kind of template arguments - types, values, and symbols. The both arguments "Hello" and "World" are values, so you can bind them with T. http://dlang.org/template.html#TemplateTupleParameter "mixin template Foo( A, T... ) { //code here } mixin Foo!( "Hello", "Word" ); <--- Fail ! mixin Foo!( string, "Word" ); < Good 'A' is TemplateTypeParameter, and it matches only types. In the first instantiation of Foo, A doesn't match with the value "hello". In the second instantiation, string is type, and T matches with it. http://dlang.org/template.html#TemplateTypeParameter mixin template Foo( alias A, T... ) { //code here } mixin Foo!( "Hello", "world" ); <--- Good mixin Foo!( string, "world" ); <--- Fail ! - 'alias A' is TemplateAliasParameter, and it matches both symbols and values. Then A matches with the value "Hello", but doesn't with the type string. (string is an aliased name of immutable(char)[], and it is built-in array type.) http://dlang.org/template.html#TemplateAliasParameter Kenji Hara
Re: Compiling Was: arrays and foreach
In this case, I had to type: rdmd -unittest --main test.d Without the --main, I would get linker errors, and couldn't find the reason for these errors. Happily, someone here explained me that the effect of the --main flag was to insert a main() function just for this case. That's not surprising, try to write a C program with no main: ─[ArchBox][/tmp]╼ touch foo.c ─[ArchBox][/tmp]╼ LANG=C gcc foo.c /usr/lib/gcc/i686-pc-linux-gnu/4.7.0/../../../crt1.o: In function `_start': (.text+0x18): undefined reference to `main' collect2: error: ld returned 1 exit status You get the linker errors, because there is no entry-point for your program, but that has nothing to do with D, it's a common behaviour for C, C++, D and other languages. And the unittest(-switch) is also good relativly good explained at http://dlang.org/unittest.html (dlang -> search -> unittest)
Re: Metaprogramming work around
On Tuesday, 17 April 2012 at 10:29:56 UTC, Kenji Hara wrote: On Tuesday, 17 April 2012 at 08:28:45 UTC, Erèbe wrote: Hi, I'm working on some metaprogramming code which implement a Factory and generate an enum from a list of string. So here my questions : 1) The documentation say mixin templates could take as TemplateParameterList a "TemplateParameter , TemplateParameterList" but all my tried to instaciate this template failed lamentably. mixin template Foo(T, R...) { anotherTemplate!(T); Foo!(R); } mixin Foo!( string, string, string); Is something wrong with variadic template and mixin, do i miss something ? 2) Below some code I writed and I wanted to know if you have some advice to improve it (Right maner to do it, TypeChecking, Safety, ...) <- variaidc arguments The code is working is purpose is to create an enum of commands and to create a factory which returns me the command associated to a string. Thanks ! ===Code import std.stdio; import std.traits; import std.conv; //Use to create the enums of every commands mixin template enumGenerator( T... ) { template generate( T... ) { enum string value = T[0] ~ ", " ~ generate!( T[2..$] ).value; } template generate() { enum string value = "UNKNOW"; } //Here the creation of the enum mixin("enum Command { " ~ generate!(T).value ~ "};"); } //Generate a function which return a command in regard of a string mixin template factoryGenerator( T... ) { template generate( T... ) { enum string value = "if( cmd == \"" ~ T[1] ~ "\")" ~ "return Command." ~ T[0] ~ ";" ~ "else " ~ generate!(T[2..$]).value; } template generate() { enum string value = "return Command.UNKNOW;"; } //The function in question auto CommandFactory( string cmd ) { mixin( generate!(T).value ); } } mixin template IrcCommands( T... ) { mixin enumGenerator!( T ); mixin factoryGenerator!( T ); } void main() { /*Command*/ /*String associated*/ mixin IrcCommands!( "Connected","001", "NicknameUsed", "433", "Message", "PRIVMSG", "UserLeaved", "PART", "UserJoined", "JOIN", "UserQuit", "QUIT" "UserQuit", "QUIT", // lack of comma "Ping", "PING" ); writefln( to!string(CommandFactory("001")) ); } You can debug templates with adding static assertions in some where, like: mixin template enumGenerator( T... ) { template generate( T... ) { static assert(T.length%2==0 && is(typeof(T[0]) : string)); // check enum string value = T[0] ~ ", " ~ generate!( T[2..$] ).value; } //[snip] } mixin template factoryGenerator( T... ) { template generate( T... ) { static assert(T.length%2==0 && is(typeof(T[1]) : string)); // check enum string value = "if( cmd == \"" ~ T[1] ~ "\")" ~ "return Command." ~ T[0] ~ ";" ~ "else " ~ generate!(T[2..$]).value; } //[snip] } Bye. Kenji Hara Thanks for the comma ! The issue with static assert (in my case) is that the compiler blow you a full page of "template's instatiation error" before the message of your assert. Ok not even a page of the size of c++ template error, but that lead to your message be less noticeable. While browsering the standard librairy I found this : static if ( expression ) //put your code here else assert(false, "your message"); With this, the compiler print just one line, "your message". That pretty neat and readable enough for me :) Stick in the magic pragma(msg, value); in here you won't regret it ;) Another important thing to note here is that you should really reconsider using plain if/else if it's a production code not some toy to learn meta programming. At very least try to generate switch over strings but I don't think any D compiler optimizes it. (but it should in future) Real world options are binary search on string table or even better built-in hash table. Thanks for pragma, it's awesome ! You guessed right, this code is just for the sake of learning some D meta programming. But I will try with an built-in hash table. There is something I still don't understand : mixin template Foo( T... ) { //Code here } mixin Foo!( "Hello", "Word" ); < Good mixin template Foo( A, T... ) { //code here } mixin Foo!( "Hello", "Word" ); <--- Fail ! mixin Foo!( string, "Word" ); < Good mixin template Foo( alias A, T... ) { //code here } mixin Foo!( "Hello", "world" ); <--- Good
Re: Compiling Was: arrays and foreach
Le 17/04/2012 12:19, Mike Parker a écrit : > On 4/17/2012 4:42 PM, Somedude wrote: > >>> >>> Ali >>> >>> >> Hi Ali, >> >> Sorry for hijacking this thread, but since you're around, I hope you'll >> see this message. As a D beginner, I'm browsing through your book. >> I wanted to tell you that there is something essential missing in it: >> how to compile. It's actually quite hard to find it in the official >> website, and since the first chapters are targetted at complete >> beginners, I thought it would be nice to add a few lines or pages about >> compilation, linking, debugging, etc. >> What do you think ? > > In the sidebar at dlang.org, under Documentation, is a link labeled > "Tutorial". The very first code example shows a minimal program and how > to compile it. Well, yes, that's sufficient for "Hello, world", but not for something barely more complex, i.e a function with a unit test. In this case, I had to type: rdmd -unittest --main test.d Without the --main, I would get linker errors, and couldn't find the reason for these errors. Happily, someone here explained me that the effect of the --main flag was to insert a main() function just for this case. Now, I see there is a mention of this in http://dlang.org/rdmd.html But without rdmd, I would compile with dmd, which has no --main switch, and it would still fail to link, because of lack of main(). The code I posted wasn't my code, and I knew it had worked, so I assumed it was correct, I didn't figure out that adding a main() was necessary given there was a unit test. And anyway, explaining in the book how to link is a necessary step imho. This is why I made this page more visible in the Wiki: http://prowiki.org/wiki4d/wiki.cgi?D__Tutorial/CompilingLinkingD
Re: Metaprogramming work around
On 17.04.2012 12:28, "Erèbe" wrote: Hi, I'm working on some metaprogramming code which implement a Factory and generate an enum from a list of string. So here my questions : 1) The documentation say mixin templates could take as TemplateParameterList a "TemplateParameter , TemplateParameterList" but all my tried to instaciate this template failed lamentably. mixin template Foo(T, R...) { anotherTemplate!(T); Foo!(R); } mixin Foo!( string, string, string); Is something wrong with variadic template and mixin, do i miss something ? 2) Below some code I writed and I wanted to know if you have some advice to improve it (Right maner to do it, TypeChecking, Safety, ...) <- variaidc arguments The code is working is purpose is to create an enum of commands and to create a factory which returns me the command associated to a string. Thanks ! ===Code import std.stdio; import std.traits; import std.conv; //Use to create the enums of every commands mixin template enumGenerator( T... ) { template generate( T... ) { enum string value = T[0] ~ ", " ~ generate!( T[2..$] ).value; } template generate() { enum string value = "UNKNOW"; } //Here the creation of the enum mixin("enum Command { " ~ generate!(T).value ~ "};"); } //Generate a function which return a command in regard of a string mixin template factoryGenerator( T... ) { template generate( T... ) { enum string value = "if( cmd == \"" ~ T[1] ~ "\")" ~ "return Command." ~ T[0] ~ ";" ~ "else " ~ generate!(T[2..$]).value; Stick in the magic pragma(msg, value); in here you won't regret it ;) } Another important thing to note here is that you should really reconsider using plain if/else if it's a production code not some toy to learn meta programming. At very least try to generate switch over strings but I don't think any D compiler optimizes it. (but it should in future) Real world options are binary search on string table or even better built-in hash table. -- Dmitry Olshansky
Re: Metaprogramming work around
On Tuesday, 17 April 2012 at 08:28:45 UTC, Erèbe wrote: Hi, I'm working on some metaprogramming code which implement a Factory and generate an enum from a list of string. So here my questions : 1) The documentation say mixin templates could take as TemplateParameterList a "TemplateParameter , TemplateParameterList" but all my tried to instaciate this template failed lamentably. mixin template Foo(T, R...) { anotherTemplate!(T); Foo!(R); } mixin Foo!( string, string, string); Is something wrong with variadic template and mixin, do i miss something ? 2) Below some code I writed and I wanted to know if you have some advice to improve it (Right maner to do it, TypeChecking, Safety, ...) <- variaidc arguments The code is working is purpose is to create an enum of commands and to create a factory which returns me the command associated to a string. Thanks ! ===Code import std.stdio; import std.traits; import std.conv; //Use to create the enums of every commands mixin template enumGenerator( T... ) { template generate( T... ) { enum string value = T[0] ~ ", " ~ generate!( T[2..$] ).value; } template generate() { enum string value = "UNKNOW"; } //Here the creation of the enum mixin("enum Command { " ~ generate!(T).value ~ "};"); } //Generate a function which return a command in regard of a string mixin template factoryGenerator( T... ) { template generate( T... ) { enum string value = "if( cmd == \"" ~ T[1] ~ "\")" ~ "return Command." ~ T[0] ~ ";" ~ "else " ~ generate!(T[2..$]).value; } template generate() { enum string value = "return Command.UNKNOW;"; } //The function in question auto CommandFactory( string cmd ) { mixin( generate!(T).value ); } } mixin template IrcCommands( T... ) { mixin enumGenerator!( T ); mixin factoryGenerator!( T ); } void main() { /*Command*/ /*String associated*/ mixin IrcCommands!( "Connected","001", "NicknameUsed", "433", "Message", "PRIVMSG", "UserLeaved", "PART", "UserJoined", "JOIN", "UserQuit", "QUIT" "UserQuit", "QUIT", // lack of comma "Ping", "PING" ); writefln( to!string(CommandFactory("001")) ); } You can debug templates with adding static assertions in some where, like: mixin template enumGenerator( T... ) { template generate( T... ) { static assert(T.length%2==0 && is(typeof(T[0]) : string)); // check enum string value = T[0] ~ ", " ~ generate!( T[2..$] ).value; } //[snip] } mixin template factoryGenerator( T... ) { template generate( T... ) { static assert(T.length%2==0 && is(typeof(T[1]) : string)); // check enum string value = "if( cmd == \"" ~ T[1] ~ "\")" ~ "return Command." ~ T[0] ~ ";" ~ "else " ~ generate!(T[2..$]).value; } //[snip] } Bye. Kenji Hara
Compiling Was: arrays and foreach
On 4/17/2012 4:42 PM, Somedude wrote: Ali Hi Ali, Sorry for hijacking this thread, but since you're around, I hope you'll see this message. As a D beginner, I'm browsing through your book. I wanted to tell you that there is something essential missing in it: how to compile. It's actually quite hard to find it in the official website, and since the first chapters are targetted at complete beginners, I thought it would be nice to add a few lines or pages about compilation, linking, debugging, etc. What do you think ? In the sidebar at dlang.org, under Documentation, is a link labeled "Tutorial". The very first code example shows a minimal program and how to compile it.
Re: Aquivalent References as in C++?
On Tuesday, 17 April 2012 at 08:02:02 UTC, Namespace wrote: Now i have something like this. It works and manipulates lvalues so that i can pass my objects by ref to except null. But is this smart? class Bar { public: int x; static ref Bar opCall(int x) { static Bar b; b = new Bar(x); return b; } this(int x) { this.x = x; } } class Foo { private: Bar _bar; public: int y; this() { } this(ref Bar b) { //assert(b !is null); writefln("B.x %d", b.x); } } Bar b = new Bar(42); new Foo(b); // works new Foo(null); // compiler error new Foo(Bar(23)); // works new Foo(Bar(25)); // works But if I write Bar bn; new Foo(bn); it works also and doesn't throw a compiler error. To avoid this, I have to write an assert(obj !is null); again. This really sucks. If anybody else works with my Code and puts a null reference to any method he gets no compiler error and wonder why he gets a runtime error instead. Thats very annoying...
Metaprogramming work around
Hi, I'm working on some metaprogramming code which implement a Factory and generate an enum from a list of string. So here my questions : 1) The documentation say mixin templates could take as TemplateParameterList a "TemplateParameter , TemplateParameterList" but all my tried to instaciate this template failed lamentably. mixin template Foo(T, R...) { anotherTemplate!(T); Foo!(R); } mixin Foo!( string, string, string); Is something wrong with variadic template and mixin, do i miss something ? 2) Below some code I writed and I wanted to know if you have some advice to improve it (Right maner to do it, TypeChecking, Safety, ...) <- variaidc arguments The code is working is purpose is to create an enum of commands and to create a factory which returns me the command associated to a string. Thanks ! ===Code import std.stdio; import std.traits; import std.conv; //Use to create the enums of every commands mixin template enumGenerator( T... ) { template generate( T... ) { enum string value = T[0] ~ ", " ~ generate!( T[2..$] ).value; } template generate() { enum string value = "UNKNOW"; } //Here the creation of the enum mixin("enum Command { " ~ generate!(T).value ~ "};"); } //Generate a function which return a command in regard of a string mixin template factoryGenerator( T... ) { template generate( T... ) { enum string value = "if( cmd == \"" ~ T[1] ~ "\")" ~ "return Command." ~ T[0] ~ ";" ~ "else " ~ generate!(T[2..$]).value; } template generate() { enum string value = "return Command.UNKNOW;"; } //The function in question auto CommandFactory( string cmd ) { mixin( generate!(T).value ); } } mixin template IrcCommands( T... ) { mixin enumGenerator!( T ); mixin factoryGenerator!( T ); } void main() { /*Command*/ /*String associated*/ mixin IrcCommands!( "Connected","001", "NicknameUsed", "433", "Message", "PRIVMSG", "UserLeaved", "PART", "UserJoined", "JOIN", "UserQuit", "QUIT" "Ping", "PING" ); writefln( to!string(CommandFactory("001")) ); }
Re: Thread join behaviour
Le 17/04/2012 08:40, Russel Winder a écrit : > On Mon, 2012-04-16 at 21:03 +0200, Somedude wrote: > [...] > > Issue 7919 > > http://d.puremagic.com/issues/show_bug.cgi?id=7919 > Thanks.
Re: Aquivalent References as in C++?
Now i have something like this. It works and manipulates lvalues so that i can pass my objects by ref to except null. But is this smart? class Bar { public: int x; static ref Bar opCall(int x) { static Bar b; b = new Bar(x); return b; } this(int x) { this.x = x; } } class Foo { private: Bar _bar; public: int y; this() { } this(ref Bar b) { //assert(b !is null); writefln("B.x %d", b.x); } } Bar b = new Bar(42); new Foo(b); // works new Foo(null); // compiler error new Foo(Bar(23)); // works new Foo(Bar(25)); // works
Re: arrays and foreach
Le 17/04/2012 02:01, Ali Çehreli a écrit : > On 04/16/2012 04:56 PM, darkstalker wrote: >> i have this example program: >> >> --- >> void main() >> { >> int[3] a; >> foreach (p; a) >> p = 42; >> writeln(a); >> } >> --- >> >> after running it, i expect to get [42, 42, 42] but instead i get [0, 0, >> 0] (i know that you can do a[] = 42, it's just a trivial example). So it >> seems that you cannot write into the array because the elements are >> being passed by value each iteration. It possible to have 'p' passed by >> reference? > > Yes: > > foreach (ref p; a) > > Ali > > Hi Ali, Sorry for hijacking this thread, but since you're around, I hope you'll see this message. As a D beginner, I'm browsing through your book. I wanted to tell you that there is something essential missing in it: how to compile. It's actually quite hard to find it in the official website, and since the first chapters are targetted at complete beginners, I thought it would be nice to add a few lines or pages about compilation, linking, debugging, etc. What do you think ?
Re: "No stack address"
Le 17/04/2012 01:26, Andrej Mitrovic a écrit : > On 4/17/12, Somedude wrote: >> But running the exe crashes immediately at execution with "unauthorized >> instruction". Why ? > > That's the old exectuable leftover from the previous compile. RDMD > generates the exe in a temporary folder with a random name and runs it > immediately. Because the main function doesn't do anything (RDMD > provides an empty one via --main), the app exited immediately. > >> And how do I execute the unit test ? > > rdmd -unittest --main test.d Thanks, it works. BTW, I couldn't find this information. Do you have any idea where this is explained (in particular the --main switch) that I overlooked ? Anyway, I think I'll add this simple piece of info somewhere in the wiki. I've already cleaned it up a little.