odd behavior of split() function
I would like to split "A+B+C+D" into "A", "B", "C", "D" but when using split() I get "A+B+C+D", "B+C+D", "C+D", "D" the code is below import std.stdio; import std.string; import std.array; int main() { string [] str_list; string test_str = "A+B+C+D"; str_list = test_str.split("+"); foreach(item; str_list) printf("%s\n", cast(char*)item); return 0; }
Re: odd behavior of split() function
On Friday, June 07, 2013 09:18:57 Bedros wrote: > I would like to split "A+B+C+D" into "A", "B", "C", "D" > > but when using split() I get > > "A+B+C+D", "B+C+D", "C+D", "D" > > > the code is below > > > import std.stdio; > import std.string; > import std.array; > > int main() > { > string [] str_list; > string test_str = "A+B+C+D"; > str_list = test_str.split("+"); > foreach(item; str_list) > printf("%s\n", cast(char*)item); > > return 0; > } That would be because of your misuse of printf. If you used foreach(item; str_list) writeln(item); you would have been fine. D string literals do happen to have a null character one past their end so that you can pass them directly to C functions, but D strings in general are _not_ null terminated, and printf expects strings to be null terminated. If you want to convert a D string to a null terminated string, you need to use std.string.toStringz, not a cast. You should pretty much never cast a D string to char* or const char* or any variant thereof. So, you could have done printf("%s\n", toStringz(item)); but I don't know why you'd want to use printf rather than writeln or writefln - both of which (unlike printf) are typesafe and understand D types. You got "A+B+C+D", "B+C+D", "C+D", "D" because the original string (being a string literal) had a null character one past its end, and each of the strings returned by split was a slice of the original string, and printf blithely ignored the actual boundaries of the slice looking for the next null character that it happened to find in memory, which - because they were all slices of the same string literal - happened to be the end of the original string literal. And the strings printed differed, because each slice started in a different portion of the underlying array. - Jonathan M Davis
Re: geting stack trace from signal handlers
On Thursday, 6 June 2013 at 21:50:58 UTC, Timothee Cour wrote: Great! two issues (on OSX at least): A) it seems the top-most element of the call stack gets chopped off; eg in your code, the main_module.main symbol will not appear in the stack trace. Any idea why or how to fix that? Is that some inlining issue ? I tried with dmd -g, or -gs or -gc. This can be annoying when the top-most function is a large function and it's not at all clear where the code stopped. I haven't got Mac OSX to test it out but I fixed it a little bit so it is less hacky: http://dpaste.dzfl.pl/241c6fb5 Compiler switches you may want to consider are: -gc -L--export-dynamic -O0 B) there are no line numbers. I did a complex workaround by launching a process and calling atos to get those, but isn't there a better way? Yeah, it is a complex issue. There are 2 ways to fix it from what I know. 1) pipe addresses to addr2line - easier 2) use libdwarf - more complex but also more out-of-box solution
Re: odd behavior of split() function
first of all, many thanks for the quick reply. I'm learning D and it's just because of the habit I unconsciously used printf instead of writef thanks again. -Bedros On Friday, 7 June 2013 at 07:29:48 UTC, Jonathan M Davis wrote: On Friday, June 07, 2013 09:18:57 Bedros wrote: I would like to split "A+B+C+D" into "A", "B", "C", "D" but when using split() I get "A+B+C+D", "B+C+D", "C+D", "D" the code is below import std.stdio; import std.string; import std.array; int main() { string [] str_list; string test_str = "A+B+C+D"; str_list = test_str.split("+"); foreach(item; str_list) printf("%s\n", cast(char*)item); return 0; } That would be because of your misuse of printf. If you used foreach(item; str_list) writeln(item); you would have been fine. D string literals do happen to have a null character one past their end so that you can pass them directly to C functions, but D strings in general are _not_ null terminated, and printf expects strings to be null terminated. If you want to convert a D string to a null terminated string, you need to use std.string.toStringz, not a cast. You should pretty much never cast a D string to char* or const char* or any variant thereof. So, you could have done printf("%s\n", toStringz(item)); but I don't know why you'd want to use printf rather than writeln or writefln - both of which (unlike printf) are typesafe and understand D types. You got "A+B+C+D", "B+C+D", "C+D", "D" because the original string (being a string literal) had a null character one past its end, and each of the strings returned by split was a slice of the original string, and printf blithely ignored the actual boundaries of the slice looking for the next null character that it happened to find in memory, which - because they were all slices of the same string literal - happened to be the end of the original string literal. And the strings printed differed, because each slice started in a different portion of the underlying array. - Jonathan M Davis
Re: odd behavior of split() function
Am 07.06.2013 09:53, schrieb Bedros: first of all, many thanks for the quick reply. I'm learning D and it's just because of the habit I unconsciously used printf instead of writef thanks again. -Bedros On Friday, 7 June 2013 at 07:29:48 UTC, Jonathan M Davis wrote: On Friday, June 07, 2013 09:18:57 Bedros wrote: I would like to split "A+B+C+D" into "A", "B", "C", "D" but when using split() I get "A+B+C+D", "B+C+D", "C+D", "D" the code is below import std.stdio; import std.string; import std.array; int main() { string [] str_list; string test_str = "A+B+C+D"; str_list = test_str.split("+"); foreach(item; str_list) printf("%s\n", cast(char*)item); return 0; } That would be because of your misuse of printf. If you used foreach(item; str_list) writeln(item); you would have been fine. D string literals do happen to have a null character one past their end so that you can pass them directly to C functions, but D strings in general are _not_ null terminated, and printf expects strings to be null terminated. If you want to convert a D string to a null terminated string, you need to use std.string.toStringz, not a cast. You should pretty much never cast a D string to char* or const char* or any variant thereof. So, you could have done printf("%s\n", toStringz(item)); but I don't know why you'd want to use printf rather than writeln or writefln - both of which (unlike printf) are typesafe and understand D types. You got "A+B+C+D", "B+C+D", "C+D", "D" because the original string (being a string literal) had a null character one past its end, and each of the strings returned by split was a slice of the original string, and printf blithely ignored the actual boundaries of the slice looking for the next null character that it happened to find in memory, which - because they were all slices of the same string literal - happened to be the end of the original string literal. And the strings printed differed, because each slice started in a different portion of the underlying array. - Jonathan M Davis You can use printf if you want to, the correct usage is not so nice though: string str = "test"; printf("%.*s", str.length, str.ptr); Kind Regards Benjamin Thaut
Re: geting stack trace from signal handlers
On Fri, Jun 7, 2013 at 12:39 AM, nazriel wrote: > On Thursday, 6 June 2013 at 21:50:58 UTC, Timothee Cour wrote: > >> Great! >> two issues (on OSX at least): >> >> A) >> it seems the top-most element of the call stack gets chopped off; eg in >> your code, the main_module.main symbol will not appear in the stack trace. >> Any idea why or how to fix that? >> Is that some inlining issue ? I tried with dmd -g, or -gs or -gc. >> This can be annoying when the top-most function is a large function and >> it's not at all clear where the code stopped. >> >> I haven't got Mac OSX to test it out but I fixed it a little bit so it > is less hacky: > > http://dpaste.dzfl.pl/241c6fb5 > Thanks, ya, the demangling part is the easy part :) (although demangle is still incomplete in many cases...) > Compiler switches you may want to consider are: > -gc -L--export-dynamic -O0 export-dynamic or rdynamic are not available on OSX. -gc doesn't change anything on dmd (and -O0 isn't available on dmd) -gc -O0 doesn't change anything on ldc > > > B) >> there are no line numbers. I did a complex workaround by launching a >> process and calling atos to get those, but isn't there a better way? >> >> Yeah, it is a complex issue. There are 2 ways to fix it from what I know. > 1) pipe addresses to addr2line - easier > OSX doesn't have addr2line, hence my solution based on piping to atos on OSX. It works except in a few cases where for some reason only the basename of the file is shown instead of full file path, but its a bit complex so i was hoping for simpler. > 2) use libdwarf - more complex but also more out-of-box solution Thanks for the link, that sounds promising! Will look at it. under doc: http://sourceforge.net/apps/trac/elftoolchain/wiki/libdwarf relevant sections: "Line Number Operations"
Conditional compilation
Hi folks, I need to apply different calling conventions to the same interfaces when compiling for different platform. It's something like this: OSX: interface InterfaceA : IUnknown { extern(C): ... } Windows: interface InterfaceA : IUnknown { ... } I have to add extern(C) on OSX because apparently when the compiler sees IUnknown it automatically assumes the calling convention is extern(Windows) and in order to maintain compatibility with existing system I have to explicitly declare them as extern(C). Now I have several dozens of interfaces like the above. I don't want to repeat them for OSX and Windows because the interface definitions are identical except the extern(C) line. I have tried using version() like this: interface InterfaceA : IUnknown { version(OSX) { extern(C): } ...methohds. } but it doesn't work because version limits the scope of the extern(C). static if has the same problem. In C/C++ this is really easy, I can simply define a macro which expands to extern(C) on OSX and nothing on windows. Is there any way to achieve this in D without repeating the interface definitions?
Re: Conditional compilation
string mixins and template mixins don't work either. On Friday, 7 June 2013 at 12:14:45 UTC, finalpatch wrote: Hi folks, I need to apply different calling conventions to the same interfaces when compiling for different platform. It's something like this: OSX: interface InterfaceA : IUnknown { extern(C): ... } Windows: interface InterfaceA : IUnknown { ... } I have to add extern(C) on OSX because apparently when the compiler sees IUnknown it automatically assumes the calling convention is extern(Windows) and in order to maintain compatibility with existing system I have to explicitly declare them as extern(C). Now I have several dozens of interfaces like the above. I don't want to repeat them for OSX and Windows because the interface definitions are identical except the extern(C) line. I have tried using version() like this: interface InterfaceA : IUnknown { version(OSX) { extern(C): } ...methohds. } but it doesn't work because version limits the scope of the extern(C). static if has the same problem. In C/C++ this is really easy, I can simply define a macro which expands to extern(C) on OSX and nothing on windows. Is there any way to achieve this in D without repeating the interface definitions?
Emplace using private constructor
In a project I'm working on there are classes that are available publicly but I want to disable their construction outside of their modules. class Display { const string name; private this(string name) { this.name = name; } static Display[] all() { // Returns all available displays, the only place where Display objects // are to be constructed. } } This is easy when using "new". But I'm using std.conv.emplace which does not work with private constructors. "Don't know how to initialize an object of type Display with arguments (string)" Is there any solution to this problem? I know I can just make the constructor public but it just feels wrong, I want to keep public API as small as possible and it bugs me that language/library limits me here.
Re: Conditional compilation
On Friday, 7 June 2013 at 12:14:45 UTC, finalpatch wrote: Hi folks, I need to apply different calling conventions to the same interfaces when compiling for different platform. extern(System) On Windows, it will be seen by the compiler as extern(Windows), elsewhere as extern(C).
Re: Learning D
Thanks for all the fantastic replies, now I'm really glad I asked. Ali, I'm already reading your book and it's pretty good. I've also ordered The D Programming language, so that should be a big help. The only thing that remains is patience I guess. I won't give up on D so easily this time. Thanks a lot, really
Re: Emplace using private constructor
Nevermind, problem was not worth the question. I just copied code from Phobos std.conv.emplace and placed it directly in my code, it works since it is in the same module as the private constructor.
Re: Emplace using private constructor
tldr; I had the crazy idea of mixing-in a specialization of emplace but failed probably because mixin does not respect template constraints. On 06/07/2013 06:50 AM, develop32 wrote: > Nevermind, problem was not worth the question. I just copied code from > Phobos std.conv.emplace and placed it directly in my code, it works > since it is in the same module as the private constructor. But it is too heavy-handed. Your problem exposes a real weakness. Other library code will make assumptions like emplace does below and they will fail if the constructor is not accessible. From std.conv.emplace: // Call the ctor if any static if (is(typeof(result.__ctor(args { // T defines a genuine constructor accepting args // Go the classic route: write .init first, then call ctor result.__ctor(args); } I tried making your code better but not copying emplace's implementation: module display; import std.conv; class Display { private: const string name; this(string name) { this.name = name; } public: static Display emplace(Args...)(void[] chunk, auto ref Args args) { return std.conv.emplace!(Display)(chunk, args); } } Here is a test program: import display; void main() { enum roomNeeded = __traits(classInstanceSize, Display); ubyte[roomNeeded] buffer; auto d = Display.emplace(buffer, "hello"); } But I failed with the same error: Error: static assert "Don't know how to initialize an object of type Display with arguments (string)" Then I thought about mixing in the template but that did not work either: class Display { // ... static Display emplace(Args...)(void[] chunk, auto ref Args args) { mixin std.conv.emplace!(Display, string); } } The error message indicated that mixin was picking the wrong specialization, because it had a template constraint for 'struct': T* emplace(T, Args...)(T* chunk, auto ref Args args) if (is(T == struct)) { // ... } If it picked the one that matched is(T == class) then we would have achieved our goal without copy-pasting. Still, if it worked, it also feels hacky because we would be mixing-in a specialization right inside our function and hope that it would somehow work in our environment. For example, the specialization of emplace has a return statement: return result; What if my function should not return? I guess then we would mix-in inside a wrapper function, call that function, and ignore the return value. I have a feeling that bearophile already has a bug report about all of this but I haven't checked yet. :p Not the same, but it look like it is related to this bug: http://d.puremagic.com/issues/show_bug.cgi?id=9235 Ali
Question on class templates
interface Identity(V, K) { } class X(V, K) : Identity!(V, K) { private K k; public this(K k) { this.k = k; } } void main() { auto x = new X!(X, double)(6.0); } Hi - I have the code above, but the line in main() gives the following compile error: Error: template instance X!(X, double) does not match template declaration X(V, K) If I change the template parameter X to something else, like string, it compiles fine. But I want the Identity interface to know the type of the implementing class. Is that possible? Thanks, Eric
Re: Question on class templates
On Friday, 7 June 2013 at 17:52:48 UTC, Eric wrote: interface Identity(V, K) { } class X(V, K) : Identity!(V, K) { private K k; public this(K k) { this.k = k; } } void main() { auto x = new X!(X, double)(6.0); } Hi - I have the code above, but the line in main() gives the following compile error: Error: template instance X!(X, double) does not match template declaration X(V, K) If I change the template parameter X to something else, like string, it compiles fine. But I want the Identity interface to know the type of the implementing class. Is that possible? Thanks, Eric class X(K) : Identity!(X, K) auto x = new X!(double)(6.0);
Re: Learning D
On Friday, 7 June 2013 at 13:45:50 UTC, Daemon wrote: The only thing that remains is patience I guess. That, buy Andrei's book and ask questions here. :) http://www.amazon.co.uk/The-Programming-Language-Andrei-Alexandrescu/dp/0321635361
Re: Question on class templates
On Friday, 7 June 2013 at 18:06:26 UTC, anonymous wrote: On Friday, 7 June 2013 at 17:52:48 UTC, Eric wrote: interface Identity(V, K) { } class X(V, K) : Identity!(V, K) { private K k; public this(K k) { this.k = k; } } void main() { auto x = new X!(X, double)(6.0); } Hi - I have the code above, but the line in main() gives the following compile error: Error: template instance X!(X, double) does not match template declaration X(V, K) If I change the template parameter X to something else, like string, it compiles fine. But I want the Identity interface to know the type of the implementing class. Is that possible? Thanks, Eric class X(K) : Identity!(X, K) auto x = new X!(double)(6.0); Oh... Duh... Thanks.
Strange output
The following program is supposed to print out only numbers that are less than 5, yet the number 63 gets printed. module main; import std.stdio; import std.conv; int main(string[] argv) { auto de = find!(delegate(a) { return a < 5; })([10, 11, 15, 16, 27, 20, 2, -4, -17, 8, 64, 6]); foreach (int b; de[0 .. $]) { writeln(b); } readln(); return 0; } T[] find(alias pred, T)(T[] input) if (is(typeof(pred(input[0])) == bool)) { for (; input.length > 0; input = input[1 .. $]) { if (pred(input[0])) { break; } } return input; } I realize it's extremely improbable that I've discovered a bug, so what exactly could I be doing wrong? Why is the output: 2 -4 -17 8 63 6 I'm probably missing something obvious. If the input is just [63], then nothing gets printed out.
Re: Strange output
auto de = find!(delegate(a) { return a < 5; })([10, 11, 15, 16, 27, 20, 2, -4, -17, 8, 64, 6]); Just a clarification, it prints out 64 with the input above, I changed it later just to test it and forgot to update the rest.
std.traits functions causing the compiler to crash
mport std.traits; interface Xidentity(V, K) { static if (hasMember!(V, "k")) static assert(0); public int getInstanceCount(); } class X(K) : Xidentity!(X!(K), K) { private K k; X newInstance(K k) { return(new X(k)); } private this(K k) { this.k = k; } public int getInstanceCount() { return(5); } } void main() { auto x = new X!(double)(6.0); } If I compile the above code, the static if statement in the interface declaration causes the compiler to segfault without any other information. gdb give the following stacktrace: Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 0xf75106c0 (LWP 30889)] 0x08170d26 in TraitsExp::semantic () Current language: auto; currently asm (gdb) backtrace #0 0x08170d26 in TraitsExp::semantic () #1 0x0809a51a in Expression::ctfeSemantic () #2 0x081446da in TemplateInstance::semanticTiargs () #3 0x08145035 in TemplateInstance::semanticTiargs () #4 0x08148f04 in TemplateInstance::semantic () #5 0x08149470 in TemplateInstance::semantic () #6 0x0809feae in ScopeExp::semantic () #7 0x0809fcfd in BinExp::semantic () #8 0x080ac66e in BinExp::semanticp () #9 0x080ac7bc in EqualExp::semantic () #10 0x080aa75e in OrOrExp::semantic () #11 0x0809a51a in Expression::ctfeSemantic () #12 0x08077bee in VarDeclaration::semantic () #13 0x0804ccc5 in StaticIfDeclaration::semantic () #14 0x0813fc49 in TemplateInstance::expandMembers () #15 0x0813fc8c in TemplateInstance::tryExpandMembers () #16 0x08148ce0 in TemplateInstance::semantic () #17 0x08149470 in TemplateInstance::semantic () #18 0x0809feae in ScopeExp::semantic () #19 0x0809a51a in Expression::ctfeSemantic () #20 0x080713c4 in StaticIfCondition::include () #21 0x0804b443 in ConditionalDeclaration::include () #22 0x0804cd40 in StaticIfDeclaration::include () #23 0x0804cc95 in StaticIfDeclaration::semantic () #24 0x0806a0f0 in InterfaceDeclaration::semantic () #25 0x0813fc49 in TemplateInstance::expandMembers () #26 0x0813fc8c in TemplateInstance::tryExpandMembers () #27 0x08148ce0 in TemplateInstance::semantic () #28 0x08149470 in TemplateInstance::semantic () #29 0x080fcd13 in TypeInstance::resolve () #30 0x080f9a4d in TypeInstance::semantic () #31 0x080685b0 in ClassDeclaration::semantic () #32 0x0813fc49 in TemplateInstance::expandMembers () #33 0x0813fc8c in TemplateInstance::tryExpandMembers () #34 0x08148ce0 in TemplateInstance::semantic () #35 0x08149470 in TemplateInstance::semantic () #36 0x080fcd13 in TypeInstance::resolve () #37 0x080f9a4d in TypeInstance::semantic () #38 0x080af314 in NewExp::semantic () #39 0x080deaf4 in ExpInitializer::inferType () #40 0x08077560 in VarDeclaration::semantic () #41 0x080a3ea1 in DeclarationExp::semantic () #42 0x0812cc41 in ExpStatement::semantic () #43 0x08138c91 in CompoundStatement::semantic () #44 0x080c0cf5 in FuncDeclaration::semantic3 () #45 0x080f16bb in Module::semantic3 () #46 0x080edf5c in tryMain () #47 0x080efab2 in main () I'm using compiler version v2.063-devel-53aa503. Is this a known problem, or is there a work-around? Thanks, Eric
Re: Emplace using private constructor
On Friday, 7 June 2013 at 16:14:25 UTC, Ali Çehreli wrote: But it is too heavy-handed. Your problem exposes a real weakness. Other... Well, its not *that* heavy. // Inside Display class. auto display = alloc!Display; display.__ctor(name); Where alloc(T) is a bigger part of the original emplace code and is widely used. But generally, yeah. It would be nice to fix mixins.
Re: Strange output
On Friday, 7 June 2013 at 19:10:54 UTC, Daemon wrote: The following program is supposed to print out only numbers that are less than 5, yet the number 63 gets printed. module main; import std.stdio; import std.conv; int main(string[] argv) { auto de = find!(delegate(a) { return a < 5; })([10, 11, 15, 16, 27, 20, 2, -4, -17, 8, 64, 6]); foreach (int b; de[0 .. $]) { writeln(b); } readln(); return 0; } T[] find(alias pred, T)(T[] input) if (is(typeof(pred(input[0])) == bool)) { for (; input.length > 0; input = input[1 .. $]) { if (pred(input[0])) { break; } } return input; } I realize it's extremely improbable that I've discovered a bug, so what exactly could I be doing wrong? Why is the output: 2 -4 -17 8 63 6 I'm probably missing something obvious. If the input is just [63], then nothing gets printed out. It looks like your find function just stops at the first item that is less than five (which is two) and returns a range consisting of all the following items. If you'll look closer, your output is just all items after and including 2.
Re: Strange output
On Friday, 7 June 2013 at 19:47:39 UTC, develop32 wrote: On Friday, 7 June 2013 at 19:10:54 UTC, Daemon wrote: The following program is supposed to print out only numbers that are less than 5, yet the number 63 gets printed. module main; import std.stdio; import std.conv; int main(string[] argv) { auto de = find!(delegate(a) { return a < 5; })([10, 11, 15, 16, 27, 20, 2, -4, -17, 8, 64, 6]); foreach (int b; de[0 .. $]) { writeln(b); } readln(); return 0; } T[] find(alias pred, T)(T[] input) if (is(typeof(pred(input[0])) == bool)) { for (; input.length > 0; input = input[1 .. $]) { if (pred(input[0])) { break; } } return input; } I realize it's extremely improbable that I've discovered a bug, so what exactly could I be doing wrong? Why is the output: 2 -4 -17 8 63 6 I'm probably missing something obvious. If the input is just [63], then nothing gets printed out. It looks like your find function just stops at the first item that is less than five (which is two) and returns a range consisting of all the following items. If you'll look closer, your output is just all items after and including 2. I totally misunderstood the for loop before, I feel ashamed. Thanks a lot, haha
Re: Strange output
On Fri, Jun 07, 2013 at 09:10:53PM +0200, Daemon wrote: > The following program is supposed to print out only numbers that are > less than 5, yet the number 63 gets printed. On Fri, Jun 07, 2013 at 09:14:00PM +0200, Daemon wrote: > >auto de = find!(delegate(a) { return a < 5; })([10, 11, 15, 16, > >27, 20, 2, -4, -17, 8, 64, 6]); > > Just a clarification, it prints out 64 with the input above, I > changed it later just to test it and forgot to update the rest. This should not be surprising. Please see my comments below: > module main; > > import std.stdio; > import std.conv; > > int main(string[] argv) > { > auto de = find!(delegate(a) { return a < 5; })([10, 11, 15, 16, 27, > 20, 2, -4, -17, 8, 64, 6]); > OK, so here 'de' is assigned whatever is returned by 'find', and the following loop prints out its contents. The question then is, what does find() return? > foreach (int b; de[0 .. $]) > { > writeln(b); > } > > readln(); > > return 0; > } > > T[] find(alias pred, T)(T[] input) > if (is(typeof(pred(input[0])) == bool)) > { > for (; input.length > 0; input = input[1 .. $]) OK, so what the above is saying, is that you want to loop over the input array, and reduce it by one element each time (i.e. slice from 1 to the end). So let's look at the input main() is giving it: [10, 11, 15, ...]. So the first time round, we're looking at the entire array, which starts with the element 10. > { > if (pred(input[0])) > { > break; > } So here, 'pred' is passed the value of input[0]. The first time round, input[0] is 10, so pred returns false: because 10 < 5 is false. So the loop runs again, and the next time round, the array has been shortened to [11, 15, ...]. So now, input[0] is 11, and again, 11 < 5 is false, so the loop keeps running. Now what happens after the next few iterations, when you get to '2'? At that point, input looks like this: [2, -4, -17, 8, 64, 6]. So input[0] is 2, and since 2 < 5, pred(input[0]) returns true. So the next line says 'break', which means "stop running the loop". Remember that at this point, input is [2, -4, -17, 8, 64, 6]. And then finally: > } > return input; > } This says, return input (which is currently [2, -4, -17, 8, 64, 6]). So going back to main(), we see that 'de' must be [2, -4, -17, 8, 64, 6]. And indeed, that's the output you get. So the program isn't doing anything wrong. It's just that what you wrote isn't quite what you wanted. :) It sounds like you wanted to *filter* the array for elements less than 5. So what you need to do is, once you find an element that's 5 or greater, you need to skip over it. However, a D array is a *contiguous* list of elements; there's no such thing as a skipped element in an array. So you can't just return a slice of the original array -- a slice is also a contiguous block of elements; while it *can* give you a "sub-array" view of the original array, it cannot start somewhere, skip over some elements, and then continue. The easiest solution is to construct a new array that doesn't have the offending elements, maybe something along these lines: T[] find(alias pred, T)(T[] input) if (is(typeof(pred(input[0])) == bool)) { // Note this line: we're creating a new array containing only // the elements we want. T[] result; for (; input.length > 0; input = input[1 .. $]) { if (pred(input[0])) { // Found an element that satisfies our // predicate, so append that to the end of our // results. result ~= input[0]; // (No break here: we want to look at every // element in the input.) } } // N.B.: instead of returning input, which is a slice of the // original array, we return the new array we've constructed // that only has the elements we want. return result; } Hope this helps! T -- Freedom of speech: the whole world has no right *not* to hear my spouting off!
Re: std.traits functions causing the compiler to crash
Eric: Is this a known problem, or is there a work-around? This is your code reduced a little: import std.traits: hasMember; interface Xidentity(V, K) if (!hasMember!(V, "x")) { } class Foo(K): Xidentity!(Foo!K, K) { K x; } void main() { new Foo!double; } I think it contains a loop at the level of types. In theory the compiler should catch them and give a nice error message. You probably want to use the template constraint syntax, as I have used. In D return is not a function, so don't use the ( ). Bye, bearophile
-profile
Compiling with -profile and without -release Gives the following error (not exactly but the best I can recall) balancedParens is not nothrow safe pure With -release and -profile all is fine. Builds fine without -profile. Simple question is why?
opEquals does not work?
Did I miss something? I expected this output opEquals: 23 == 23 Equal 1 opEquals: 23 == 23 Equal 2 by the following code, but I only get this: opEquals: 23 == 23 Equal 2 Code: [code] import std.stdio; class A { public: int id; this(int id) { this.id = id; } bool opEquals(const A a) const { writefln("opEquals: %d == %d", this.id, a.id); return a.id == this.id; } } void main() { A a1 = new A(23); A a2 = new A(23); if (a1 == a2) { writeln("Equal 1"); } if (a1.opEquals(a2)) { writeln("Equal 2"); } } [/code]
Re: opEquals does not work?
I got it. I must use Object instead of A... How ridiculous. I thought this was already fixed...
Re: -profile
Anthony Goins: Simple question is why? Looks like a little compiler bug. Please create a minimal example that shows the problem. If it's a real problem then it's for Bugzilla. Bye, bearophile
Re: opEquals does not work?
On Friday, 7 June 2013 at 20:51:13 UTC, Namespace wrote: I got it. I must use Object instead of A... How ridiculous. I thought this was already fixed... The class opEquals is quite like .equals in Java. You need to match the signature of Object, which is implicitly the base class of all classes. I think I recommend something like this. override bool opEquals(Object o) const { auto other = cast(A) o; // It's probably easy to miss out !is null here, which matters. return other !is null && this.id == other.id; }
Re: opEquals does not work?
On Friday, 7 June 2013 at 20:58:40 UTC, w0rp wrote: On Friday, 7 June 2013 at 20:51:13 UTC, Namespace wrote: I got it. I must use Object instead of A... How ridiculous. I thought this was already fixed... The class opEquals is quite like .equals in Java. You need to match the signature of Object, which is implicitly the base class of all classes. I think I recommend something like this. override bool opEquals(Object o) const { auto other = cast(A) o; // It's probably easy to miss out !is null here, which matters. return other !is null && this.id == other.id; } Yes, I remember. As I heard it the first time I thought it's because of the limited compiler and that it will fixed some day.
Re: opEquals does not work?
On Friday, 7 June 2013 at 21:02:15 UTC, Namespace wrote: Yes, I remember. As I heard it the first time I thought it's because of the limited compiler and that it will fixed some day. opEquals for classes is interesting because you actually do need to write 'Object' there because of type polymorphism.
Re: opEquals does not work?
On Friday, June 07, 2013 22:51:12 Namespace wrote: > I got it. I must use Object instead of A... How ridiculous. I > thought this was already fixed... I have an open pull request as part of the move to getting rid of opEquals, opCmp, toHash, and toString from Object, and it would make it so that you could use something other than Object: https://github.com/D-Programming-Language/druntime/pull/459 However, due to D's overload rules, you will _always_ be forced to have an opEquals which takes the most base class that you can compare. But you should be able to do something like overload it with the derived class type and then alias the base classes' opEquals into the scope of the derived class. - Jonathan M Davis
Re: -profile
Anthony Goins: Simple question is why? I am compiling this code with -profile, and I don't see errors: import std.string: balancedParens; void main() { assert(balancedParens("[[]]", '[', ']')); } Bye, bearophile
Re: opEquals does not work?
On Friday, 7 June 2013 at 21:18:12 UTC, Jonathan M Davis wrote: I have an open pull request as part of the move to getting rid of opEquals, opCmp, toHash, and toString from Object, and it would make it so that you could use something other than Object Oh, that's cool. I didn't know about that.
Re: opEquals does not work?
Jonathan M Davis: However, due to D's overload rules, you will _always_ be forced to have an opEquals which takes the most base class that you can compare. http://d.puremagic.com/issues/show_bug.cgi?id=10292 Bye, bearophile
Re: opEquals does not work?
On Friday, 7 June 2013 at 21:42:36 UTC, bearophile wrote: Jonathan M Davis: However, due to D's overload rules, you will _always_ be forced to have an opEquals which takes the most base class that you can compare. http://d.puremagic.com/issues/show_bug.cgi?id=10292 Bye, bearophile Thank you.
Re: opEquals does not work?
On 06/07/2013 02:18 PM, Jonathan M Davis wrote: > I have an open pull request as part of the move to getting rid of opEquals, > opCmp, toHash, and toString from Object, and it would make it so that you > could use something other than Object: I hope it supports delegate-taking toString overload for classes.[1] Ali [1] As a reminder to others who don't know or keep forgetting like me, :) toString has a more efficient toString overload. Unfortunately, it works only with structs at this point. I am way off-topic now but here is an example: import std.stdio; import std.format; struct Point { int x; int y; void toString(void delegate(const(char)[]) sink) const { formattedWrite(sink, "(%s,%s)", x, y); } } struct Color { ubyte r; ubyte g; ubyte b; void toString(void delegate(const(char)[]) sink) const { formattedWrite(sink, "RGB:%s,%s,%s", r, g, b); } } struct ColoredPoint { Color color; Point point; void toString(void delegate(const(char)[]) sink) const { formattedWrite(sink, "{%s;%s}", color, point); } } struct Poligon { ColoredPoint[] points; this(ColoredPoint[] points) { this.points = points; } void toString(void delegate(const(char)[]) sink) const { formattedWrite(sink, "%s", points); } } void main() { auto poligon = Poligon( [ ColoredPoint(Color(10, 10, 10), Point(1, 1)), ColoredPoint(Color(20, 20, 20), Point(2, 2)), ColoredPoint(Color(30, 30, 30), Point(3, 3)) ]); writeln(poligon); } The advantage of this method over the more-common toString() overload (the one that returns string) is that although there are still a total of 10 calls made to various toString() functions, those calls collectively produce a single string, not 10. Ali
Re: Strange output
On Friday, 7 June 2013 at 19:10:54 UTC, Daemon wrote: The following program is supposed to print out only numbers that are less than 5, yet the number 63 gets printed. You're probably just playing around, but FYI the function is http://dlang.org/phobos/std_algorithm.html#filter While you've created the same find already in std.algorithm.
Re: -profile
On Friday, 7 June 2013 at 21:39:26 UTC, bearophile wrote: Anthony Goins: Simple question is why? I am compiling this code with -profile, and I don't see errors: import std.string: balancedParens; void main() { assert(balancedParens("[[]]", '[', ']')); } Bye, bearophile okay found it module profiletest; import std.path; void main() { assert(globMatch("foo.bar", "*")); } dmd -profile profiletest.d /usr/include/dmd/phobos/std/path.d(2187): Error: balancedParens is not nothrow /usr/include/dmd/phobos/std/path.d(2188): Error: balancedParens is not nothrow globMatch is @safe pure nothrow balancedParens is not nothrow -release ignores contracts, right?
Re: -profile
On Friday, 7 June 2013 at 23:42:58 UTC, Anthony Goins wrote: On Friday, 7 June 2013 at 21:39:26 UTC, bearophile wrote: Anthony Goins: Simple question is why? I am compiling this code with -profile, and I don't see errors: import std.string: balancedParens; void main() { assert(balancedParens("[[]]", '[', ']')); } Bye, bearophile okay found it module profiletest; import std.path; void main() { assert(globMatch("foo.bar", "*")); } dmd -profile profiletest.d /usr/include/dmd/phobos/std/path.d(2187): Error: balancedParens is not nothrow /usr/include/dmd/phobos/std/path.d(2188): Error: balancedParens is not nothrow globMatch is @safe pure nothrow balancedParens is not nothrow -release ignores contracts, right? oops forgot to say balancedParens is called from the 'in' contract of globMatch. Is this even worth a bug report?
Re: -profile
Anthony Goins: Is this even worth a bug report? Yes, it's worth a bug report in Bugzilla, it's a (small) Phobos Bug. I confirmed its presence. Bye, bearophile
Re: opEquals does not work?
On Friday, June 07, 2013 14:53:44 Ali Çehreli wrote: > On 06/07/2013 02:18 PM, Jonathan M Davis wrote: > > I have an open pull request as part of the move to getting rid of > > opEquals, > > > opCmp, toHash, and toString from Object, and it would make it so that you > > > could use something other than Object: > I hope it supports delegate-taking toString overload for classes.[1] It should be perfectly possible to declare such an overload now. It just won't work when used through Object. If it doesn't work, then I expect that that's a bug in formattedWrite and friends. As far as overriding goes though, that'll depend on what the base classes of a class have declared. If they all declare toString without a delegate, then that's what you'd have to override to use toString using references of their type, whereas if they use the toString which takes a delegate, then that's what you'd have to override. But I don't see any reason that you can't have both just so long as the type of the reference that you're using has it. Howver, I supposed that a potential problem with formattedWrite and friends is that if you have two toString methods, it has to pick which one to use, and right now, it probably just picks the one from Object. Better behavior would be to us the delegate one if it's there and fall back to the non-delegate version if it's not. Long term though, formattedWrite et al will probably have the potential of not working at all with a class if we fully remove it from Object ike we intend to, since then there's no guarantee that a class or any of its base classes have even declared any toString. In any case, if toString with a delegate doesn't work with formattedWrite et al, then we need an enhancement request for that to be fixed. - Jonathan M Davis
Derelict linking (Debian + derelict + dmd 2.062)
Hi! I am trying to add SDL support to my project. libderelict-dev installed into my Debian and I am just added "import derelict.sdl2.sdl;". And caused: dmd -I/usr/include/dmd/ -unittest -g -debug -debug=osmpbf -L-lDerelictUtil -L-lDerelictSDL2 -L-ldl -ofmain libosmpbfd.a math/rtree2d.d math/geometry.d math/graph.d pb_encoding.d main.d /usr/lib/x86_64-linux-gnu/libDerelictSDL2.a(sdl_1_698.o):(.data+0x60): undefined reference to `_D8derelict4util6loader15SharedLibLoader7__ClassZ' /usr/lib/x86_64-linux-gnu/libDerelictSDL2.a(sdl_1_698.o):(.rodata+0x41f0): undefined reference to `_D8derelict4util6loader15SharedLibLoader4loadMFZv' /usr/lib/x86_64-linux-gnu/libDerelictSDL2.a(sdl_1_698.o):(.rodata+0x41f8): undefined reference to `_D8derelict4util6loader15SharedLibLoader4loadMFAyaZv' /usr/lib/x86_64-linux-gnu/libDerelictSDL2.a(sdl_1_698.o):(.rodata+0x4200): undefined reference to `_D8derelict4util6loader15SharedLibLoader4loadMFAAyaZv' /usr/lib/x86_64-linux-gnu/libDerelictSDL2.a(sdl_1_698.o):(.rodata+0x4208): undefined reference to `_D8derelict4util6loader15SharedLibLoader6unloadMFZv' /usr/lib/x86_64-linux-gnu/libDerelictSDL2.a(sdl_1_698.o):(.rodata+0x4210): undefined reference to `_D8derelict4util6loader15SharedLibLoader8isLoadedMFNdZb' /usr/lib/x86_64-linux-gnu/libDerelictSDL2.a(sdl_1_698.o):(.rodata+0x4220): undefined reference to `_D8derelict4util6loader15SharedLibLoader10loadSymbolMFAyaZPv' /usr/lib/x86_64-linux-gnu/libDerelictSDL2.a(sdl_1_698.o):(.rodata+0x4228): undefined reference to `_D8derelict4util6loader15SharedLibLoader3libMFNdZS8derelict4util9sharedlib9SharedLib' /usr/lib/x86_64-linux-gnu/libDerelictSDL2.a(sdl_1_698.o):(.rodata+0x4230): undefined reference to `_D8derelict4util6loader15SharedLibLoader8bindFuncMFPPvAyabZv' /usr/lib/x86_64-linux-gnu/libDerelictSDL2.a(sdl_1_698.o): In function `_D8derelict4sdl23sdl18DerelictSDL2Loader6__ctorMFZC8derelict4sdl23sdl18DerelictSDL2Loader': ../derelict/sdl2/sdl.d:(.text._D8derelict4sdl23sdl18DerelictSDL2Loader6__ctorMFZC8derelict4sdl23sdl18DerelictSDL2Loader+0x1b): undefined reference to `_D8derelict4util6loader15SharedLibLoader6__ctorMFAyaZC8derelict4util6loader15SharedLibLoader' collect2: error: ld returned 1 exit status --- errorlevel 1 make: *** [main] Error 1 What is it? Can anyone help?
Re: -profile
On Friday, 7 June 2013 at 23:57:37 UTC, bearophile wrote: Anthony Goins: Is this even worth a bug report? Yes, it's worth a bug report in Bugzilla, it's a (small) Phobos Bug. I confirmed its presence. Bye, bearophile Thank you for all your help. Not just here but throughout the forums. One more question though... What is the error here :) 1. dmd profiletest.d should fail because balancedParens is not nothrow even though it is called from a contract. 2. dmd -profile profiletest.d should succeed because nothrow, @safe, pure don't apply to contracts
Re: -profile
Anthony Goins: Is this even worth a bug report? http://d.puremagic.com/issues/show_bug.cgi?id=10295 Bye, bearophile
Re: -profile
Anthony Goins: What is the error here :) 1. dmd profiletest.d should fail because balancedParens is not nothrow even though it is called from a contract. 2. dmd -profile profiletest.d should succeed because nothrow, @safe, pure don't apply to contracts I think -profile and pre-conditions should not be correlated. That's why I have reported this bug as a dmd bug instead just of a Phobos bug. I am not sure what's the right answer. I think the right answer is 1. Bye, bearophile
Re: std.traits functions causing the compiler to crash
O import std.traits: hasMember; interface Xidentity(V, K) if (!hasMember!(V, "x")) { } class Foo(K): Xidentity!(Foo!K, K) { K x; } void main() { new Foo!double; } I think it contains a loop at the level of types. In theory the compiler should catch them and give a nice error message. You probably want to use the template constraint syntax, as I have used. Yes, the template constraint is much better. However, the compiler still crashes, even with the new code: import std.traits: hasMember; interface Identity(V, K) if (!hasMember!(V, "k")) { } class Foo(K): Identity!(Foo!K, K) { K k; } void main() { new Foo!double; } (dmd7) mrbig:~/tp/d_test2/dlib>dmd Test.d Segmentation fault (core dumped) In D return is not a function, so don't use the ( ). Yeah, I know. return returns an expression, and parenthesis are legal expression syntax:) -Eric
Re: std.traits functions causing the compiler to crash
Eric: Yes, the template constraint is much better. However, the compiler still crashes, even with the new code: Because there's a type definition loop, regardless. Using a constraint doesn't change that situation. Bye, bearophile
Re: Conditional compilation
On Friday, 7 June 2013 at 12:20:23 UTC, finalpatch wrote: string mixins and template mixins don't work either. On Friday, 7 June 2013 at 12:14:45 UTC, finalpatch wrote: Hi folks, I need to apply different calling conventions to the same interfaces when compiling for different platform. It's something like this: OSX: interface InterfaceA : IUnknown { extern(C): ... } Windows: interface InterfaceA : IUnknown { ... } I have to add extern(C) on OSX because apparently when the compiler sees IUnknown it automatically assumes the calling convention is extern(Windows) and in order to maintain compatibility with existing system I have to explicitly declare them as extern(C). Now I have several dozens of interfaces like the above. I don't want to repeat them for OSX and Windows because the interface definitions are identical except the extern(C) line. I have tried using version() like this: interface InterfaceA : IUnknown { version(OSX) { extern(C): } ...methohds. } but it doesn't work because version limits the scope of the extern(C). static if has the same problem. In C/C++ this is really easy, I can simply define a macro which expands to extern(C) on OSX and nothing on windows. Is there any way to achieve this in D without repeating the interface definitions? string mixin will work import std.stdio; enum :string { //define relevant functions in this string x1 = `void testfunc(string str) { writeln(str); }` } version(X) { extern(C) mixin(x1); string str2 = "c version"; } version(Y) { extern(Windows) mixin(x1); string str2 = "windows version"; } void main() { testfunc(str2); } Yes it's ... well ... not very ... umm But it works :) extern(system) MIGHT be a better option.
Re: Derelict linking (Debian + derelict + dmd 2.062)
On Saturday, 8 June 2013 at 00:27:36 UTC, mimi wrote: Hi! I am trying to add SDL support to my project. libderelict-dev installed into my Debian and I am just added "import derelict.sdl2.sdl;". And caused: dmd -I/usr/include/dmd/ -unittest -g -debug -debug=osmpbf -L-lDerelictUtil -L-lDerelictSDL2 -L-ldl -ofmain libosmpbfd.a Looks like a problem with the order in which the libraries are specified on the command line. Swap them like so: "-L-lDerelictSDL2 -L-lDerelictUtil" and see if that does it for you.
Re: Derelict linking (Debian + derelict + dmd 2.062)
Thanks! It worked! On Saturday, 8 June 2013 at 03:44:22 UTC, Mike Parker wrote: On Saturday, 8 June 2013 at 00:27:36 UTC, mimi wrote: Hi! I am trying to add SDL support to my project. libderelict-dev installed into my Debian and I am just added "import derelict.sdl2.sdl;". And caused: dmd -I/usr/include/dmd/ -unittest -g -debug -debug=osmpbf -L-lDerelictUtil -L-lDerelictSDL2 -L-ldl -ofmain libosmpbfd.a Looks like a problem with the order in which the libraries are specified on the command line. Swap them like so: "-L-lDerelictSDL2 -L-lDerelictUtil" and see if that does it for you.
Re: std.traits functions causing the compiler to crash
On Saturday, 8 June 2013 at 02:32:57 UTC, bearophile wrote: Eric: Yes, the template constraint is much better. However, the compiler still crashes, even with the new code: Because there's a type definition loop, regardless. Using a constraint doesn't change that situation. Bye, bearophile How is there a type definition loop? I'm just trying to constrain the interface. At a minimum this should be a compiler bug, but I would hope that dimple constraints would work. -Eric
can we detect at compile time module ctor/dtor cycles ?
Why can't we detect at compile time module ctor/dtor cycles (instead of runtime) ? See example below. It should be easy to detect the chain at CT: algo: build graph from import dependencies a=>b if module a imports module b. mark as red the modules that have a ctor collapse each non-red node into its parent (and update parent's edges) detect cycles (eg BFS) (same with dtor) a1: import a2; void main(){} static this(){} a2: import a3; static this(){} a3: import a1; rdmd --force --build-only -oftest a1 #works ./test #error: object.Exception@src/rt/minfo.d(243): Aborting: Cycle detected between modules with ctors/dtors: a1 -> a2 -> a3 -> a1
Re: can we detect at compile time module ctor/dtor cycles ?
On Friday, June 07, 2013 23:23:25 Timothee Cour wrote: > Why can't we detect at compile time module ctor/dtor cycles (instead of > runtime) ? At minimum, separate compilation stops it. A .di file isn't likely to have them even if its corresponding .d file did. IIRC, there were other reasons as well, but I don't remember them at the moment. - Jonathan M Davis