Re: Creating a growable binary heap or priority queue using Phobos?
On Monday, 14 November 2011 at 06:15:18 UTC, SimonM wrote: On 2011/11/14 02:10 AM, bearophile wrote: SimonM: 2009, 27 April: http://www.digitalmars.com/d/archives/digitalmars/D/std.algorithm.BinaryHeap_88811.html See the working version: http://rosettacode.org/wiki/Huffman_coding#D Bye, bearophile Okay, I looked at the example, and it seems that the only reason it works is because that piece of code never requires the array's length to grow larger than it's initial length (at the start of the loop, 2 elements are taken out, and at the end, only one is inserted back in). If I try using a BinaryHeap with a range, then, like the documentation mentions, I can't grow that BinaryHeap any larger than it's initial size, because I got the following error: Cannot grow a heap created over a range. But somehow I can't get it working with an Array!(T) like the documentation implies it should be capable of? Is this problem resolved? I cannot produce a growable BinaryHeap myself.
Re: Creating a growable binary heap or priority queue using Phobos?
On Saturday, 22 June 2013 at 07:48:25 UTC, qznc wrote: On Monday, 14 November 2011 at 06:15:18 UTC, SimonM wrote: On 2011/11/14 02:10 AM, bearophile wrote: SimonM: 2009, 27 April: http://www.digitalmars.com/d/archives/digitalmars/D/std.algorithm.BinaryHeap_88811.html See the working version: http://rosettacode.org/wiki/Huffman_coding#D Bye, bearophile Okay, I looked at the example, and it seems that the only reason it works is because that piece of code never requires the array's length to grow larger than it's initial length (at the start of the loop, 2 elements are taken out, and at the end, only one is inserted back in). If I try using a BinaryHeap with a range, then, like the documentation mentions, I can't grow that BinaryHeap any larger than it's initial size, because I got the following error: Cannot grow a heap created over a range. But somehow I can't get it working with an Array!(T) like the documentation implies it should be capable of? Is this problem resolved? I cannot produce a growable BinaryHeap myself. Ok, got it. Instead of using a dynamic array directly, wrapping it into a std.container.Array works. import std.container: Array, heapify; Foo[] arr = ...; auto wrapped = Array!Foo(arr); auto queue = heapify(wrapped); In general, other containers should work as well, since containers provide an insertBack method whereas the builtin arrays/ranges do not.
Re: limits for numeric types
On Saturday, 22 June 2013 at 02:47:04 UTC, Jesse Phillips wrote: On Friday, 21 June 2013 at 19:30:28 UTC, Craig Dillabaugh wrote: Thank you very much. Now, is there any way to get Google to find my question/your answer if someone searches for dlang numeric limits? Cheers, Craig Yes, get the text, numeric limits onto the page. Could you expand on this part a bit. Is there a way to tell the Google search engine, hey I searched for this, you gave me these links, but here is the one I wanted.
Re: Is it possible to use global variables spanning modules?
That works great thanks all.
Re: limits for numeric types
On Saturday, 22 June 2013 at 11:20:18 UTC, Craig Dillabaugh wrote: On Saturday, 22 June 2013 at 02:47:04 UTC, Jesse Phillips wrote: On Friday, 21 June 2013 at 19:30:28 UTC, Craig Dillabaugh wrote: Thank you very much. Now, is there any way to get Google to find my question/your answer if someone searches for dlang numeric limits? Cheers, Craig Yes, get the text, numeric limits onto the page. Could you expand on this part a bit. Is there a way to tell the Google search engine, hey I searched for this, you gave me these links, but here is the one I wanted. Sorry, replied too early in the morning. Now I understand what you are saying, to add numeric limits to the D site. I may give that a try.
Passing Appender by value
I just learned today that passing Appender by value does not have the semantics I thought it would: - import std.array; import std.stdio; void call(Appender!(int[]) buffer) { buffer.put(1); } void main() { Appender!(int[]) buffer; writeln(buffer.data); // writes [], it's empty } - Is this a bug? If not, shouldn't we introduce a disabled copy constructor to force passing Appender by ref to functions to avoid this type of user bug? I can't see how the current behavior is useful to anyone.
Re: Passing Appender by value
On 6/22/13, Andrej Mitrovic andrej.mitrov...@gmail.com wrote: I just learned today that passing Appender by value does not have the semantics I thought it would: - import std.array; import std.stdio; void call(Appender!(int[]) buffer) { buffer.put(1); } void main() { Appender!(int[]) buffer; writeln(buffer.data); // writes [], it's empty } - WRONG example, there's a missing call there, I meant: - import std.array; import std.stdio; void call(Appender!(int[]) buffer) { buffer.put(1); } void main() { Appender!(int[]) buffer; call(buffer); writeln(buffer.data); // writes [], it's empty } -
Re: Passing Appender by value
On 6/22/13, Andrej Mitrovic andrej.mitrov...@gmail.com wrote: Appender!(int[]) buffer; call(buffer); writeln(buffer.data); // writes [], it's empty Apparently it's the same thing as the old AA problem. Essentially the buffer would have to be initialized first by appending: - import std.array; import std.stdio; void call(Appender!(int[]) buffer) { buffer.put(1); } void main() { Appender!(int[]) buffer; call(buffer); assert(buffer.data.empty); // passes call(buffer); assert(buffer.data.empty); // still passes buffer.put(2); call(buffer); assert(buffer.data == [2, 1]); // now it finally went through } - It has something to do with null-initialization. I remember the discussion about this problem with hashes, I just can't remember if there was a bug report about it to link to.
Re: Passing Appender by value
On Saturday, 22 June 2013 at 13:48:53 UTC, Andrej Mitrovic wrote: On 6/22/13, Andrej Mitrovic andrej.mitrov...@gmail.com wrote: Appender!(int[]) buffer; call(buffer); writeln(buffer.data); // writes [], it's empty Apparently it's the same thing as the old AA problem. Essentially the buffer would have to be initialized first by appending: - import std.array; import std.stdio; void call(Appender!(int[]) buffer) { buffer.put(1); } void main() { Appender!(int[]) buffer; call(buffer); assert(buffer.data.empty); // passes call(buffer); assert(buffer.data.empty); // still passes buffer.put(2); call(buffer); assert(buffer.data == [2, 1]); // now it finally went through } - It has something to do with null-initialization. I remember the discussion about this problem with hashes, I just can't remember if there was a bug report about it to link to. The problem occurs whenever the internal array is resized because what actually happens is that a new array is allocated and the contents copied over - the original Appender still references the original array (or in this case null). The last example only works because when you call put(2) it actually allocates an array large enough to hold at least another item as well. As usual it can be solved by introducing an extra layer of indirection, either by passing by ref or by making Appender store a pointer to a range.
Re: Passing Appender by value
On Saturday, 22 June 2013 at 14:19:45 UTC, Diggory wrote: The problem occurs whenever the internal array is resized because what actually happens is that a new array is allocated and the contents copied over - the original Appender still references the original array (or in this case null). The last example only works because when you call put(2) it actually allocates an array large enough to hold at least another item as well. As usual it can be solved by introducing an extra layer of indirection, either by passing by ref or by making Appender store a pointer to a range. No, it's not that bad, because the extra layer of indirection is already there. The problem is that said layer isn't actually initialized yet...
Re: Passing Appender by value
On Saturday, 22 June 2013 at 13:48:53 UTC, Andrej Mitrovic wrote: On 6/22/13, Andrej Mitrovic andrej.mitrov...@gmail.com wrote: Appender!(int[]) buffer; call(buffer); writeln(buffer.data); // writes [], it's empty Apparently it's the same thing as the old AA problem. Essentially the buffer would have to be initialized first by appending: Yeah... same old, same old. I think you can work around the problem using appender: auto buffer = appender!(int[])(); This is off memory, so not 100% guaranteed, but I remember this worked for me last time *I* ran into this problem. Indeed, this is a recurring problem in D with non-initialized reference types, AA's, Appender, Containers... The fact there is no standardized way to make a call for run-time intialization with no arguments doesn't help either. I had made a request for having an explicit runtime constructor that takes no arguments: http://forum.dlang.org/thread/bvuquzwfykiytdwsq...@forum.dlang.org Didn't really get anywhere though... In any case, I think this is a ***HUGE*** problem for D (my N°1 problem anyways). static opCall() kind of helps, but it's not quite a constructor... I think we're kind of doomed to keep this issue around unresolved, biting users in the ass *everyday*, for still quite some time :(
Re: Passing Appender by value
On 6/22/13, monarch_dodra monarchdo...@gmail.com wrote: I think you can work around the problem using appender: auto buffer = appender!(int[])(); Yes, because it has a default argument which it passes to the Appender constructor. If only we had default constructors for structs in D.. or a general solution to this issue. I remember maybe a year ago or so I've ran into the same issue with hashes, and now it almost bit me hard again (luckily this was caught immediately in a failing unittest).
Re: Passing Appender by value
On Saturday, 22 June 2013 at 16:08:01 UTC, Andrej Mitrovic wrote: On 6/22/13, monarch_dodra monarchdo...@gmail.com wrote: I think you can work around the problem using appender: auto buffer = appender!(int[])(); Yes, because it has a default argument which it passes to the Appender constructor. If only we had default constructors for structs in D.. or a general solution to this issue. I remember maybe a year ago or so I've ran into the same issue with hashes, and now it almost bit me hard again (luckily this was caught immediately in a failing unittest). What was the main reason for Walter to disable default CTors for structs?
Re: Can call static method with null reference
but that's a problem caused by the fact that static functions can be called via an instance, and fixing that would mean making it illegal to call static functions on instances (which I would love to have happen but don't expect to ever happen). - Jonathan M Davis What was the reason for this terrible design decision?
Re: Can call static method with null reference
On Sat, Jun 22, 2013 at 06:34:25PM +0200, Namespace wrote: but that's a problem caused by the fact that static functions can be called via an instance, and fixing that would mean making it illegal to call static functions on instances (which I would love to have happen but don't expect to ever happen). - Jonathan M Davis What was the reason for this terrible design decision? I've asked about that, but never got a real answer. I'm still hoping people would change their mind and reverse this bad decision. Conflating static members with non-static members is just a really bad idea. T -- 640K ought to be enough -- Bill G., 1984. The Internet is not a primary goal for PC usage -- Bill G., 1995. Linux has no impact on Microsoft's strategy -- Bill G., 1999.
Re: Passing Appender by value
On Saturday, 22 June 2013 at 16:31:16 UTC, Namespace wrote: On Saturday, 22 June 2013 at 16:08:01 UTC, Andrej Mitrovic wrote: On 6/22/13, monarch_dodra monarchdo...@gmail.com wrote: I think you can work around the problem using appender: auto buffer = appender!(int[])(); Yes, because it has a default argument which it passes to the Appender constructor. If only we had default constructors for structs in D.. or a general solution to this issue. I remember maybe a year ago or so I've ran into the same issue with hashes, and now it almost bit me hard again (luckily this was caught immediately in a failing unittest). What was the main reason for Walter to disable default CTors for structs? So that *default* construction can be evaluated statically, which then means .init can exist, which allows all of D's postblit mechanics, as well as move semantics. It also means that declaring statics in a function is possible and doesn't require any special run-time code for first initialization. I think the problem is that since in C++ no-arg = default, they removed constructors that took no arguments, so as to avoid any confusion, or maybe they just didn't realize that someone might want to runtime construct something, but have no arguments to pass to the constructor. IMO, there was a *little* bit of lack of hindsight on that one, but the choice was clearly superior to C++'s CC scheme on return by value...
Multiple return type from object factory possible?
class A { ... } class NonContainer : A { ... } class Container : A { A[] container; } class NC1 : NonContainer {} ... class C1 : Container {} ... A getO(string info) { switch (info) { default : return new NonContainer(); case info1: return new C1(); case info2: return new NC1(); case info3: return new Container(); case info4: return new NonContainer(); ... } } void foo() { auto o = getO(some information); if (is(typeof(o) == Container) { ... } // Doesn't work. // Type is always A. ... } Is there a way to make getO return the most specialized type of the instantiated object in the switch statement to enable this pattern?
Re: Multiple return type from object factory possible?
On Sat, 22 Jun 2013 18:58:22 +0200, deed n...@none.none wrote: class A { ... } class NonContainer : A { ... } class Container : A { A[] container; } class NC1 : NonContainer {} ... class C1 : Container {} ... A getO(string info) { switch (info) { default : return new NonContainer(); case info1: return new C1(); case info2: return new NC1(); case info3: return new Container(); case info4: return new NonContainer(); ... } } void foo() { auto o = getO(some information); if (is(typeof(o) == Container) { ... } // Doesn't work. // Type is always A. ... } Is there a way to make getO return the most specialized type of the instantiated object in the switch statement to enable this pattern? The type of an expression in D is determined at compile time, and getO returns an A. Hence, o will always have static type A, and is(typeof(... only checks the static type. If you want to check the dynamic (run-time) type of o, you should instead see if it is castable to Container: auto o = getO(info3); if (cast(Container)o != null) { ... } -- Simen
Re: Can call static method with null reference
On Saturday, 22 June 2013 at 16:44:36 UTC, H. S. Teoh wrote: On Sat, Jun 22, 2013 at 06:34:25PM +0200, Namespace wrote: but that's a problem caused by the fact that static functions can be called via an instance, and fixing that would mean making it illegal to call static functions on instances (which I would love to have happen but don't expect to ever happen). - Jonathan M Davis What was the reason for this terrible design decision? I've asked about that, but never got a real answer. I'm still hoping people would change their mind and reverse this bad decision. Conflating static members with non-static members is just a really bad idea. I don't see what's so terrible about it: If A can do it, I don't see what an instance of a couldn't? I find that it is in line with what ufcs does: It streamlines the calling convention. This is particularly relevent to the fact that D has a lot of emphasis on auto type, which means that more often than not, it is easy to manipulate the instance, but more laborious to get the type. EG: auto myObject = foo!mode.getObject(); auto copy = myObject[0].bar.CreateInstance(); There! I wouldn't want to have to insert a typeof in there. My bar member is perfectly capable of creating and instance, so I don't see why I'd have to explicitly request this from the typeof. ... unless typeof could be used ufcs style, as a property, just like stringof et al. ... *THEN* we'd be talking. I *HATE* writing typeof(a).stringof or whatever when everything screams at me to write a.typeof.stringof. :(
Re: Multiple return type from object factory possible?
auto o = getO(info3); if (cast(Container)o != null) { ... } Thanks Simen. (Compiler requires !is instead of !=)
Re: Ping qznc: Re: A little of coordination for Rosettacode
On Saturday, 16 February 2013 at 11:30:00 UTC, Jos van Uden wrote: On 16-2-2013 8:58, qznc wrote: On Saturday, 16 February 2013 at 06:58:01 UTC, qznc wrote: On Saturday, 16 February 2013 at 02:23:42 UTC, Jos van Uden wrote: On 5-2-2013 20:45, Jos van Uden wrote: By the way, I think 'Qznc' may want to have a look at 'The dining philosophers': http://rosettacode.org/wiki/Dining_philosophers I should find the time to solve it this weekend. Wow, my kid let me do some hacking right now and it was simpler than expected. Posted a solution already. Wow, that was quick. Thanks! The current D code for Dining philosophers does not compile with dmd v2.063.2, the error message being dining.d(34): Error: cannot uniquely infer foreach argument types The code looks OK to me (but I'm a D newbie) so I wonder if someone could explain the inference issue. Where should an annotation be added to allow this to compile? 1 import std.stdio, std.algorithm, std.string, std.parallelism, 2core.sync.mutex; 3 4 void eat(in uint i, in string name, Mutex[] forks) { 5writeln(name, is hungry.); 6 7immutable j = (i + 1) % forks.length; 8 9 // Take forks i and j. The lower one first to prevent deadlock. 10auto fork1 = forks[min(i, j)]; 11auto fork2 = forks[max(i, j)]; 12 13fork1.lock(); 14scope(exit) fork1.unlock(); 15 16fork2.lock(); 17scope(exit) fork2.unlock(); 18 19writeln(name, is eating.); 20writeln(name, is full.); 21 } 22 23 void think(in string name) { 24writeln(name, is thinking.); 25 } 26 27 void main() { 28 const philosophers = Aristotle Kant Spinoza Marx Russell.split(); 29Mutex[philosophers.length] forks; 30foreach (ref fork; forks) 31 fork = new Mutex(); 32 33defaultPoolThreads = forks.length; 34 foreach (uint i, philo; taskPool.parallel(philosophers)) { 35 foreach (_; 0 .. 100) { 36eat(i, philo, forks); 37think(philo); 38 } 39} 40 } BTW, I like the coding style being used in the rosetta examples and TDPL much better than the library style. -- Brian
Problems building docs
Hello all, I'm having problems building the docs. I've got the latest d-programming-language.org checked out, and have tried to build with make -f posix.mak. The basic html part builds fine, but it falls over when trying to build phobos-prerelease with the error: make --directory=../phobos -f posix.mak \ DOC_OUTPUT_DIR=~/code/D/d-programming-language.org/web/phobos-prerelease html -j 4 make[1]: Entering directory `~/code/D/phobos' make[1]: *** No rule to make target `~/code/D/d-programming-language.org/web/phobos-prerelease/index.html', needed by `html'. Stop. make[1]: Leaving directory `~/code/D/phobos' make: *** [~/code/D/d-programming-language.org/web/phobos-prerelease/index.html] Error 2 Can anyone advise? Or is it just a bug in the makefile? Thanks best wishes, -- Joe
Re: Ping qznc: Re: A little of coordination for Rosettacode
Brian Rogoff: The current D code for Dining philosophers does not compile with dmd v2.063.2, the error message being dining.d(34): Error: cannot uniquely infer foreach argument types I try to keep the D entries on Rosettacode updated, but every dmd release breaks tons of code, and Rosettacode has almost one thousand D programs (many tasks have two or more D entries, to show different solutions or different coding style, or to show code with different tradeoffs, etc), so you find some broken programs. I don't know what's changed in taskPool.parallel, I will investigate later. Or you can investigate yourself if you want. BTW, I like the coding style being used in the rosetta examples and TDPL much better than the library style. I try to keep the D code on Rosettacode with a quite uniform style. It follows the dstyle, the main difference is the opening brace that's in Egyptian style, but such brace style is required only in Phobos, while the dstyle does not require the Phobos style for all D code, it's in Additional Requirements for Phobos: http://dlang.org/dstyle.html Later, bearophile
alias c=mixin(expr); disallowed, why?
Is there a reason the language spec disallows this? void main(){ auto a=mixin(1);//OK alias b=a;//OK mixin(alias c=a;);//OK // alias c=mixin(a);//NG : Error: basic type expected, not mixin }
Re: Can call static method with null reference
On 2013-06-22 19:11, monarch_dodra wrote: I don't see what's so terrible about it: If A can do it, I don't see what an instance of a couldn't? The problem is that you cannot overload on static. That is, have a two methods with the same name, one being declared static. Usually it's possible to find a different name for one of the methods to avoid overloading. That's not always the case though, for example, opDispatch. -- /Jacob Carlborg
Re: Ping qznc: Re: A little of coordination for Rosettacode
On 06/22/2013 11:53 AM, Brian Rogoff wrote: The current D code for Dining philosophers does not compile with dmd v2.063.2, the error message being dining.d(34): Error: cannot uniquely infer foreach argument types The code compiles under 32-bit (e.g. with the -m32 compiler switch) where size_t is an alias of uint. 4void eat(in uint i, in string name, Mutex[] forks) { 1) Replace that uint with size_t: void eat(in size_t i, in string name, Mutex[] forks) { 34 foreach (uint i, philo; taskPool.parallel(philosophers)) { 2) Remove that uint: foreach (i, philo; taskPool.parallel(philosophers)) { Ali
Re: Ping qznc: Re: A little of coordination for Rosettacode
Ali Çehreli: The code compiles under 32-bit (e.g. with the -m32 compiler switch) where size_t is an alias of uint. Oh, I see. I compile most of the code on a 32 bit system. I asked Walter to warn d programmers against such mistakes, and Walter closed it down. Someone else has opened the ER again... Bye, bearophile
Re: alias c=mixin(expr); disallowed, why?
On 06/22/2013 09:52 PM, Timothee Cour wrote: Is there a reason the language spec disallows this? void main(){ auto a=mixin(1);//OK alias b=a;//OK mixin(alias c=a;);//OK // alias c=mixin(a);//NG : Error: basic type expected, not mixin } No, it is arbitrary.
Re: Ping qznc: Re: A little of coordination for Rosettacode
I asked Walter to warn d programmers against such mistakes, and Walter closed it down. Someone else has opened the ER again... I meant this: http://d.puremagic.com/issues/show_bug.cgi?id=5063 In the meantime I have fixed the Rosettacode entry. Bye, bearophile
Re: alias c=mixin(expr); disallowed, why?
On Sat, Jun 22, 2013 at 2:47 PM, Timon Gehr timon.g...@gmx.ch wrote: On 06/22/2013 09:52 PM, Timothee Cour wrote: Is there a reason the language spec disallows this? void main(){ auto a=mixin(1);//OK alias b=a;//OK mixin(alias c=a;);//OK // alias c=mixin(a);//NG : Error: basic type expected, not mixin } No, it is arbitrary. that's what i thought! same with template mixin's being restricated. ... can we fix it? it makes for cleaner code.
Re: Can call static method with null reference
On 06/22/2013 10:20 PM, Jacob Carlborg wrote: On 2013-06-22 19:11, monarch_dodra wrote: I don't see what's so terrible about it: If A can do it, I don't see what an instance of a couldn't? The problem is that you cannot overload on static. That is, have a two methods with the same name, one being declared static. Usually it's possible to find a different name for one of the methods to avoid overloading. That's not always the case though, for example, opDispatch. If that is the only problem then the solution is to allow overloading on static, which is easy to do.
Re: alias c=mixin(expr); disallowed, why?
On 06/22/2013 11:51 PM, Timothee Cour wrote: On Sat, Jun 22, 2013 at 2:47 PM, Timon Gehr timon.g...@gmx.ch mailto:timon.g...@gmx.ch wrote: On 06/22/2013 09:52 PM, Timothee Cour wrote: Is there a reason the language spec disallows this? void main(){ auto a=mixin(1);//OK alias b=a;//OK mixin(alias c=a;);//OK // alias c=mixin(a);//NG : Error: basic type expected, not mixin } No, it is arbitrary. that's what i thought! same with template mixin's being restricated. ? ... can we fix it? it makes for cleaner code. It surely could be fixed if you want to spend the time hacking on DMD. I think the grammar is somewhat poorly designed in general.
Re: alias c=mixin(expr); disallowed, why?
On Sat, Jun 22, 2013 at 2:55 PM, Timon Gehr timon.g...@gmx.ch wrote: On 06/22/2013 11:51 PM, Timothee Cour wrote: On Sat, Jun 22, 2013 at 2:47 PM, Timon Gehr timon.g...@gmx.ch mailto:timon.g...@gmx.ch wrote: On 06/22/2013 09:52 PM, Timothee Cour wrote: Is there a reason the language spec disallows this? void main(){ auto a=mixin(1);//OK alias b=a;//OK mixin(alias c=a;);//OK // alias c=mixin(a);//NG : Error: basic type expected, not mixin } No, it is arbitrary. that's what i thought! same with template mixin's being restricated. ? they're restricted to declarations. I don't see the need for such restriction. ... can we fix it? it makes for cleaner code. It surely could be fixed if you want to spend the time hacking on DMD. I think the grammar is somewhat poorly designed in general.