Re: DlangIDE Themes
On Thursday, 12 May 2016 at 03:01:02 UTC, thedeemon wrote: On Wednesday, 11 May 2016 at 12:55:13 UTC, Chris wrote: Is there a way I can add my own themes? I've created a theme file and added it to views/resources.list However, it doesn't show up. "Default" and "Dark" seem to be hardwired somewhere in the source code. Indeed they are, just grep for "ide_theme_dark" and you'll find those two places (settings.d, idesettings.d). They shouldn't be hardwired. Best would be to load them dynamically with their respective names encoded in the xml file. In this way people could add their own themes as they see fit. I wouldn't mind creating themes and adding them to DlangIDE as a humble contribution.
.array changes the order
I came across the issue where using .array after .joiner caused the changes to the output. The program is at https://dpaste.dzfl.pl/0885ba2eddb4 . I tried to debug through the output but I couldn't get the exact issue. It will be helpful if someone confirms this as a bug.
Re: DlangIDE Themes
On Thursday, 12 May 2016 at 09:17:24 UTC, Chris wrote: They shouldn't be hardwired. Best would be to load them dynamically with their respective names encoded in the xml file. In this way people could add their own themes as they see fit. I wouldn't mind creating themes and adding them to DlangIDE as a humble contribution. Don't forget that contents of all those files in resources.list is also "hardwired" into the executable, so there's not much difference between mentioning something in such list file and in the source code. Of course, dynamic loading would be a nice thing to do, in addition to what there is now.
Re: DlangIDE Themes
On Thursday, 12 May 2016 at 09:51:18 UTC, thedeemon wrote: On Thursday, 12 May 2016 at 09:17:24 UTC, Chris wrote: They shouldn't be hardwired. Best would be to load them dynamically with their respective names encoded in the xml file. In this way people could add their own themes as they see fit. I wouldn't mind creating themes and adding them to DlangIDE as a humble contribution. Don't forget that contents of all those files in resources.list is also "hardwired" into the executable, so there's not much difference between mentioning something in such list file and in the source code. Of course, dynamic loading would be a nice thing to do, in addition to what there is now. Sure, but changing `resources.list` is trivial and can be added to the docs like so "Add the path to your theme file to `resources.list` and restart DlangIDE." It has to be hardwired somewhere, but it shouldn't be the themes. Other editors/IDE's allow you to load your own themes. This is important, because apart from aesthetics, some people might find certain themes easier on the eye than others, e.g. color blind people or people with some sort of visual impairment.
Re: .array changes the order
On Thursday, 12 May 2016 at 09:44:39 UTC, xtreak wrote: I came across the issue where using .array after .joiner caused the changes to the output. The program is at https://dpaste.dzfl.pl/0885ba2eddb4 . I tried to debug through the output but I couldn't get the exact issue. It will be helpful if someone confirms this as a bug. It's not a bug per se, just probably documentation being not clear enough. Essentially it's the same issue as with File.byLine: a range that mutates its state, so it's ok to consume lazily but if you just store references (as array() does) you get references to the same mutated value as result. Quick fix: r.chunks(2).map!permutations.joiner.map!array.array.writeln; i.e. copy each permutation to separate array before it's gone.
Re: .array changes the order
On Thursday, 12 May 2016 at 10:02:46 UTC, thedeemon wrote: On Thursday, 12 May 2016 at 09:44:39 UTC, xtreak wrote: I came across the issue where using .array after .joiner caused the changes to the output. The program is at https://dpaste.dzfl.pl/0885ba2eddb4 . I tried to debug through the output but I couldn't get the exact issue. It will be helpful if someone confirms this as a bug. It's not a bug per se, just probably documentation being not clear enough. Essentially it's the same issue as with File.byLine: a range that mutates its state, so it's ok to consume lazily but if you just store references (as array() does) you get references to the same mutated value as result. Quick fix: r.chunks(2).map!permutations.joiner.map!array.array.writeln; i.e. copy each permutation to separate array before it's gone. Thanks a lot. Can you kindly elaborate a little more on File.byLine with an example of the scenario so that I don't get bitten by it. File.byLine.array works as expected for me. A little more explanation on the permutations will also be helpful since joiner.map!array converts the subranges to arrays, so does joiner work by mutating state if so how does it do.
Re: D equivalent of C++ bind ?
On Tuesday, 10 May 2016 at 09:39:53 UTC, chmike wrote: Is there an equivalent in D of the C++11 std.bind template class [http://en.cppreference.com/w/cpp/utility/functional/bind] ? Here is a blog post showing different examples of its use https://oopscenities.net/2012/02/24/c11-stdfunction-and-stdbind/ A possible use case is for a callback function/delegate with the expected signature bool cb(int error). I would like to pass a function bool myCb(int error, ref int myArg) instead with the variable myArg being given as predefined argument. Here is an example. int count = 0; bool myCb(int error, ref int myArg) { if (myArg >= 6) return false; writeln(++myArg); return true; } void async_task(void function(int error) cb) { . . . while cb(0) . . . } void main() { . . . async_task( ??? myCb ??? count ??? ); . . . } In C++ we would write async_task(std::bind(myCb, std::placeholders::_1, count)); I write one, bind functon to a delegate. In here: https://github.com/putao-dev/collie/blob/master/source/collie/utils/functional.d this is the code: auto bind(T,Args...)(auto ref T fun,Args args) if (isCallable!(T)) { alias FUNTYPE = Parameters!(fun); static if(is(Args == void)) { static if(isDelegate!T) return fun; else return toDelegate(fun); } else static if(FUNTYPE.length > args.length) { alias DTYPE = FUNTYPE[args.length..$]; return delegate(DTYPE ars){ TypeTuple!(FUNTYPE) value; value[0..args.length] = args[]; value[args.length..$] = ars[]; return fun(value); }; } else { return delegate(){return fun(args);}; } }
Re: D equivalent of C++ bind ?
On Tuesday, 10 May 2016 at 15:33:03 UTC, chmike wrote: Thanks. This does the job but it's not as concise. The std.functional.partial can not use in runtime, only on complier time. and it can not bind args that more than one.
Re: static import (v2.071.0)
On 5/11/16 10:11 AM, Chris wrote: I'm updating my code to 2.071.0 at the moment. Naturally, I get a lot of warnings like `module std.uni is not accessible here, perhaps add 'static import std.uni;'` Will `static import` bloat my exe or simply access the members I use? No. static import just defines what symbols are accessible in what contexts. The (likely) reason you are getting this is because you are importing a module with a selective import: import std.uni : foo; And then using: std.uni.bar(); What the compiler is saying is that the fully qualified names are no longer going to be imported with selective imports. In order to "fix" this, you do: import std.uni : foo; static import std.uni; Note that another option is: import std.uni : foo, bar; and then changing the fully qualified name to just bar. Or you could use renamed imports. See this article for some explanation: http://www.schveiguy.com/blog/2016/03/import-changes-in-d-2-071/ -Steve
Re: .array changes the order
On 5/12/16 6:17 AM, xtreak wrote: On Thursday, 12 May 2016 at 10:02:46 UTC, thedeemon wrote: On Thursday, 12 May 2016 at 09:44:39 UTC, xtreak wrote: I came across the issue where using .array after .joiner caused the changes to the output. The program is at https://dpaste.dzfl.pl/0885ba2eddb4 . I tried to debug through the output but I couldn't get the exact issue. It will be helpful if someone confirms this as a bug. It's not a bug per se, just probably documentation being not clear enough. Essentially it's the same issue as with File.byLine: a range that mutates its state, so it's ok to consume lazily but if you just store references (as array() does) you get references to the same mutated value as result. Quick fix: r.chunks(2).map!permutations.joiner.map!array.array.writeln; i.e. copy each permutation to separate array before it's gone. Thanks a lot. Can you kindly elaborate a little more on File.byLine with an example of the scenario so that I don't get bitten by it. File.byLine.array works as expected for me. A little more explanation on the permutations will also be helpful since joiner.map!array converts the subranges to arrays, so does joiner work by mutating state if so how does it do. File.byLine.array will create an array of references to the same buffer, which is rewritten as byLine iterates. There can be cases where it works, but there are definitely those for which it won't work. Basically, you are keeping references to the buffer for buffered i/o. I think there is a byLineCopy which works. -Steve
Re: static import (v2.071.0)
On Thursday, 12 May 2016 at 12:45:38 UTC, Steven Schveighoffer wrote: On 5/11/16 10:11 AM, Chris wrote: No. static import just defines what symbols are accessible in what contexts. The (likely) reason you are getting this is because you are importing a module with a selective import: import std.uni : foo; And then using: std.uni.bar(); What the compiler is saying is that the fully qualified names are no longer going to be imported with selective imports. In order to "fix" this, you do: import std.uni : foo; static import std.uni; Note that another option is: import std.uni : foo, bar; and then changing the fully qualified name to just bar. Or you could use renamed imports. See this article for some explanation: http://www.schveiguy.com/blog/2016/03/import-changes-in-d-2-071/ -Steve Thanks for clarifying this. Indeed, I had a mixture of FQN and selective imports. This is due to things like std.uni.foo(); being in parts of older code and import std.uni : bar; So I would have bar() and std.uni.foo() in the same module and stuff like that. I've fixed it now, but I will have to revise things and see what's the best import strategy for each case (based on the newly gained insights).
Re: Is it bug compiler?
On Thursday, 12 May 2016 at 13:20:35 UTC, MGW wrote: Windows 7 32bit --- import std.stdio; import std.conv; class CFormaMain { ~this() { char[] zz = [ 'A', 'B', 'C' ]; writeln(to!string(zz)); } } int main(string[] args) { CFormaMain formaMain; formaMain = new CFormaMain(); return 0; } --- core.exception.InvalidMemoryOperationError@src\core\exception.d(693): Invalid me mory operation No. Look at the documentation of InvalidMemoryOperationError.
Re: Is it bug compiler?
On 5/12/16 9:20 AM, MGW wrote: Windows 7 32bit --- import std.stdio; import std.conv; class CFormaMain { ~this() { char[] zz = [ 'A', 'B', 'C' ]; This allocates. Allocations are not allowed in GC collection cycle. -Steve
Is it bug compiler?
Windows 7 32bit --- import std.stdio; import std.conv; class CFormaMain { ~this() { char[] zz = [ 'A', 'B', 'C' ]; writeln(to!string(zz)); } } int main(string[] args) { CFormaMain formaMain; formaMain = new CFormaMain(); return 0; } --- core.exception.InvalidMemoryOperationError@src\core\exception.d(693): Invalid me mory operation
Re: .array changes the order
On Thursday, 12 May 2016 at 10:17:19 UTC, xtreak wrote: Thanks a lot. Can you kindly elaborate a little more on File.byLine with an example of the scenario so that I don't get bitten by it. File.byLine.array works as expected for me. A little more explanation on the permutations will also be helpful since joiner.map!array converts the subranges to arrays, so does joiner work by mutating state if so how does it do. With some ranges the value they return by .front is only valid until the next call to popFront(). For example, File.byLine() reuses its buffer so after popFront() is called the buffer contains different data and if you had references to the contents of previously returned value they become invalid. This is why byLineCopy() was added. In the same vein permutations() returns a range that has a mutable array of indices inside, which changes every time popFront() is called, and since every value returned by its .front refers to that indices array, if you collect such permutations they will all use the same array of indices and show the same order of elements, the same permutation. Because of this mutable nature of some ranges it's important to understand in which order calls to .front and .popFront() happen. The array() function calls popFront on its input in a loop, consuming the mutable ranges, while map() does not. So in r.map!f.array function f will receive different valid values, before they get invalidated in the loop of array(). But if they contain references to something mutable, it makes sense to make copies before the thing they refer to mutates.
Re: Async or event library
On Tuesday, 10 May 2016 at 13:34:36 UTC, chmike wrote: vibed uses libevent, a C library. The discussion is regarding a possible pure D equivalent of libevent. libasync is an interesting proposal but it is apparently slower than libevent. I don't know the current status because vibed improved its performance in the last months. My initial question is if there is a working group I could join to work on this pure D async library. I'm interested in working on the subject. if you used in unix(linux,bsd,mac),you can look our's event-net lib. now it is only epoll(linux), the kqueue(bsd and mac) is easy to support. and now only timer and tcp. It's like facebook/wangle(Netty + Finagle) smooshed together, but in D. https://github.com/putao-dev/collie
Re: Async or event library
On Tuesday, 10 May 2016 at 13:34:36 UTC, chmike wrote: vibed uses libevent, a C library. The discussion is regarding a possible pure D equivalent of libevent. libasync is an interesting proposal but it is apparently slower than libevent. I don't know the current status because vibed improved its performance in the last months. My initial question is if there is a working group I could join to work on this pure D async library. I'm interested in working on the subject. from my experience its not really slower than libevent and it could be made even faster by taking some time to profile it. plus its battle tested in production and fully cross platform. also, it will most probably not be your bottleneck.
Re: .array changes the order
On Thursday, 12 May 2016 at 13:43:10 UTC, thedeemon wrote: On Thursday, 12 May 2016 at 10:17:19 UTC, xtreak wrote: Thanks a lot. Can you kindly elaborate a little more on File.byLine with an example of the scenario so that I don't get bitten by it. File.byLine.array works as expected for me. A little more explanation on the permutations will also be helpful since joiner.map!array converts the subranges to arrays, so does joiner work by mutating state if so how does it do. With some ranges the value they return by .front is only valid until the next call to popFront(). For example, File.byLine() reuses its buffer so after popFront() is called the buffer contains different data and if you had references to the contents of previously returned value they become invalid. This is why byLineCopy() was added. In the same vein permutations() returns a range that has a mutable array of indices inside, which changes every time popFront() is called, and since every value returned by its .front refers to that indices array, if you collect such permutations they will all use the same array of indices and show the same order of elements, the same permutation. Because of this mutable nature of some ranges it's important to understand in which order calls to .front and .popFront() happen. The array() function calls popFront on its input in a loop, consuming the mutable ranges, while map() does not. So in r.map!f.array function f will receive different valid values, before they get invalidated in the loop of array(). But if they contain references to something mutable, it makes sense to make copies before the thing they refer to mutates. Thanks a lot for the info that really clears a lot of things for me :) I see from the source that byLineCopy makes a .dup on each line and cached at https://github.com/dlang/phobos/blob/master/std/stdio.d#L2029-L2034 with gotFront when front is called a lot of times. I could see a function called emplaceref being used in array. Any ideas on that please.
Re: DlangIDE Themes
On Thursday, 12 May 2016 at 09:57:42 UTC, Chris wrote: On Thursday, 12 May 2016 at 09:51:18 UTC, thedeemon wrote: On Thursday, 12 May 2016 at 09:17:24 UTC, Chris wrote: They shouldn't be hardwired. Best would be to load them dynamically with their respective names encoded in the xml file. In this way people could add their own themes as they see fit. I wouldn't mind creating themes and adding them to DlangIDE as a humble contribution. Don't forget that contents of all those files in resources.list is also "hardwired" into the executable, so there's not much difference between mentioning something in such list file and in the source code. Of course, dynamic loading would be a nice thing to do, in addition to what there is now. Sure, but changing `resources.list` is trivial and can be added to the docs like so "Add the path to your theme file to `resources.list` and restart DlangIDE." It has to be hardwired somewhere, but it shouldn't be the themes. Other editors/IDE's allow you to load your own themes. This is important, because apart from aesthetics, some people might find certain themes easier on the eye than others, e.g. color blind people or people with some sort of visual impairment. Hello, External themes support is planned. It is not a hard task. Btw, try to copy your resource files (res directory) to the same place dlangui executable (e.g. dlangide) is located. Resources from this directory must be accessible from application. The only problem should be list of themes in UI settings. AFAIR, resources from directory should have higher priority than embedded ones. So for testing, you can rename theme to standard name. Best regards, Vadim
Is this template constraint a bug?
is(T : A!T) tells if T can automatically be converted to A!T. The last line below is doing just that, yet the template constraint does not work. class A(T) if (is(T : A!T)) { } // if (is(T : A!T)) gives this error: // Error: template instance x.A!(B) does not match //template declaration A(T) if (is(T : A!T)) //while looking for match for A!(B) class B : A!(B) { } void main(string[] args) { B b = new B(); A!B a = b; // compiles fine } -Eric
Re: Is this template constraint a bug?
On Thursday, 12 May 2016 at 15:33:24 UTC, Eric wrote: is(T : A!T) tells if T can automatically be converted to A!T. The last line below is doing just that, yet the template constraint does not work. class A(T) if (is(T : A!T)) { } Yes, it's a bug. Please file an issue. Meanwhile try this workaround: class A(T) { static assert(is(T : A!T), "..."); }
Re: DlangIDE Themes
On Thursday, 12 May 2016 at 15:29:17 UTC, Vadim Lopatin wrote: Hello, External themes support is planned. It is not a hard task. Btw, try to copy your resource files (res directory) to the same place dlangui executable (e.g. dlangide) is located. Resources from this directory must be accessible from application. The only problem should be list of themes in UI settings. AFAIR, resources from directory should have higher priority than embedded ones. So for testing, you can rename theme to standard name. Best regards, Vadim I've tried that too, but changes I make are ignored.
Re: Is this template constraint a bug?
Yes, it's a bug. Please file an issue. Meanwhile try this workaround: class A(T) { static assert(is(T : A!T), "..."); } Bug report filed, and thanks for the workaround. -Eric
Re: How to split a string/array with multiple separators?
On Wednesday, 16 December 2015 at 15:27:22 UTC, Marc Schütz wrote: On Wednesday, 16 December 2015 at 14:47:26 UTC, Dragos Carp wrote: On Wednesday, 16 December 2015 at 14:18:28 UTC, Borislav Kosharov wrote: I want to split a string using multiple separators. In std.array the split function has a version where it takes a range as a separator, but it works differently than what I want. Say if I call it with " -> " it will search for the whole thing together. I want to pass split a list of separators say [":", ",", ";"] and if it finds any of those to split it. Sorry if this questions is stupid but I cant find how to do it. void main() { import std.stdio: writeln; writeln("abc,def;ghi".splitter!(a => !":,;".find(a).empty).array); } The call to `array` is unnecessary in this example, and you can use the shorter `canFind`: writeln("abc,def;ghi".splitter!(a => ":,;".canFind(a))); Dear Borislav, Dragos and Marc, Thanks for this question (@Borislav) and the solution's approaches (@Dragos and @Marc). Today, I had the same task and tried to find a solution for it. Unfortunately, the proposed solutions seem not work. Here is the version from Dragos (run it directly on the web): http://ideone.com/fglk0s Here the version from Marc: http://ideone.com/yCaYrD In both cases, I got the "Error: template std.algorithm.iteration.splitter cannot deduce function from argument types [...]" message. Can anyone help me with a functional example? That would be great :) Best regards, Thorsten
Re: How to split a string/array with multiple separators?
On 5/12/16 3:25 PM, Thorsten Sommer wrote: On Wednesday, 16 December 2015 at 15:27:22 UTC, Marc Schütz wrote: On Wednesday, 16 December 2015 at 14:47:26 UTC, Dragos Carp wrote: On Wednesday, 16 December 2015 at 14:18:28 UTC, Borislav Kosharov wrote: I want to split a string using multiple separators. In std.array the split function has a version where it takes a range as a separator, but it works differently than what I want. Say if I call it with " -> " it will search for the whole thing together. I want to pass split a list of separators say [":", ",", ";"] and if it finds any of those to split it. Sorry if this questions is stupid but I cant find how to do it. void main() { import std.stdio: writeln; writeln("abc,def;ghi".splitter!(a => !":,;".find(a).empty).array); } The call to `array` is unnecessary in this example, and you can use the shorter `canFind`: writeln("abc,def;ghi".splitter!(a => ":,;".canFind(a))); Dear Borislav, Dragos and Marc, Thanks for this question (@Borislav) and the solution's approaches (@Dragos and @Marc). Today, I had the same task and tried to find a solution for it. Unfortunately, the proposed solutions seem not work. Here is the version from Dragos (run it directly on the web): http://ideone.com/fglk0s Here the version from Marc: http://ideone.com/yCaYrD In both cases, I got the "Error: template std.algorithm.iteration.splitter cannot deduce function from argument types [...]" message. Can anyone help me with a functional example? That would be great :) You are missing some imported symbols. Unfortunately, due to the way binaryFun works, this masks the true error (can't compile your lambda!). https://dpaste.dzfl.pl/79399404f2ad Note, the ideone compiler is very out of date. But it probably would work with the correct imports. -Steve
Dynamically setting struct values from hash map
Hi guys, apologies for the silly question, but I come from the world of dynamic languages and I'm wondering if it's possible to set struct values basic on dynamic variables? e.g. struct Person { string firstName; string lastName; } void main() { string[string] map; map["firstName"] = "Homer"; map["lastName"] = "Simpson"; } Is it possible to iterate through the hash map and set the struct values using the key/value pairs? Something like this: e.g. Person p1; foreach(key,val; map) { p1[key] = val; } The problem I'm trying to solve is that I'm wanting to write a generic "model" class that can read a record from a database and populate a known struct from the database values. I have seen the "allMembers" method from the traits module that can give me the names of the struct fields, but I am unsure if it's even possible to set the struct values using variable/dynamic names. Any help will be greatly appreciated! Cheers, Andrew.
Re: Dynamically setting struct values from hash map
On Thursday, 12 May 2016 at 20:52:46 UTC, Andrew Chapman wrote: I have seen the "allMembers" method from the traits module that can give me the names of the struct fields, but I am unsure if it's even possible to set the struct values using variable/dynamic names. Yes. You can't loop over the hash and set values on the struct, since looping a hash is a run time operation, but you can loop over struct members. So, the trick is to loop over the struct members (a compile-time operation) and set them (converting type with `std.conv.to` if necessary) if the value is in the hash. foreach(member; __traits(allMembers, YourStruct)) if(member in yourhash) __traits(getMember, your_object, member) = to!right_type(yourhash[member]); basically, it is a bit more complex to filter out inappropriate fields and such, but that's the idea. Check out the sample chapter of my book https://www.packtpub.com/application-development/d-cookbook to see more, you can get the reflection chapter free on that site.
Re: Dynamically setting struct values from hash map
On Thursday, 12 May 2016 at 21:01:06 UTC, Adam D. Ruppe wrote: foreach(member; __traits(allMembers, YourStruct)) if(member in yourhash) __traits(getMember, your_object, member) = to!right_type(yourhash[member]); basically, it is a bit more complex to filter out inappropriate fields and such, but that's the idea. Check out the sample chapter of my book https://www.packtpub.com/application-development/d-cookbook to see more, you can get the reflection chapter free on that site. That's wonderful Adam, thank you! I actually had your book previously bookmarked - I should probably buy it :-)
Request assistance converting C's #ifndef to D
The following preprocessor directives are frequently encountered in C code, providing a default constant value where the user of the code has not specified one: #ifndef MIN #define MIN 99 #endif #ifndef MAX #define MAX 999 #endif I'm at a loss at how to properly convert it to D. I've tried the following: enum MIN = 0; static if(MIN <= 0) { MIN = 99; } it works as long as the static if is enclosed in a static this(), otherwise the compiler complains: mo.d(493): Error: no identifier for declarator MIN mo.d(493): Error: declaration expected, not '=' This however, does not feel like the right way to do thinks but I cannot find any documentation that provides an alternative. Is there a better way to do this? Thanks, Andrew
Re: Request assistance converting C's #ifndef to D
On Fri, May 13, 2016 at 07:51:17AM +0900, Andrew Edwards via Digitalmars-d-learn wrote: > The following preprocessor directives are frequently encountered in C > code, providing a default constant value where the user of the code > has not specified one: > > #ifndef MIN > #define MIN 99 > #endif > > #ifndef MAX > #define MAX 999 > #endif > > I'm at a loss at how to properly convert it to D. I've tried the > following: > > enum MIN = 0; > static if(MIN <= 0) > { > MIN = 99; > } [...] That seems wrong. You can't assign to an enum. Besides, doesn't your declaration of MIN shadow whatever other definitions may be currently in effect? Perhaps what you meant is something like this? static if (!is(typeof(MIN) : int)) enum MIN = 99; though I'm not sure if such a thing will actually work, since order-dependent declarations in D are a kind of dangerous territory to tread on. T -- What's an anagram of "BANACH-TARSKI"? BANACH-TARSKI BANACH-TARSKI.
Re: Request assistance converting C's #ifndef to D
On 5/13/16 8:00 AM, H. S. Teoh via Digitalmars-d-learn wrote: On Fri, May 13, 2016 at 07:51:17AM +0900, Andrew Edwards via Digitalmars-d-learn wrote: The following preprocessor directives are frequently encountered in C code, providing a default constant value where the user of the code has not specified one: #ifndef MIN #define MIN 99 #endif #ifndef MAX #define MAX 999 #endif I'm at a loss at how to properly convert it to D. I've tried the following: enum MIN = 0; static if(MIN <= 0) { MIN = 99; } [...] That seems wrong. You can't assign to an enum. Besides, doesn't your declaration of MIN shadow whatever other definitions may be currently in effect? Okay, got it. It seams I just hadn't hit that bug yet because of other unresolved issues. Perhaps what you meant is something like this? static if (!is(typeof(MIN) : int)) enum MIN = 99; This seems to do the trick. though I'm not sure if such a thing will actually work, since order-dependent declarations in D are a kind of dangerous territory to tread on. So what is the current best practice when encountering such statements during porting? T
imports && -run [Bug?]
module mod; // import inc; [1] // import inc: p=print; [1] // static import inc; [1] void main() { // import inc: print; // [2] print(); // static import inc; // [3] // inc.print(); } -- module inc; /*public*/ void print() // [4] { import std.stdio: writeln; writeln("You made it!"); } -- compiler: DMD v2.071.0 os: OS X El Capitan (10.11.3) -- command: dmd -run mod inc output: Undefined symbols for architecture x86_64: "_D3inc5printFZv", referenced from: __Dmain in mod.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) --- errorlevel 1 None of the variations of imports work when compiled with the -run switch but all work perfectly well without it.
Re: Request assistance converting C's #ifndef to D
On 5/13/16 8:40 AM, Andrew Edwards wrote: That seems wrong. You can't assign to an enum. Besides, doesn't your declaration of MIN shadow whatever other definitions may be currently in effect? Okay, got it. It seams I just hadn't hit that bug yet because of other unresolved issues. Perhaps what you meant is something like this? static if (!is(typeof(MIN) : int)) enum MIN = 99; This seems to do the trick. But not exactly the way it's expected to. In the snippets below, C outputs 10 while D outputs 100; min.c = #define MIN 10 // [1] #include "mild.h" int main() { print(); return 0; } min.h = #include #ifndef MIN #define MIN 100 #endif void print() { printf("%d\n", MIN); } minA.d = enum MIN = 10; // [1] import minB; void main() { print(); } minB.d = static if (!is(typeof(MIN) : int)) enum MIN = 100; void print() { import std.stdio: writeln; writeln(MIN); } Is there a way to reproduce the same behavior? Are there reason's for not allowing this functionality or am I just misunderstanding and going about things the wrong way? [1] same result whether placed before or after the #include/import statement. though I'm not sure if such a thing will actually work, since order-dependent declarations in D are a kind of dangerous territory to tread on. So what is the current best practice when encountering such statements during porting? T
Re: Request assistance converting C's #ifndef to D
On Friday, 13 May 2016 at 04:59:23 UTC, Andrew Edwards wrote: Is there a way to reproduce the same behavior? Are there reason's for not allowing this functionality or am I just misunderstanding and going about things the wrong way? [1] same result whether placed before or after the #include/import statement. though I'm not sure if such a thing will actually work, since order-dependent declarations in D are a kind of dangerous territory to tread on. C's #include directive and D's import statement have fundamentally different semantics: C's is basically equivalent to copy-pasting the contents of the included file at the location of the #include directive. Combined with C's other pre-processor features, this means that a header file can (potentially) do something *completely* different in each file that includes it, because it is being recompiled from scratch, in a new context. D's import statement, on the other hand, merely makes one module's symbols visible from another. Each module is only compiled once, regardless of how many times it is imported. As such, a module's semantics cannot be changed by each importer, unlike in C. So what is the current best practice when encountering such statements during porting? The affected code should be re-factored to use some other means of configuration, such as: 1) Adding configuration parameters individually to each public symbol as needed: minA.d = import minB; void main() { print!10(); } minB.d = module minB; void print(long MIN)() { import std.stdio: writeln; writeln(MIN); } 2) Enclosing the module in a `struct` or `class` which can be instantiated and configured individually by each user, either at run time or compile time: minA.d = import minB; immutable minB = MinB(10); void main() { minB.print(); } minB.d = module minB; struct MinB { long MIN; void print() { import std.stdio: writeln; writeln(MIN); } } 3) Enclosing the module in a `template` that can be instantiated and configured by each user at compile time: minA.d = import minB; alias minB = MinB!10; // Or: alias print = MinB!(10).print; void main() { minB.print(); // Or: print(); } minB.d = module minB; template MinB(long MIN) { void print() { import std.stdio: writeln; writeln(MIN); } } 4) Passing `version` identifiers at compile time (using the -version command line switch): minA.d = import minB; void main() { print!10(); } minB.d = module minB; version(Min10) { enum MIN = 10; } else { enum MIN = 100; } void print() { import std.stdio: writeln; writeln(MIN); } 5) As a last resort, enclosing the module in a `mixin template` that can be mixed in to each importing module with the required configuration options at compile time: minA.d = import minB; mixin minB!10; void main() { print(); } minB.d = module minB; mixin template minB(long MIN) { void print() { import std.stdio: writeln; writeln(MIN); } } (5) is the most similar to how the C example works, but most of the time it is a very inefficient solution, causing tons of code bloat and redundant instantiations of the included functions and data structures. Don't do this unless you can't find any other reasonable way to do it. Which of (1) to (4) is best just depends on exactly what the pre-processor logic was being used for.
Re: Request assistance converting C's #ifndef to D
On 5/13/16 7:51 AM, Andrew Edwards wrote: The following preprocessor directives are frequently encountered in C code, providing a default constant value where the user of the code has not specified one: #ifndef MIN #define MIN 99 #endif #ifndef MAX #define MAX 999 #endif I'm at a loss at how to properly convert it to D. I've tried the following: enum MIN = 0; static if(MIN <= 0) { MIN = 99; } it works as long as the static if is enclosed in a static this(), otherwise the compiler complains: mo.d(493): Error: no identifier for declarator MIN mo.d(493): Error: declaration expected, not '=' This however, does not feel like the right way to do thinks but I cannot find any documentation that provides an alternative. Is there a better way to do this? Thanks, Andrew Additionally, what's the best way to handle nested #ifdef's? Those that appear inside structs, functions and the like... I know that global #ifdef's are turned to version blocks but versions blocks cannot be used inside classes, stucts, functions, etc.
Re: imports && -run [Bug?]
On Friday, 13 May 2016 at 01:16:36 UTC, Andrew Edwards wrote: command: dmd -run mod inc output: Undefined symbols for architecture x86_64: "_D3inc5printFZv", referenced from: __Dmain in mod.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) --- errorlevel 1 None of the variations of imports work when compiled with the -run switch but all work perfectly well without it. According to the DMD compiler manual, the -run switch only accepts a single source file: -run srcfile args... After the first source file, any further arguments passed to DMD will be interpreted as arguments to be passed to the program being run. Have you tried using DUB? It has lots of convenient features, including a `run` command that supports multiple source files: http://code.dlang.org/docs/commandline#run
Re: Request assistance converting C's #ifndef to D
On Friday, 13 May 2016 at 06:05:14 UTC, Andrew Edwards wrote: Additionally, what's the best way to handle nested #ifdef's? Those that appear inside structs, functions and the like... I know that global #ifdef's are turned to version blocks but versions blocks cannot be used inside classes, stucts, functions, etc. `static if` and `version()` can be nested, and both work just fine inside classes, structs, functions, etc.: module app; version = withPrint; struct A { version(withPrint) { class B { static if(size_t.sizeof == 4) { static void print() { import std.stdio : writeln; version(unittest) { writeln("Hello, 32-bit world of unit tests!"); } else { writeln("Hello, 32-bit world!"); } } } else { static void print() { import std.stdio : writeln; version(unittest) { writeln("Hello, presumably 64-bit world of unit tests!"); } else { writeln("Hello, presumably 64-bit world!"); } } } } } } void main() { A.B.print(); } (Try it on DPaste: https://dpaste.dzfl.pl/0fafe316f739)
Re: imports && -run [Bug?]
On 5/13/16 3:10 PM, tsbockman wrote: On Friday, 13 May 2016 at 01:16:36 UTC, Andrew Edwards wrote: command: dmd -run mod inc output: Undefined symbols for architecture x86_64: "_D3inc5printFZv", referenced from: __Dmain in mod.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) --- errorlevel 1 None of the variations of imports work when compiled with the -run switch but all work perfectly well without it. According to the DMD compiler manual, the -run switch only accepts a single source file: -run srcfile args... After the first source file, any further arguments passed to DMD will be interpreted as arguments to be passed to the program being run. Thanks, I guess I just expected it to work the same as rdmd does and didn't even bother trying to look in the manual regarding this. I fail to see why the compiler would be less capable at this task than rdmd. Since it is already build to accept multiple input files and knows more about what's going on during compilation than rdmd will ever know, in does not make sense that it should inferior in this regard: yet rdmd takes one imput file and sorts out all dependencies. Have you tried using DUB? It has lots of convenient features, including a `run` command that supports multiple source files: http://code.dlang.org/docs/commandline#run I've used dub before but it is not desired for what I'm trying to do. rdmd does the trick. Thank you.
Re: imports && -run [Bug?]
On 2016-05-13 08:10, tsbockman wrote: According to the DMD compiler manual, the -run switch only accepts a single source file: -run srcfile args... After the first source file, any further arguments passed to DMD will be interpreted as arguments to be passed to the program being run. To elaborate, since the second file "inc" is not passed to the compiler, it will not compile that file, therefore you get linker errors. The solution is to pass all extra files before the -run flag. Even better is to use "rdmd" which will automatically track and compile dependencies. Using rdmd it's enough to pass a single file to compile all dependencies and run the resulting binary: "rdmd mod". Have you tried using DUB? It has lots of convenient features, including a `run` command that supports multiple source files: http://code.dlang.org/docs/commandline#run Dub is a great tool when a project grows larger than a few files. -- /Jacob Carlborg
Re: Request assistance converting C's #ifndef to D
On 5/13/16 3:23 PM, tsbockman wrote: On Friday, 13 May 2016 at 06:05:14 UTC, Andrew Edwards wrote: Additionally, what's the best way to handle nested #ifdef's? Those that appear inside structs, functions and the like... I know that global #ifdef's are turned to version blocks but versions blocks cannot be used inside classes, stucts, functions, etc. `static if` and `version()` can be nested, and both work just fine inside classes, structs, functions, etc.: module app; version = withPrint; struct A { version(withPrint) { class B { static if(size_t.sizeof == 4) { static void print() { import std.stdio : writeln; version(unittest) { writeln("Hello, 32-bit world of unit tests!"); } else { writeln("Hello, 32-bit world!"); } } } else { static void print() { import std.stdio : writeln; version(unittest) { writeln("Hello, presumably 64-bit world of unit tests!"); } else { writeln("Hello, presumably 64-bit world!"); } } } } } } void main() { A.B.print(); } Not sure what I was doing wrong earlier. Works perfectly fine now. Glad I asked because I usually just get frustrated and put it aside and usually never return to it. Thanks for the assist. (Try it on DPaste: https://dpaste.dzfl.pl/0fafe316f739)