Re: dcollections 1.0 and 2.0a beta released
On Wed, 26 May 2010 10:06:32 -0400, Bruno Medeiros brunodomedeiros+s...@com.gmail wrote: On 24/05/2010 16:45, Andrei Alexandrescu wrote: In the past I have built a C++ library that abstracted features of the OS. My goal was to make it possible to dynamically load a module that abstracted things like setting the IP address of a network interface. My modules used std::string instead of char * to lookup services to get objects that implement the interface. Big mistake. On a later version of the standard C++ runtime, the private implementation of std::string changed, so the dynamically loaded libraries crashed horribly. No change in string's interface, just the private stuff changed, but because it's a template, the code that uses it necessarily has to be aware of it. We ended up ditching the standard C++ library's version of string, and used STLPort so we could control the library. I envision this same sort of problem would be likely with D collection objects that were not used via interfaces. I see no problem retrofitting a no-interface container into a formal interface if so needed. I don't understand this discussion: isn't the reason above pretty much a dead-on hard requirement for the collections to have interfaces? Something like, for example, an interface version of the range traits? Only if you wish to have binary compatibility with dynamic libs. Such a thing isn't likely today since dynamic libs aren't very well supported in D, and even phobos or dcollections isn't a dynamic lib. And I have specifically decided not to use interfaces with ranges because that makes them reference types. Ranges work well as value types, but not well as reference types. Therefore, to use dcollections as interfaces, you must not require the range traits. -Steve
Re: Bug fix week
Don wrote: snip IMHO, one of the most important bugs to fix is actually a spec bug: 4056 Template instantiation with bare parameter not documented snip Why single out that one? This is the one that needs fixing most of all: http://d.puremagic.com/issues/show_bug.cgi?id=677 Stewart.
Re: Bug fix week
Stewart Gordon wrote: Don wrote: snip IMHO, one of the most important bugs to fix is actually a spec bug: 4056 Template instantiation with bare parameter not documented snip Why single out that one? Because it's a feature that is used in almost every non-trivial D2 program, and the spec gives no hint that it even exists. Without it, you can't even make sense of many of the Phobos docs. It's an absolute disaster for anyone taking a first look at the language -- something which we expect to happen frequently in the next few weeks.
Re: dmd 1.061 and 2.046 release
Jérôme M. Berger wrote: Ary Borenszweig wrote: Jérôme M. Berger wrote: Walter Bright wrote: snip I'm using firefox. Even on their main developer.apple.com/iphone/index.action, most of the text is light grey on white. Text is black here. But it is very thin, are you sure this isn't an anti-aliasing issue? In Windows Vista at least, anti-aliasing (whether Standard or ClearType) clearly isn't a straight average, considering that zooming out doesn't cause it to fade. AIUI, part of M$'s patent on ClearType is about how it differs from straight average anti-aliasing by colour stripes. I don't really know how it works. Nor do I know how the anti-aliasing in other OSs compares. But there, there's also the issue of system gamma vs. CSS standard gamma (well, sRGB) and whether or not the browser corrects. It's #323232 Well, that's dark grey, not light grey like Walter said he gets... Which text? In the top half, most of the text is #33 (obscure grey, according to the VisiBone naming). In the bottom half, most of the text is #66 (dark grey) or #77. (Firefox 3.6.3, examined using Firebug) Stewart.
[OT] Web font sizing (was: dmd 1.061 and 2.046 release)
Nick Sabalausky wrote: Walter Bright newshou...@digitalmars.com wrote in message news:hspj3m$1c9...@digitalmars.com... snip Web sites should avoid setting specific font sizes, so low vision users can enlarge it. I agree a lot with most of this, but any web browser that doesn't scale so-called fixed-size fonts when zooming has a broken, archaic zoom function, period. snip Correct. Indeed, here's a post I once made here http://www.facebook.com/group.php?gid=2384051749 -- 6. For partially sighted persons, there is no way to adjust text size. You say wow, they are demanding, this is something really easy to do. Yes there is a way. Just stop using Internet Exploiter and get yourself a real web browser. But still -- But you could well ask: Is it right to punish people for using broken browsers? Especially if you're going out of your way to do so by specifying font sizes in pt or px. I've always told people it just shouldn't be done. Moreover, some have sensibly pointed out that web authors shouldn't change the body text size from the default, since the user's default is the size the user is comfortable with. But maybe it's acceptable if all you're doing is compensating for the font you've chosen looking a little bigger or smaller at the same point size than the default Times New Roman. That said: - somebody might have set a different font as default in browser settings or a user stylesheet - who decreed that the factory default in all graphical browsers shall be Times New Roman, anyway? Stewart.
Re: [OT] Web font sizing
Stewart Gordon wrote: But maybe it's acceptable if all you're doing is compensating for the font you've chosen looking a little bigger or smaller at the same point size than the default Times New Roman. That said: - somebody might have set a different font as default in browser settings or a user stylesheet - who decreed that the factory default in all graphical browsers shall be Times New Roman, anyway? With style sheets, you can set the font size as larger or smaller than the default. This should be good enough. Setting fonts as pixel sizes is just wrong.
Re: To interface or not to interface
Steven Schveighoffer Wrote: On Tue, 25 May 2010 02:26:02 -0400, Kagamin s...@here.lot wrote: Recently I've hit a problem with collections in C#. Given classes class A {} class B {} And two collections CollectionA and CollectionB it's possible to concat them into an array A[]. The efficient way to do it is to use CopyTo(T[],int) method, but it accepts only array of exact collection item's type, so I had to change the CollectionB type to CollectionA. Did you mean class B : A {} ? Ah, yes. According to this page, it says that an exception could be thrown if Type T cannot be cast automatically to the type of the destination array. This implies that a destination array type to which T could automatically be cast should work. ICollectionA acoll; ICollectionB bcoll; A[] cat; ICollectionA.CopyTo(A[],int) ICollectionB.CopyTo(B[],int) - note the signature, the destination array can't be an array of supertype. There's no chance to throw an exception because the code doesn't pass type check at compile time.
Re: To interface or not to interface
ICollectionA acoll; ICollectionB bcoll; A[] cat; ICollectionA.CopyTo(A[],int) ICollectionB.CopyTo(B[],int) - note the signature, the destination array can't be an array of supertype. There's no chance to throw an exception because the code doesn't pass type check at compile time. To ease understanding: ICollectionAnimal acoll; ICollectionCat ccoll; Animal[] animals; ICollectionAnimal.CopyTo(Animal[],int) ICollectionCat.CopyTo(Cat[],int)
Re: Uniform function call syntax
On 2010-05-27 01.41, retard wrote: Wed, 26 May 2010 22:05:48 +0200, Jacob Carlborg wrote: I've asked this before, probably several times: if and when will D get the uniform function call syntax that has been talked about? Example: void foo (int i) {} 3.foo(); And please don't say it's already implemented because it isn't, I've heard that before. Are you sure you're not confusing two things. The uniform access says that client code should not be affected by a decision to implement an attribute as a field or method. -- Programming in Scala The other is a term known as extension methods. Extension methods enable you to add methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. -- http:// msdn.microsoft.com/en-us/library/bb383977.aspx This was talked about at the first D conference and the term used there was uniform/unified function call syntax. -- /Jacob Carlborg
Re: Uniform function call syntax
On 2010-05-27 01.52, Simen kjaeraas wrote: On Thu, 27 May 2010 01:41:16 +0200, retard r...@tard.com.invalid wrote: Wed, 26 May 2010 22:05:48 +0200, Jacob Carlborg wrote: I've asked this before, probably several times: if and when will D get the uniform function call syntax that has been talked about? Example: void foo (int i) {} 3.foo(); And please don't say it's already implemented because it isn't, I've heard that before. Are you sure you're not confusing two things. The uniform access says that client code should not be affected by a decision to implement an attribute as a field or method. -- Programming in Scala The other is a term known as extension methods. Extension methods enable you to add methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. -- http:// msdn.microsoft.com/en-us/library/bb383977.aspx http://s3.amazonaws.com/dconf2007/WalterAndrei.pdf Page 9. The idea is that foo(bar) may be replaced with bar.foo() and vice versa, making function calls 'uniform' in that both member functions and free functions may be called in the same manner. What he said ^ -- /Jacob Carlborg
Re: Uniform function call syntax
On 2010-05-27 07.17, Robert Jacques wrote: On Wed, 26 May 2010 16:05:48 -0400, Jacob Carlborg d...@me.com wrote: I've asked this before, probably several times: if and when will D get the uniform function call syntax that has been talked about? Example: void foo (int i) {} 3.foo(); And please don't say it's already implemented because it isn't, I've heard that before. Is your patch still current or does it need to be looked at? (http://d.puremagic.com/issues/show_bug.cgi?id=3382) 1. I assume that the line numbers in the diff is not correct anymore, don't know how sensitive that is 2. As I say in the bug report literals don't work, i.e. 3.foo();, x.foo(); works though. To make 2. work I assume additional changes need to made in the lexer and/or parser. What I've heard 2. will never work until .1 and/or 1. are not allowed anymore. -- /Jacob Carlborg
Re: container stuff
Jonathan M Davis: Well, I've never needed to do that particular operation on _any_ container, so it does strike me as weird regardless. I've basically always been looking to remove a specific element or elements or to remove the element at a specific location. You have probably missed my other answer. But I can add some more. That operation is common. You use it every time you have a container that doesn't define a deterministic order (like hash sets, hash associative arrays, and so on) and you want to process and consume its items. In such collection you can't ask to pop the last or first item because they are not defined. So you pop out one randomly. I have used it many times in my programs. Bye, bearophile
Re: container stuff
Andrei Alexandrescu: Done. removeAny was my choice as of a few months ago but I'd forgotten. I suggest to call it just pop. Bye, bearophile
Static constructors in circularly imported modules - again
There was a discussion about those a while ago that terminated with Andrei's authoritative it would be a step backward. I am not entirely convinced that there had been a step forward in the first place. Defining static construction order to be determined by the module import graph had been a half step forward. Completely disallowing static construction of circularly imported modules - a half step backward. The result is std.stdiobase and impossibility to initialize static data in mixins without resorting to lazy initialization. I can live with hacks like std.stdiobase when such are possible. What is more critical is initialization of mixins. Restating the problem: module a; mixin template Foo() { static immutable Object foo; shared static this() { foo = cast(immutable)new Object; } } module b; import a; import c; mixin Foo; module c; import a; import b; mixin Foo; In this scenario one is forced to avoid static constructors by lazily initializing foo and using some kind of synchronization, which should be absolutely unnecessary and sometimes is not tolerable. So which of the following is going to happen? 1. The current blinkered design will stay. 2. A solution will be provided before D2 is feature-freezed. Note that I am well aware of http://yosefk.com/c++fqa/ctors.html#fqa-10.12 etc, but simply disallowing static construction is not a good solution for static construction problems.
Re: container stuff
On Thu, 27 May 2010 00:20:24 -0400, Jonathan M Davis jmdavisp...@gmail.com wrote: Steven Schveighoffer wrote: Jonathan M Davis Wrote: Looks interesting overall. There is one function, however, which makes no sense to me: removeElement()/stableRemoveElement(). So, it basically removes a random element from the container? It could be quite consistent as to which element it removes from the container (it being implementation-dependent), but effectively, it removes a random element? What's the point of that? I can't remember the last time - if ever - that I wanted to remove an element from a container and I didn't care which. Or am I misunderstanding what it does? I think you are misunderstanding. Random element means you can't tell which one is removed, but it doesn't *have* to be truly random :) It most likely will be the most convenient element to remove (maybe that would be a better description). In other words, you can't expect it to always be the last element, or the first element, or the lowest element, or whatever. So essentially, I think that's what you were asking for, and I think that's what Andrei meant. -Steve I don't think that I misunderstood, but I may not have stated it well. No, the element is not _truly_ random, but it is removing an unspecified element which could be any element in the container, and is therefore random in the sense that you aren't telling it which one to remove. I've never been in a situation where it made any sense to do that. So, the function struck me as really weird. If you wanted truly random, you'd have to implement a function that actually did random number generation or whatnot to decide which element to pick, and presumably, it would be abnormal to use that here (though I think that doing so would still follow the API). So, no, removeElement() (now removeAny()) is not truly random, but it isn't deterministic from the perspective of the programmer having any clue which one will be removed, and it may or may not be deterministic from the container's perspective. OK. I think the point of removeAny is that it removes an element as fast as possible, however that can be implemented by the container. I.e. removing the back or front element may not be the fastest operation, think about something like a tree, where the fastest element to remove is probably the top element. -Steve
Re: To interface or not to interface
On Tue, 25 May 2010 23:29:34 -0400, Walter Bright newshou...@digitalmars.com wrote: Steven Schveighoffer wrote: On Mon, 24 May 2010 18:13:38 -0400, Walter Bright newshou...@digitalmars.com wrote: Steven Schveighoffer wrote: All an interface does is give an abstract representation of functions that are *already there*. Removing the interface does not remove the functions that implemented the interface. Then why do interfaces need to be part of the collection component? Why can't the user add them if he wants them? How do you add an interface to a class? Define an interface who's member functions call the class' member functions. Quoting from earlier message: Wrapping seems like it would add more overhead than just implementing the interface, especially since D's inliner has some strange restrictions. -Steve
Re: Bug fix week
Don wrote: snip IMHO, one of the most important bugs to fix is actually a spec bug: 4056 Template instantiation with bare parameter not documented snip Why single out that one? This is the one that needs fixing most of all: http://d.puremagic.com/issues/show_bug.cgi?id=677 Stewart.
Re: container stuff
bearophile wrote: Jonathan M Davis: Well, I've never needed to do that particular operation on _any_ container, so it does strike me as weird regardless. I've basically always been looking to remove a specific element or elements or to remove the element at a specific location. You have probably missed my other answer. But I can add some more. That operation is common. You use it every time you have a container that doesn't define a deterministic order (like hash sets, hash associative arrays, and so on) and you want to process and consume its items. In such collection you can't ask to pop the last or first item because they are not defined. So you pop out one randomly. I have used it many times in my programs. When is it better to do it that way, rather than just iterating over all elements, and then completely empty the container? (Just curious -- I'm having trouble thinking of a use case for this feature).
Re: container stuff
Don: When is it better to do it that way, rather than just iterating over all elements, and then completely empty the container? (Just curious -- I'm having trouble thinking of a use case for this feature). I'm having troubles understanding why two persons have troubles seeing use cases for this feature :-) Iterating over the container and then emptying the container is two operations, you have to keep in mind to empty it, while if you pop items out of it progressively you just need to keep in mind to do one thing, and you avoid forgetting the final cleaning. Also, the progressive popping out of items allows you to have a collection that is correct in every moment, there is no risk of removing two times an item, so you can pass around the data structure in any moment of this process of wearing it away. This is what you suggest (Python code): s = set([ab, bc, de]) def process_item(item): print item for item in s: process_item(item) s.clear() # removes all items But this is better, you can print the correct collection in any moment and you can't forget the final clear: s = set([ab, bc, de]) def process_item(item): print item def show_data(items): print items while s: process_item(s.pop()) show_data(s) Bye, bearophile
Re: Bug fix week
Stewart Gordon: This is the one that needs fixing most of all: http://d.puremagic.com/issues/show_bug.cgi?id=677 I don't think Walter will fix that bug. If you think that bug is important for you, then I suggest you to find other people that agree with you, and write down the specs yourself (and then maybe Walter will read your document to tell you how to fix its errors). This is the most voted bug, one of those votes is mine, but now I am not so sure Walter takes a look at the vote counts when he fixes bugs: http://d.puremagic.com/issues/show_bug.cgi?id=314 Bye, bearophile
Re: Uniform function call syntax
Wed, 26 May 2010 21:43:38 -0400, Robert Jacques wrote: On Wed, 26 May 2010 20:44:50 -0400, retard r...@tard.com.invalid wrote: Thu, 27 May 2010 01:52:32 +0200, Simen kjaeraas wrote: On Thu, 27 May 2010 01:41:16 +0200, retard r...@tard.com.invalid wrote: Wed, 26 May 2010 22:05:48 +0200, Jacob Carlborg wrote: I've asked this before, probably several times: if and when will D get the uniform function call syntax that has been talked about? Example: void foo (int i) {} 3.foo(); And please don't say it's already implemented because it isn't, I've heard that before. Are you sure you're not confusing two things. The uniform access says that client code should not be affected by a decision to implement an attribute as a field or method. -- Programming in Scala The other is a term known as extension methods. Extension methods enable you to add methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. -- http:// msdn.microsoft.com/en-us/library/bb383977.aspx http://s3.amazonaws.com/dconf2007/WalterAndrei.pdf Page 9. The idea is that foo(bar) may be replaced with bar.foo() and vice versa, making function calls 'uniform' in that both member functions and free functions may be called in the same manner. I understood what you meant. It's just that the idea was invented before in C#. I usually give attribution to (and favor the term invented by) the original innovator, not the copycat. Those two features have only few differences, for example C# requires importing the symbols first with 'using'. The proposed D feature is more careless here. Actually, C# is, if anything, the copycat. (Convergent evolution is much more likely) Extension methods were introduced in C# 3, which was released November 2007. Uniform function call syntax was discussed at D language conference in August 2007. And it's a logical extension from array 'Functions as Array Properties' which has been around since at least 2006. I've found articles of the proposed extension methods for C# already in 2004 and blog posts in 2005. Of course C# is a copycat, most of the ideas in modern programming languages were already invented 20-50 years ago. But AFAIK this feature was presented in C# context long before D reinvented it.
AAs of struct or array
I have noticed a significant speed difference between foo1 and foo2 (D2 code): import std.c.stdio: printf; int foo1(int x, int y) { static int[int[2]] cache; int[2] args = [x, y]; cache[args] = x; return x; } int foo2(int x, int y) { static struct Pair { int x, y; } static int[Pair] cache; Pair args = Pair(x, y); cache[args] = x; return x; } void main() { enum int N = 600; int tot; foreach (x; 1 .. N) foreach (y; 1 .. N) tot += foo2(x, y); // use foo1 or foo2 here printf(%d\n, tot); } Bye, bearophile
Re: Static constructors in circularly imported modules - again
On 05/27/2010 01:37 PM, Max Samukha wrote: module a; mixin template Foo() { static immutable Object foo; shared static this() { foo = cast(immutable)new Object; } } module b; import a; import c; mixin Foo; module c; import a; import b; mixin Foo; In this scenario one is forced to avoid static constructors by lazily initializing foo and using some kind of synchronization, which should be absolutely unnecessary and sometimes is not tolerable. Ok, I've just thought of a way to avoid synchronization (using __gshared for simplicity): module a; mixin template Foo() { static __gshared Object foo; // shared foo static Object tlFoo; // thread-local foo Object getFoo() { if (!tlFoo) { synchronized(lock) { if (!foo) foo = new Object; } tlFoo = foo; } return tlFoo; } } There is still unnecessary overhead of accessing and testing the thread-local variable.
Re: container stuff
bearophile wrote: Don: When is it better to do it that way, rather than just iterating over all elements, and then completely empty the container? (Just curious -- I'm having trouble thinking of a use case for this feature). I'm having troubles understanding why two persons have troubles seeing use cases for this feature :-) Iterating over the container and then emptying the container is two operations, you have to keep in mind to empty it, while if you pop items out of it progressively you just need to keep in mind to do one thing, and you avoid forgetting the final cleaning. Yes, but if I understand correctly, the only reason to have removeAny _as a primitive_ is for speed. And iterating over the container followed by a single removal is almost always going to be much faster. If, however, speed is not critical, removeAny can be a generic function -- call removeFront() if present, else call removeBack(). And your examples would work just fine with that. I'm having trouble identifying a use case where it needs to be a primitive.
Re: Static constructors in circularly imported modules - again
Max Samukha Wrote: There was a discussion about those a while ago that terminated with Andrei's authoritative it would be a step backward. I am not entirely convinced that there had been a step forward in the first place. Defining static construction order to be determined by the module import graph had been a half step forward. Completely disallowing static construction of circularly imported modules - a half step backward. The result is std.stdiobase and impossibility to initialize static data in mixins without resorting to lazy initialization. I can live with hacks like std.stdiobase when such are possible. What is more critical is initialization of mixins. Restating the problem: module a; mixin template Foo() { static immutable Object foo; shared static this() { foo = cast(immutable)new Object; } } module b; import a; import c; mixin Foo; module c; import a; import b; mixin Foo; In this scenario one is forced to avoid static constructors by lazily initializing foo and using some kind of synchronization, which should be absolutely unnecessary and sometimes is not tolerable. So which of the following is going to happen? 1. The current blinkered design will stay. 2. A solution will be provided before D2 is feature-freezed. Note that I am well aware of http://yosefk.com/c++fqa/ctors.html#fqa-10.12 etc, but simply disallowing static construction is not a good solution for static construction problems. In module b, delete the import of c. In module c, delete the import of b. Your sample code will then compile and run. It probably wouldn't do what you want though; you'll have two globals (b.foo and c.foo). I suspect what you really want is one global a.foo?
Re: std.container update
On Thu, 27 May 2010 00:36:24 -0400, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: I just implemented a singly-linked list type to illustrate the container abstraction. http://erdani.com/d/phobos/std_container.html http://erdani.com/d/phobos/container.d One interesting aspect is that SList must cooperate with Take. More details are to be found in code, but essentially SList ranges are all sentinel-terminated, which makes them right-bound. If you want to only remove a few elements from the middle of a list, you need to construct a range that spans a limited portion of the list. I encoded that by using the Take abstraction in std.range. Please let me know of how you find it. There are a few refinements and ancillary functions to define, but those are pretty clear given the rest. Well, one thing I don't like about it is that you cannot do O(1) insertion or removal. insertBefore requires O(n) complexity and insertAfter requires O(m) complexity. Removal will require O(n) complexity, even though it doesn't exist right now. Fast removal and insertion are key to having a linked list. I'd suggest modifying the range so it uses a Node ** instead, which points to the _next element of the previous node of the one currently being iterated, or _root if it's the first node in the list. -Steve
Re: std.container update
On Thu, 27 May 2010 09:23:03 -0400, Steven Schveighoffer schvei...@yahoo.com wrote: On Thu, 27 May 2010 00:36:24 -0400, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: I just implemented a singly-linked list type to illustrate the container abstraction. http://erdani.com/d/phobos/std_container.html http://erdani.com/d/phobos/container.d One interesting aspect is that SList must cooperate with Take. More details are to be found in code, but essentially SList ranges are all sentinel-terminated, which makes them right-bound. If you want to only remove a few elements from the middle of a list, you need to construct a range that spans a limited portion of the list. I encoded that by using the Take abstraction in std.range. Please let me know of how you find it. There are a few refinements and ancillary functions to define, but those are pretty clear given the rest. Well, one thing I don't like about it is that you cannot do O(1) insertion or removal. insertBefore requires O(n) complexity and insertAfter requires O(m) complexity. Removal will require O(n) complexity, even though it doesn't exist right now. Fast removal and insertion are key to having a linked list. I'd suggest modifying the range so it uses a Node ** instead, which points to the _next element of the previous node of the one currently being iterated, or _root if it's the first node in the list. In fact, I'd say that it would be critical to split the insert and remove functions to slow (O(n) or greater) versions and fast( O(lg(n) or less)) functions. Some algorithms may depend on fast insertion and removal, such as mergesort on a linked list. -Steve
Re: container stuff
On 05/27/2010 06:49 AM, Don wrote: bearophile wrote: Jonathan M Davis: Well, I've never needed to do that particular operation on _any_ container, so it does strike me as weird regardless. I've basically always been looking to remove a specific element or elements or to remove the element at a specific location. You have probably missed my other answer. But I can add some more. That operation is common. You use it every time you have a container that doesn't define a deterministic order (like hash sets, hash associative arrays, and so on) and you want to process and consume its items. In such collection you can't ask to pop the last or first item because they are not defined. So you pop out one randomly. I have used it many times in my programs. When is it better to do it that way, rather than just iterating over all elements, and then completely empty the container? (Just curious -- I'm having trouble thinking of a use case for this feature). Again, any worklist-based algorithm will remove and add work items without minding for a specific order. http://cseweb.ucsd.edu/classes/sp00/cse231/report/node12.html Andrei
Re: std.container update
On Thu, 27 May 2010 09:27:39 -0400, Steven Schveighoffer schvei...@yahoo.com wrote: On Thu, 27 May 2010 09:23:03 -0400, Steven Schveighoffer schvei...@yahoo.com wrote: On Thu, 27 May 2010 00:36:24 -0400, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: I just implemented a singly-linked list type to illustrate the container abstraction. http://erdani.com/d/phobos/std_container.html http://erdani.com/d/phobos/container.d One interesting aspect is that SList must cooperate with Take. More details are to be found in code, but essentially SList ranges are all sentinel-terminated, which makes them right-bound. If you want to only remove a few elements from the middle of a list, you need to construct a range that spans a limited portion of the list. I encoded that by using the Take abstraction in std.range. Please let me know of how you find it. There are a few refinements and ancillary functions to define, but those are pretty clear given the rest. Well, one thing I don't like about it is that you cannot do O(1) insertion or removal. insertBefore requires O(n) complexity and insertAfter requires O(m) complexity. Removal will require O(n) complexity, even though it doesn't exist right now. Fast removal and insertion are key to having a linked list. I'd suggest modifying the range so it uses a Node ** instead, which points to the _next element of the previous node of the one currently being iterated, or _root if it's the first node in the list. In fact, I'd say that it would be critical to split the insert and remove functions to slow (O(n) or greater) versions and fast( O(lg(n) or less)) functions. Some algorithms may depend on fast insertion and removal, such as mergesort on a linked list. Actualy mergesort could not be implemented without some sort of way to restructure the list without allocating new nodes, requiring knowledge of the link structure. I'm not sure it could be generic... I'll think about this a bit. -Steve
Re: std.container update
On Thu, 27 May 2010 00:36:24 -0400, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: I just implemented a singly-linked list type to illustrate the container abstraction. http://erdani.com/d/phobos/std_container.html http://erdani.com/d/phobos/container.d One interesting aspect is that SList must cooperate with Take. More details are to be found in code, but essentially SList ranges are all sentinel-terminated, which makes them right-bound. If you want to only remove a few elements from the middle of a list, you need to construct a range that spans a limited portion of the list. I encoded that by using the Take abstraction in std.range. Please let me know of how you find it. There are a few refinements and ancillary functions to define, but those are pretty clear given the rest. I have another general question in general about these collections. Ranges fix a very bad problem with iterators -- non-matching begin and end iterators. For example, passing a begin from one list and and end from another. However, all your range functions such as remove, insertBefore, etc. are called via the container type, using a range as an argument. But there can be no static verification that a range actually is part of a given container. Should there be some requirement that a container validates that a range is part of the container before performing the operation? This is the case for dcollections. In your current implementation of SList, verification seems incidental for insertBefore because you must find the previous node from the root anyways (and that will throw on enforce if it cannot find it). But insertAfter does not, so something like this will compile, run, and result in strange behavior: auto sl1 = make(SList!int, 1, 2, 3, 4, 5); // I may not have this correct, but it's not important auto sl2 = make(SList!int, 6, 7, 8, 9, 10); auto r1 = sl1[]; r1.popFront(); r1.popFront(); auto r2 = take(r1, 2); sl2.insertAfter(r2, 666); // actually inserts into sl1 -Steve
Re: Static constructors in circularly imported modules - again
On 05/27/2010 03:47 PM, Jason House wrote: In module b, delete the import of c. In module c, delete the import of b. Your sample code will then compile and run. It probably wouldn't do what you want though; you'll have two globals (b.foo and c.foo). I suspect what you really want is one global a.foo? Two distinct globals. There is a more concrete example: module QObject; class QMetaObject { ... } mixin template Q_OBJECT() { ... immutable(QMetaObject) metaObject() immutable { return staticMetaObject; } static immutable QMetaObject staticMetaObject; shared static this() { staticMetaObject = cast(immutable)QMetaObject.create!(typeof(this)); } } module a; import QObject; import b; class A : QObject { B b; mixin Q_OBJECT; } module b; import QObject; import a; class B : { A a; mixin Q_OBJECT; } When mixed in a class, Q_OBJECT, among other things, associates a global RTTI object with that class. Ideally, this object should be created at program startup. We cannot impose on the user of Q_OBJECT the requirement that a and b should not be circularly imported or that he has to manually call an initialization function etc.
Re: std.container update
On 05/27/2010 08:23 AM, Steven Schveighoffer wrote: You're making a number of great points in the four posts starting with this. Since they sort of augment one another, let me quote and answer them all here. On Thu, 27 May 2010 00:36:24 -0400, Andrei Alexandrescu seewebsiteforem...@erdani.org wrote: I just implemented a singly-linked list type to illustrate the container abstraction. http://erdani.com/d/phobos/std_container.html http://erdani.com/d/phobos/container.d Please let me know of how you find it. There are a few refinements and ancillary functions to define, but those are pretty clear given the rest. Well, one thing I don't like about it is that you cannot do O(1) insertion or removal. insertBefore requires O(n) complexity and insertAfter requires O(m) complexity. Removal will require O(n) complexity, even though it doesn't exist right now. Fast removal and insertion are key to having a linked list. I'd suggest modifying the range so it uses a Node ** instead, which points to the _next element of the previous node of the one currently being iterated, or _root if it's the first node in the list. -Steve The performance profile of SList is what one would expect for a straightforward singly-linked list implemented with nodes, pointer to root, and the such. You are making a good point that adding one 1-2 extra indirections would lead to improvements of certain primitives. There have been various experiments with STL-like slist implementations that dwell on such ideas. See e.g. http://manpages.ubuntu.com/manpages/lucid/man3/std::forward_list.3cxx.html with functions like before_begin() in addition to begin(), and also insert_after() instead of insert(). It has become clear to STL implementors that adding hidden indirections puts forward_list at a disadvantage compared to the straightforward lists against which they compete. I want to avoid that by abiding to the straight storage strategy and deal with its consequences. Second post: In fact, I'd say that it would be critical to split the insert and remove functions to slow (O(n) or greater) versions and fast( O(lg(n) or less)) functions. Some algorithms may depend on fast insertion and removal, such as mergesort on a linked list. This is a good idea, which generalizes linearRemove(). I'd suspected if there's one place to distinguish linear from better, then there ought to be more. From here we have a fork in the road: a) Tighten complexity requirements for e.g. insertBefore(Range, Stuff) and let containers that can't implement them just not have them. b) Define linearInsertBefore(Range, Stuff) etc. I'm leaning towards (a) because a list can insert virtually anywhere by only using insertAfter(Take!Range, Stuff) (which I haven't defined yet but I will, and which also takes care of the complexity issue) and insertFront(Stuff). Third post: Actualy mergesort could not be implemented without some sort of way to restructure the list without allocating new nodes, requiring knowledge of the link structure. I'm not sure it could be generic... I'll think about this a bit. You are entirely right. A mergesort that relies on link shuffling needs to have intimate knowledge of the node structure. It would most likely be a member of the list. Fourth post: I have another general question in general about these collections. Ranges fix a very bad problem with iterators -- non-matching begin and end iterators. For example, passing a begin from one list and and end from another. Right. However, all your range functions such as remove, insertBefore, etc. are called via the container type, using a range as an argument. But there can be no static verification that a range actually is part of a given container. Should there be some requirement that a container validates that a range is part of the container before performing the operation? This is the case for dcollections. In your current implementation of SList, verification seems incidental for insertBefore because you must find the previous node from the root anyways (and that will throw on enforce if it cannot find it). But insertAfter does not, so something like this will compile, run, and result in strange behavior: auto sl1 = make(SList!int, 1, 2, 3, 4, 5); // I may not have this correct, but it's not important auto sl2 = make(SList!int, 6, 7, 8, 9, 10); auto r1 = sl1[]; r1.popFront(); r1.popFront(); auto r2 = take(r1, 2); sl2.insertAfter(r2, 666); // actually inserts into sl1 It's a good question. My current view of the matter is to maximize library flexibility and versatility. Following the adage that you can build safe on fast but not the other way around, I'd go with the following philosophy: checking of range membership to their collections should be made only to the extent of ensuring memory safety. Beyond that, if efficiency is in tension with verifiability (as is the case with your example above), leave it to the programmer or the supra-structure to
Re: Bug fix week
Stewart Gordon wrote: Don wrote: snip IMHO, one of the most important bugs to fix is actually a spec bug: 4056 Template instantiation with bare parameter not documented snip Why single out that one? Because it's a feature that is used in almost every non-trivial D2 program, and the spec gives no hint that it even exists. Without it, you can't even make sense of many of the Phobos docs. It's an absolute disaster for anyone taking a first look at the language -- something which we expect to happen frequently in the next few weeks.
Re: container stuff
On 27/05/2010 06:06, Andrei Alexandrescu wrote: std.container will not contain hot-swappable components. It will contain components that could be used in some of the hot swaps. It's just one level lower than what you are discussing. That doesn't make it any more or less incompatible with dcollections. Andrei Thanks for taking the time to explain. Whatever direction D collections will take, I think we all agree that collections are the missing link in D. Once done, I am convinced that a number of D2 add on libs will grow drastically. Just can speak for myself, f.i. creating a dock /undock, tabbed MDI GUI without having a solid collection lib is not really a pleasure.. Bjoern
Re: container stuff
Don: Yes, but if I understand correctly, the only reason to have removeAny _as a primitive_ is for speed. And iterating over the container followed by a single removal is almost always going to be much faster. Most things in Python are designed to be handy first, and fast later. So I doubt performance has has any significance in this small piece of Python design. In both Python and D is pop() is useful because it allows your collection to represent coherently its decreased or increased number of items at all times (Andrei ha shown an example where you have to add and remove items continuously). Bye, bearophile
Re: To interface or not to interface
== Quote from Steven Schveighoffer (schvei...@yahoo.com)'s article On Tue, 25 May 2010 23:29:34 -0400, Walter Bright newshou...@digitalmars.com wrote: Steven Schveighoffer wrote: On Mon, 24 May 2010 18:13:38 -0400, Walter Bright newshou...@digitalmars.com wrote: Steven Schveighoffer wrote: All an interface does is give an abstract representation of functions that are *already there*. Removing the interface does not remove the functions that implemented the interface. Then why do interfaces need to be part of the collection component? Why can't the user add them if he wants them? How do you add an interface to a class? Define an interface who's member functions call the class' member functions. Quoting from earlier message: Wrapping seems like it would add more overhead than just implementing the interface, especially since D's inliner has some strange restrictions. -Steve I think the main problem is that adding an interface post-hoc on the user's side is a cumbersome error-prone process. This problem has been avoided quite elegantly by Go by the way, which allows interfaces to be applied to all types that conform without requiring inheritance (can't resist to mention that I proposed this exact approach some years ago (long before Go was released) in this news group ;-) ). cheers Martin
Re: Static constructors in circularly imported modules - again
On 2010-05-27 09:57:30 -0400, Max Samukha spam...@d-coding.com said: We cannot impose on the user of Q_OBJECT the requirement that a and b should not be circularly imported or that he has to manually call an initialization function etc. Just a small note... In the D/Objective-C bridge, I've resorted to lazy initialization for this kind of thing. This way there is no module constructors and circular imports work as expected. But it isn't thread-safe, and I expect it would be a pain to make lazy initialization thread-safe, although I haven't tried yet. -- Michel Fortin michel.for...@michelf.com http://michelf.com/
Re: std.container update
== Quote from Andrei Alexandrescu (seewebsiteforem...@erdani.org)'s article: I just implemented a singly-linked list type to illustrate the container abstraction. http://erdani.com/d/phobos/std_container.html http://erdani.com/d/phobos/container.d [...] Please let me know of how you find it. One thing worries me a bit, but may be based on a misunderstanding of how D's GC works. In dup, you allocate all the nodes at once as an array and then go through them one by one setting their payload_ and next_ values to make the list. My worry is that the array is allocated as a single block and (presumably) GC'd as a single block. If I copy a 1000 element list and then remove 999 elements from the front using removeFront(), won't I end up leaking memory for the first 999 nodes? Cheers, Pillsy
Re: Static constructors in circularly imported modules - again
On 27.05.2010 18:38, Michel Fortin wrote: But it isn't thread-safe, and I expect it would be a pain to make lazy initialization thread-safe, although I haven't tried yet. That has been the very point of this thread (no pun). In my other post I supplied a hack that uses two variables, shared and TLS, to reduce the cost of accessing the global. Not ideal at all but at least it requires synchronization only during the first access.
Re: container stuff
On Thu, May 27, 2010 at 5:44 AM, Don nos...@nospam.com wrote: bearophile wrote: Don: When is it better to do it that way, rather than just iterating over all elements, and then completely empty the container? (Just curious -- I'm having trouble thinking of a use case for this feature). I'm having troubles understanding why two persons have troubles seeing use cases for this feature :-) Iterating over the container and then emptying the container is two operations, you have to keep in mind to empty it, while if you pop items out of it progressively you just need to keep in mind to do one thing, and you avoid forgetting the final cleaning. Yes, but if I understand correctly, the only reason to have removeAny _as a primitive_ is for speed. And iterating over the container followed by a single removal is almost always going to be much faster. If, however, speed is not critical, removeAny can be a generic function -- call removeFront() if present, else call removeBack(). And your examples would work just fine with that. I'm having trouble identifying a use case where it needs to be a primitive. Think of a graph algorithm where you add all the nodes you know about to a Set. Pop one, process it, and then add any nodes it's connected to that you haven't seen yet back to the Set. Repeat until nothing left to pop. --bb
Re: Bug fix week
bearophile wrote: Stewart Gordon: This is the one that needs fixing most of all: http://d.puremagic.com/issues/show_bug.cgi?id=677 I don't think Walter will fix that bug. So you suspect that he's going to leave D until the end of time as a language that cannot be implemented by third parties because the spec is incomplete? If you think that bug is important for you, And if I don't _think_ that it's important for _me_, but _know_ that it's important to _the community_, then what? then I suggest you to find other people that agree with you, and write down the specs yourself (and then maybe Walter will read your document to tell you how to fix its errors). By errors, do you mean: * obvious typos? * bits that don't coincide with how DMD does things? * bits that don't coincide with how Walter intended it? * bits that don't coincide with Walter's current opinion? * something else? This is the most voted bug, one of those votes is mine, but now I am not so sure Walter takes a look at the vote counts when he fixes bugs: snip So I'd suspected. But then, what _does_ Walter use the votes for? After all, he advertised the feature http://www.digitalmars.com/d/archives/digitalmars/D/announce/Vote_for_your_least_favorite_bug_s_14136.html Stewart.
Re: std.container update
On 05/27/2010 11:01 AM, Pillsy wrote: == Quote from Andrei Alexandrescu (seewebsiteforem...@erdani.org)'s article: I just implemented a singly-linked list type to illustrate the container abstraction. http://erdani.com/d/phobos/std_container.html http://erdani.com/d/phobos/container.d [...] Please let me know of how you find it. One thing worries me a bit, but may be based on a misunderstanding of how D's GC works. In dup, you allocate all the nodes at once as an array and then go through them one by one setting their payload_ and next_ values to make the list. My worry is that the array is allocated as a single block and (presumably) GC'd as a single block. If I copy a 1000 element list and then remove 999 elements from the front using removeFront(), won't I end up leaking memory for the first 999 nodes? There are indeed tradeoffs associated with allocation of nodes that way. Technically that's not a leak, but indeed the entire block will stay put for as long as at least one node in it it's used. One improvement would be to put removed nodes in a static freelist to be used by all SLists of the same type in the current thread. In that case, remove becomes unstable. I think I hastened a bit with that optimization, it's debatable and detracts from the main point of the discussion. Andrei
Re: AAs of struct or array
bearophile wrote: I have noticed a significant speed difference between foo1 and foo2 (D2 code): import std.c.stdio: printf; int foo1(int x, int y) { static int[int[2]] cache; int[2] args = [x, y]; cache[args] = x; Most of it comes from the use of that temporary. -O doesn't help either. This makes foo1 only slightly slower than foo2: // int[2] args = [x, y]; cache[[x, y]] = x; return x; } int foo2(int x, int y) { static struct Pair { int x, y; } static int[Pair] cache; Pair args = Pair(x, y); cache[args] = x; return x; } void main() { enum int N = 600; int tot; foreach (x; 1 .. N) foreach (y; 1 .. N) tot += foo2(x, y); // use foo1 or foo2 here printf(%d\n, tot); } Bye, bearophile Ali
Re: std.container update
Another update: http://erdani.com/d/phobos/std_container.html http://erdani.com/d/phobos/container.d I simplified the implementation (no more array allocation etc.), eliminated replace() and insertBefore() after convincing myself they are not a good fit for lists, and added linearRemove(Take!Range). Take!Range seems to be the secret recipe for an enjoyable SList experience. I'll follow up later with an Array sample implementation. Then on the radar are an associative container (probably a straight hash or a binary tree) and then TightSList and TightArray which use deterministic storage management. I figured out a lot of stuff, and it seems to settle together quite nicely. Andrei
Re: AAs of struct or array
On 05/27/2010 02:33 PM, bearophile wrote: I have noticed a significant speed difference between foo1 and foo2 (D2 code): import std.c.stdio: printf; int foo1(int x, int y) { static int[int[2]] cache; int[2] args = [x, y]; cache[args] = x; return x; } int foo2(int x, int y) { static struct Pair { int x, y; } static int[Pair] cache; Pair args = Pair(x, y); cache[args] = x; return x; } void main() { enum int N = 600; int tot; foreach (x; 1 .. N) foreach (y; 1 .. N) tot += foo2(x, y); // use foo1 or foo2 here printf(%d\n, tot); } Bye, bearophile On my machine, foo1 takes around 9 times longer. Why is this?
Re: Bug fix week
Stewart Gordon wrote: bearophile wrote: Stewart Gordon: This is the one that needs fixing most of all: http://d.puremagic.com/issues/show_bug.cgi?id=677 I don't think Walter will fix that bug. So you suspect that he's going to leave D until the end of time as a language that cannot be implemented by third parties because the spec is incomplete? Bearophile seems to always be very pessimistic, for some reason. This is the most voted bug, one of those votes is mine, but now I am not so sure Walter takes a look at the vote counts when he fixes bugs: snip So I'd suspected. But then, what _does_ Walter use the votes for? After all, he advertised the feature http://www.digitalmars.com/d/archives/digitalmars/D/announce/Vote_for_your_least_favorite_bug_s_14136.html The situation is a little more complex than bearophile thinks. For the last six months or so, Walter has concentrated on making sure that all of the examples in TDPL will work correctly. This has involved implementing all of the new features. Most of the bugs which were fixed were submitted patches (though often Walter had to modify the patches). Votes however are definitely not ignored. If you search bugzilla, you'll find that there are 86 closed bugs which still have votes for them! Compared with 228 open bugs. So the votes themeselves are far from up-to-date.
Re: Bug fix week
On Thu, 27 May 2010 15:34:38 -0400, Don nos...@nospam.com wrote: Votes however are definitely not ignored. If you search bugzilla, you'll find that there are 86 closed bugs which still have votes for them! Compared with 228 open bugs. So the votes themeselves are far from up-to-date. Indeed, it would be nice if bugzilla reminded you that you have votes for closed bugs. Every time I go to vote for a bug, I remove my votes from any closed bugs (which are obvious with the strikethrough text). But I don't notice that until I go to vote for one. If it reminded me every time I logged in that I have votes for closed bugs, then I might pay better attention. -Steve
Re: Bug fix week
Don wrote: snip The situation is a little more complex than bearophile thinks. For the last six months or so, Walter has concentrated on making sure that all of the examples in TDPL will work correctly. This has involved implementing all of the new features. Most of the bugs which were fixed were submitted patches (though often Walter had to modify the patches). Votes however are definitely not ignored. If you search bugzilla, you'll find that there are 86 closed bugs which still have votes for them! Compared with 228 open bugs. So the votes themeselves are far from up-to-date. What search, exactly, did you do to come up with those figures? I get: Status: UNCONFIRMED, NEW, ASSIGNED, REOPENED Votes: 1 gives 257 Status: UNCONFIRMED, NEW, ASSIGNED, REOPENED Votes: 2 gives 83 Status: RESOLVED, VERIFIED, CLOSED Votes: 1 gives 64 Status: RESOLVED, VERIFIED, CLOSED Votes: 2 gives 21 I'd be amazed if there's been that much change in the last hour. Peculiarly, nothing with a WONTFIX resolution has any votes. Stewart.
Re: AAs of struct or array
Ali Ãehreli: Most of it comes from the use of that temporary. -O doesn't help either. Right. I will probably put this in Bugzilla, even if it's a low priority thing. Bye, bearophile
Method hiding
While answering to Larry Luther in a long thread in D.learn: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D.learnarticle_id=19913 I have found an interesting difference that I didn't know between Java and D. Here I have reduced the test cases: // Java code class A { void foo(A a) {} } class B extends A { void foo(B b) {} public static void main(String[] args) { A a = new A(); B b = new B(); b.foo(a); } } // D2 code class A { void foo(A a) {} } class B : A { void foo(B b) {} } void main() { A a = new A; B b = new B; b.foo(a);// comment this out and use warnings } If you comment out the last line in the D2 code, and you use warnings, DMD tells you at compile time: test.d(5): Error: class test.B test.A.foo(A a) is hidden by B If you uncomment that line DMD shows: test.d(12): Error: function test.B.foo (B b) is not callable using argument types (A) test.d(12): Error: cannot implicitly convert expression (a) of type test.A to test.B While the Java code compiles and runs with no errors. It seems in D the B.foo() hides A.foo() even if there is no overriding at all here. The presence of that warning tells me this is not an implementation bug, D is designed this way on purpose. But what is the rationale behind this difference (that at best will puzzle Java programmers trying to use D)? Bye, bearophile
Re: Method hiding
On Thu, 27 May 2010 17:00:08 -0400, bearophile bearophileh...@lycos.com wrote: While answering to Larry Luther in a long thread in D.learn: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D.learnarticle_id=19913 I have found an interesting difference that I didn't know between Java and D. Here I have reduced the test cases: // Java code class A { void foo(A a) {} } class B extends A { void foo(B b) {} public static void main(String[] args) { A a = new A(); B b = new B(); b.foo(a); } } // D2 code class A { void foo(A a) {} } class B : A { void foo(B b) {} } void main() { A a = new A; B b = new B; b.foo(a);// comment this out and use warnings } If you comment out the last line in the D2 code, and you use warnings, DMD tells you at compile time: test.d(5): Error: class test.B test.A.foo(A a) is hidden by B If you uncomment that line DMD shows: test.d(12): Error: function test.B.foo (B b) is not callable using argument types (A) test.d(12): Error: cannot implicitly convert expression (a) of type test.A to test.B While the Java code compiles and runs with no errors. It seems in D the B.foo() hides A.foo() even if there is no overriding at all here. The presence of that warning tells me this is not an implementation bug, D is designed this way on purpose. But what is the rationale behind this difference (that at best will puzzle Java programmers trying to use D)? This is actually the first question I posted on this newsgroup in 2007. It's called method hijacking, look for it on the D website for a thorough explanation. Note that this is actually the default behavior in C++ (I didn't know until I asked the question and tried it, it's pretty obscure). But the behavior is overridable, you can do this: class B : A { alias A.foo foo; void foo(A a) {} } Which means also look at A for resolving foo. However, doing this may lead to further issues. I think if you had a class C that derived from B, calling B.foo(c) would result in an ambiguity without a cast. -Steve
Re: Bug fix week
Stewart Gordon wrote: Don wrote: snip The situation is a little more complex than bearophile thinks. For the last six months or so, Walter has concentrated on making sure that all of the examples in TDPL will work correctly. This has involved implementing all of the new features. Most of the bugs which were fixed were submitted patches (though often Walter had to modify the patches). Votes however are definitely not ignored. If you search bugzilla, you'll find that there are 86 closed bugs which still have votes for them! Compared with 228 open bugs. So the votes themeselves are far from up-to-date. What search, exactly, did you do to come up with those figures? I get: Status: UNCONFIRMED, NEW, ASSIGNED, REOPENED Votes: 1 gives 257 I'd be amazed if there's been that much change in the last hour. Figured it out -- I did my search using Deskzilla. Although it updates its local database very frequently, it turns out that it doesn't update the votes very often at all. So I was using stale vote figures. Peculiarly, nothing with a WONTFIX resolution has any votes. I think hardly anything has ever been closed with WONTFIX.
Re: Method hiding
Steven Schveighoffer: This is actually the first question I posted on this newsgroup in 2007. I am very late then, sorry for not asking this is D.learn. It's called method hijacking, look for it on the D website for a thorough explanation. Note that this is actually the default behavior in C++ (I didn't know until I asked the question and tried it, it's pretty obscure). I have read this, about in the middle: http://www.digitalmars.com/d/2.0/hijack.html Thank you for the explanations and thanks to Walter for that page. I vaguely remember reading that page, but I did remember it only about free functions. I appreciate D design here :-) But the behavior is overridable, you can do this: class B : A { alias A.foo foo; void foo(A a) {} } Which means also look at A for resolving foo. OK. However, doing this may lead to further issues. I think if you had a class C that derived from B, calling B.foo(c) would result in an ambiguity without a cast. I will experiment some about this. Thank you and bye, bearophile
Bug: compiler crash when using module name twice
I'm very new to D and misused the module identifier, I thought it would be the namespace/package name. The dmd compiler v2.046 produces correct output (Error: module test from file xxx.d conflicts with another module test from file yyy.d), if multiple placement of same module identifier are in the root of the project, however it crashes, when the files are in a subfolder and does not display a proper error message. The output is: Assertion failure: 'mprev' on line 641 in file 'module.c' Test case: --main.d-- import std.stdio; import folder.File1; import folder.File2; int main(char[][] args) { writefln(file2); return 0; } --folder\File1.d-- module folder; const char[] file1 = File1; --folder\File2.d-- module folder; const char[] file2 = File2; Used Code::Blocks.
Re: Method hiding
Steven Schveighoffer: However, doing this may lead to further issues. I think if you had a class C that derived from B, calling B.foo(c) would result in an ambiguity without a cast. This is D code: import std.c.stdio: puts; class A { void foo(A a) { puts(A.foo); } } class B : A { alias A.foo foo; void foo(B b) { puts(B.foo); } } class C : B {} void main() { A a = new A(); B b = new B(); C c = new C(); b.foo(a); // Prints: A.foo b.foo(c); // Prints: B.foo } A Java translation: class A { void foo(A a) { System.out.println(A.foo); } } class B extends A { void foo(B b) { System.out.println(B.foo); } } class C extends B { public static void main(String[] args) { A a = new A(); B b = new B(); C c = new C(); b.foo(a); // Prints: A.foo b.foo(c); // Prints: B.foo } } This time they both call the same methods, b.foo(c) calls B.foo(B), probably because C is closer to B than A in the hierarchy :-) In normal programs I'd like to avoid writing this code. Bye, bearophile
Re: Bug fix week
Don wrote: Stewart Gordon wrote: snip Peculiarly, nothing with a WONTFIX resolution has any votes. I think hardly anything has ever been closed with WONTFIX. I get 61 as I look. At the moment, about 7.5% of bugs filed here have any votes, so I'm not sure that 61 counts as hardly anything. Stewart.
Re: Bug fix week
Steven Schveighoffer wrote: snip Indeed, it would be nice if bugzilla reminded you that you have votes for closed bugs. Every time I go to vote for a bug, I remove my votes from any closed bugs (which are obvious with the strikethrough text). But I don't notice that until I go to vote for one. If it reminded me every time I logged in that I have votes for closed bugs, then I might pay better attention. Why do you feel the need to remove your votes from closed bugs when you're not about to place one on another bug? This has been discussed extensively on Mozilla's own bugzilla: https://bugzilla.mozilla.org/show_bug.cgi?id=27553 Stewart.
Re: Bug: compiler crash when using module name twice
Matthias wrote: I'm very new to D and misused the module identifier, I thought it would be the namespace/package name. The dmd compiler v2.046 produces correct output (Error: module test from file xxx.d conflicts with another module test from file yyy.d), if multiple placement of same module identifier are in the root of the project, however it crashes, when the files are in a subfolder and does not display a proper error message. Ouch! I hate it when newbies hit compiler crashes. I've created a bug report: http://d.puremagic.com/issues/show_bug.cgi?id=4242 Hope to create a patch for it in the next few days.
Re: Bug fix week
Steven Schveighoffer wrote: On Thu, 27 May 2010 15:34:38 -0400, Don nos...@nospam.com wrote: Votes however are definitely not ignored. If you search bugzilla, you'll find that there are 86 closed bugs which still have votes for them! Compared with 228 open bugs. So the votes themeselves are far from up-to-date. Indeed, it would be nice if bugzilla reminded you that you have votes for closed bugs. Every time I go to vote for a bug, I remove my votes from any closed bugs (which are obvious with the strikethrough text). But I don't notice that until I go to vote for one. If it reminded me every time I logged in that I have votes for closed bugs, then I might pay better attention. -Steve What is the purpose of votes for closed bugs anyway? Should they not just get removed automatically?
Re: Bug fix week
Lutger wrote: Steven Schveighoffer wrote: On Thu, 27 May 2010 15:34:38 -0400, Don nos...@nospam.com wrote: Votes however are definitely not ignored. If you search bugzilla, you'll find that there are 86 closed bugs which still have votes for them! Compared with 228 open bugs. So the votes themeselves are far from up-to-date. Indeed, it would be nice if bugzilla reminded you that you have votes for closed bugs. Every time I go to vote for a bug, I remove my votes from any closed bugs (which are obvious with the strikethrough text). But I don't notice that until I go to vote for one. If it reminded me every time I logged in that I have votes for closed bugs, then I might pay better attention. -Steve What is the purpose of votes for closed bugs anyway? Should they not just get removed automatically? The bug might get reopened?
Re: Bug fix week
On Thu, 27 May 2010 18:09:48 -0400, Stewart Gordon smjg_1...@yahoo.com wrote: Steven Schveighoffer wrote: snip Indeed, it would be nice if bugzilla reminded you that you have votes for closed bugs. Every time I go to vote for a bug, I remove my votes from any closed bugs (which are obvious with the strikethrough text). But I don't notice that until I go to vote for one. If it reminded me every time I logged in that I have votes for closed bugs, then I might pay better attention. Why do you feel the need to remove your votes from closed bugs when you're not about to place one on another bug? This has been discussed extensively on Mozilla's own bugzilla: https://bugzilla.mozilla.org/show_bug.cgi?id=27553 I don't feel like pouring through a bugzilla discussion, but the reason is because I may have gone to vote for an issue, but found I was out of votes, and I want to keep my existing ones (or I had to cancel another bug vote in order to vote for the new one). At a later time when one of my voted-for bugs gets resolved, then I can vote for the issue I couldn't vote on, or removed my vote from. To this end, if bugzilla could remember bugs I unofficially voted for, that would be good too :) -Steve
Re: Bug fix week
Lutger wrote: snip What is the purpose of votes for closed bugs anyway? Should they not just get removed automatically? On top of the reasons linked to in my previous reply: - Many of us would probably like to be able to see which bugs they voted for have recently been fixed. - Resolving a bug would reset its vote count to zero. And so if it's reopened, voting would have to start again from scratch. - As such, an unscrupulous person could remove all votes from a bug just by marking it resolved. https://bugzilla.mozilla.org/show_bug.cgi?id=308505 Stewart.
Re: Bug: compiler crash when using module name twice
Don: Ouch! I hate it when newbies hit compiler crashes. This happens often. People that have more experience in D use it in the way it is meant to be used, so they follow the normal usage patterns, that are often tested enough (or have already known bugs). But newbies sometimes use D features in ways they where not meant to be used, so they go out of the well walked down footpath (I don't know how this is written in English), so they can often find bugs. Bye, bearophile
[OT] Votes on resolved bugs (was: Bug fix week)
Steven Schveighoffer wrote: snip I don't feel like pouring through a bugzilla discussion, but the reason is because I may have gone to vote for an issue, but found I was out of votes, and I want to keep my existing ones (or I had to cancel another bug vote in order to vote for the new one). At a later time when one of my voted-for bugs gets resolved, then I can vote for the issue I couldn't vote on, or removed my vote from. The best way to deal with that, IMO, would be for the bugmail to include a note like You have voted for this bug when the bug is resolved. If it were done by an alert when you log in, either it would lose its effect or you would have to waste time checking the list to see whether it's just the same bug(s) that you've deliberately left your vote on as before. Stewart.
Re: Bug: compiler crash when using module name twice
On Thu, 27 May 2010 18:32:34 -0400, bearophile bearophileh...@lycos.com wrote: out of the well walked down footpath (I don't know how this is written in English) off the well beaten path :) -Steve
Re: std.container update
I take it that Array is basically supposed to be std.container's version of C++'s vector or Java's ArrayList? If so, I would suggest that Array is not the best of names in that it would become very easy to confuse it with built-in arrays when discussing them (particularly in verbal communication where you can't see the capital A). Personally, I would have just gone with Vector, since it's a fairly standard name for that sort of container and wouldn't be confused with anything else. If you really want Array, that's fine - it should be clear enough when it's in code - but I would think that talking about it could easily be confusing enough that it wouldn't be the best of names. - Jonathan M Davis
Re: std.container update
Jonathan M Davis jmdavisp...@gmail.com wrote: wouldn't be confused with anything else. If you really want Array, that's Personally, I would have just gone with Vector, since it's a fairly standard name for that sort of container and wouldn't be confused with anything else. I take it you don't work in simulation or games, then? Don't do much linear algebra? While I understand the reasoning for it, I dislike the name vector for arrays. A vector to me, is a geometric object with a length and magnitude, not a random collection of whatevers. -- Simen
Re: AAs of struct or array
http://d.puremagic.com/issues/show_bug.cgi?id=4244
Re: std.container update
On 05/27/2010 06:28 PM, Jonathan M Davis wrote: I take it that Array is basically supposed to be std.container's version of C++'s vector or Java's ArrayList? If so, I would suggest that Array is not the best of names in that it would become very easy to confuse it with built-in arrays when discussing them (particularly in verbal communication where you can't see the capital A). Personally, I would have just gone with Vector, since it's a fairly standard name for that sort of container and wouldn't be confused with anything else. If you really want Array, that's fine - it should be clear enough when it's in code - but I would think that talking about it could easily be confusing enough that it wouldn't be the best of names. - Jonathan M Davis Good point. Other opinions? Andrei
std.container update - now Array is in
http://erdani.com/d/phobos/std_container.html http://erdani.com/d/phobos/container.d I defined Array as a straightforward implementation of the homonym abstraction. There are a few imperfect corners, but by and large I'm starting to believe it's becoming possible to write certain cross-container codes. Andrei
Shared Class Variables
Evening. I'm having a bit of a problem and I'm hoping someone can help. I'm trying to create a class that is shared across threads. The only purpose of this class is to write data to somewhere, though currently a file. A single-threaded version of this works fine, however I can't seem to get the code to work correctly when dealing with multiple threads. I've gotten sharing issues, compilation issues trying to figure out how to use a shared class correctly, and currently an exception occurring during class finalization. So, my question is, what is the correct way to do this? Would a class work or would a struct be better? Perhaps a singleton? Thanks. Casey
Re: Shared Class Variables
Hello sybrandy, Evening. I'm having a bit of a problem and I'm hoping someone can help. I'm trying to create a class that is shared across threads. The only purpose of this class is to write data to somewhere, though currently a file. A single-threaded version of this works fine, however I can't seem to get the code to work correctly when dealing with multiple threads. I've gotten sharing issues, compilation issues trying to figure out how to use a shared class correctly, and currently an exception occurring during class finalization. So, my question is, what is the correct way to do this? Would a class work or would a struct be better? Perhaps a singleton? I don't know much about threading but I do know that D1 vs. D2 (you didn't say what version) makes a big difference. For example, in D2 globals are thread local by default where as in D1 they are not. Thanks. Casey -- ... IXOYE
Re: std.container update
Andrei Alexandrescu, el 27 de mayo a las 20:06 me escribiste: On 05/27/2010 06:28 PM, Jonathan M Davis wrote: I take it that Array is basically supposed to be std.container's version of C++'s vector or Java's ArrayList? If so, I would suggest that Array is not the best of names in that it would become very easy to confuse it with built-in arrays when discussing them (particularly in verbal communication where you can't see the capital A). Personally, I would have just gone with Vector, since it's a fairly standard name for that sort of container and wouldn't be confused with anything else. If you really want Array, that's fine - it should be clear enough when it's in code - but I would think that talking about it could easily be confusing enough that it wouldn't be the best of names. - Jonathan M Davis Good point. Other opinions? I always thought vector was a bad name choice in C++, I had that word associated with what C++ calls a valarray (a physics vector). I agree that Array is too generic for D, though, and unfortunately I don't have a better suggestion, but you asked for other opinions ;) BTW, what would be the point of an array/vector when you have built-in arrays? If built-in arrays would be syntax sugar for a real library type, like AAs, I can see as a good option using Array for that type, since built-in arrays and the library Array would be the same thing. -- Leandro Lucarella (AKA luca) http://llucax.com.ar/ -- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) -- DETIENEN A PADRE, MADRE, TIOS Y ABUELOS: TODOS DEPRAVADOS -- Crónica TV
Re: std.container update - now Array is in
On 2010-05-27 21:08:29 -0400, Andrei Alexandrescu seewebsiteforem...@erdani.org said: http://erdani.com/d/phobos/std_container.html http://erdani.com/d/phobos/container.d I defined Array as a straightforward implementation of the homonym abstraction. There are a few imperfect corners, but by and large I'm starting to believe it's becoming possible to write certain cross-container codes. I don't get that: @property void reserve(size_t e) Why is reserve a property? You want it called like that? array.reserve = 10; I'm sure it's just an oversight. -- Michel Fortin michel.for...@michelf.com http://michelf.com/
Re: std.container update - now Array is in
On 05/27/2010 09:27 PM, Michel Fortin wrote: On 2010-05-27 21:08:29 -0400, Andrei Alexandrescu seewebsiteforem...@erdani.org said: http://erdani.com/d/phobos/std_container.html http://erdani.com/d/phobos/container.d I defined Array as a straightforward implementation of the homonym abstraction. There are a few imperfect corners, but by and large I'm starting to believe it's becoming possible to write certain cross-container codes. I don't get that: @property void reserve(size_t e) Why is reserve a property? You want it called like that? array.reserve = 10; I'm sure it's just an oversight. Sorry, fixed now. Andrei
Re: std.container update
On 05/27/2010 08:42 PM, Leandro Lucarella wrote: Andrei Alexandrescu, el 27 de mayo a las 20:06 me escribiste: On 05/27/2010 06:28 PM, Jonathan M Davis wrote: I take it that Array is basically supposed to be std.container's version of C++'s vector or Java's ArrayList? If so, I would suggest that Array is not the best of names in that it would become very easy to confuse it with built-in arrays when discussing them (particularly in verbal communication where you can't see the capital A). Personally, I would have just gone with Vector, since it's a fairly standard name for that sort of container and wouldn't be confused with anything else. If you really want Array, that's fine - it should be clear enough when it's in code - but I would think that talking about it could easily be confusing enough that it wouldn't be the best of names. - Jonathan M Davis Good point. Other opinions? I always thought vector was a bad name choice in C++, I had that word associated with what C++ calls a valarray (a physics vector). I agree that Array is too generic for D, though, and unfortunately I don't have a better suggestion, but you asked for other opinions ;) BTW, what would be the point of an array/vector when you have built-in arrays? If built-in arrays would be syntax sugar for a real library type, like AAs, I can see as a good option using Array for that type, since built-in arrays and the library Array would be the same thing. This is a good question. The relationship between Array and T[] is simple: * Array is a compliant container so it is a reference type * T[] is Array's range With built-in associative arrays the question becomes even more interesting because the associative array _is_ already a reference type. So Walter and I agreed to make built-in associative arrays just compliant std.container objects, with three differences: * AssocArray lives in object.di for various reasons * The compiler translates the type name V[K] as AssocArray!(K, V) * The compiler translates associative array literals into associative array objects Other than that... an associative array will be just one of the growing offering of collections in std.container. And I think that's the way it should be. Andrei
problem with reduce on array of Tuples
The following code fails to compile: double sim(Document doc, string query) { alias Tuple!(double, wij, double, wiq) Weights; Document q = Document.fromString(query); Weights[] wi; foreach (s; StrFilt(query)) wi ~= Weights(doc.termFreq(s) * invDocFreq(s), q.termFreq (s) * invDocFreq(s)); return reduce!((double acc, Weights w) { return acc + 0; /*w.wij * w.wiq;*/ })(0.0, wi) / (sqrt(reduce!((double acc, Weights w) { return acc + 0; / *sqr(w.wij);*/ })(0.0, wi) * sqrt(reduce!((double acc, Weights w) { return acc + 0; / *sqr(w.wiq);*/ }(0.0, wi); } and DMD 2.046 shows the following messages: ir.d(119): Error: delegate std.algorithm.__dgliteral3 cannot access frame of fun ction __dgliteral3 ir.d(232): Error: template instance ir.Index.sim.Reduce!(delegate double(double acc, Tuple!(double,wij,double,wiq) w) { return acc + 0; } ) error instantiating ir.d(119):instantiated from here: reduce!(delegate double (double acc, Tu ple!(double,wij,double,wiq) w) { return acc + 0; } ) Is it my fault because of some misunderstanding or other error, or should I report it as a bug in compiler/library? The same function compiled well with reduce on StrFilt(query) instead of Weights. I attach the full source. begin 644 ir.d M:6UP;W)T('-T9YS=1I;SL-FEM]R=!S=0NW1R:6YG.PT*:6UP;W)T M('-T9YC;VYV.PT*:6UP;W)T('-T9YF:6QE.PT*:6UP;W)T('-T9YM871H M.PT*:6UP;W)T('-T9YA;=OFET:T[#0II;7!OG0@W1D+G1Y5C;VYS M.PT*#0I4('-QBA4*2A4('@I#0I[#0H)F5T=7)N('@@*B!X.PT*?0T*#0IC M;%SR!3='):6QT#0I[#0H)W1A=EC()O;VQ;W1R:6YG72!PF5PSL- M@T*7-T871I8R!T:ES*D-@E[#0H)69OF5A8V@@*'-Tc...@6r`b(BP@ M(F$B+`B=AE(BP@(G=H870B+`B8GDB+`B;V8B+`B86YD(BP@(F]R(BP@ M(G1O(BP@(F9R;VTB+`B9\B+`B65S(BP@(FYO(BP@(FYO=(L()B=70B M+`B:70B+`B:6XB+`B:2(L()Y;W4B+`B:4B+`BVAE(BP@(G1H97DB M+`B86TB(%TI#0H)7L-@D)7!R97!S6W-TET@/2!TG5E.PT*0E]#0H) M?0T*#0H)W1A=EC(]P0V%L;AS=')I;F@;EN92D-@E[#0H)7)E='5R M;B`N9FEL=5R(2...@h82d@R!R971Uf...@82`a:6X@')E',[('TI*'-P;ET M*QI;F4N=]L;W=EBYTb...@b82uz(BP@(B`B+`B8R(I+G-TFEP*2D[#0H) M?0T*?0T*#0IC;%SR!$;V-U;65N=`T*PT*7-TFEN9R!F:6QE;F%M93L- M@EU:6YT('=OF1S.PT*75I;G1;W1R:6YG72!FF5QSL-@EU:6YT(UA M$9R97$[#0H)#0H)=F]I9!A91,:6YE*'-TFEN9R!L:6YE*0T*7L-@D) M9F]R96%C:`h=v]r...@4w1r1fel=AL:6YE*2D-@D)PT*0D)*RMFF5Q MUMW;W)D73L-@D)?0T*7T-@T*79O:6...@8v%l8tua$9R97$H*0T*7L- M@D);6%X1G)E2`](UI;E!OR$H(F$@/B!B(BDH9G)E7,N=F%L=65S*5LP M73L-@E]#0H-@ES=%T:6,@1]C=6UE;g...@9g)O;49I;4HW1R:6YG(9I M;5N86UE*0T*7L-@D)1]C=6UE;g...@9]C(#T@;F5W($1O8W5M96YT.PT* M0ED;V,N9FEL96YA;64@/2!F:6QE;F%M93L-@D)875T;R!F:6QE(#T@;F5W M($9I;4H9FEL96YA;64L()R(BD[#0H)69OF5A8V@@*QI;F4[(9I;4N M8GE,:6YE*0T*0E[#0H)0ED;V,N861D3EN92AT;R%S=')I;FH;EN92DI M.PT*0E]#0H)61O8RYC86QC36%X1G)E3L-@D)F5T=7)N(1O8SL-@E] M#0H)#0H)W1A=EC($1O8W5M96YT(9R;VU3=')I;FHW1R:6YG('-TBD- M@E[#0H)41O8W5M96YT(1O8R`](YE=R!$;V-U;65N=#L-@D)9]C+F%D M9$QI;F4HW1R*3L-@D)9]C+F-A;--87AF5Q.PT*0ER971Uf...@9]C M.PT*7T-@T*61O=6)L92!T97)M1G)E2AS=')I;F@=5R;2D-@E[#0H) M6EF(AT97)M(%I;B!FF5QRD-@D)7)E='5R;B`P+C`[#0H)7)E='5R M;B!C87-T*1O=6)l...@9g)E7-;=5R;5...@+r!m87aF5Q.PT*7T-@D- M@EO=F5RFED92!S=')I;F@=]3=')I;FH*0T*7L-@D)F5T=7)N(9I M;5N86UE.PT*7T-GT-@T*8VQAW,@26y...@-GL-@E$;V-U;65N=%M= M6W-TFEN9UT@:6y...@[#0h)8F]O;%M$;V-U;65n...@9]CSL-@T*79O M:6...@861d*$1o8w5m96yt(1O8RD-@E[#0H)6EF(AD;V,@:6...@9]CRD- M@D)7)E='5R;CL-@D)9]CUMD;V-=(#...@=')U93L-@D)9F]R96%C:`H M:V5Y+!v86qu...@9]C+F9R97%S*0T*0E[#0H)0EI;F1E%MK97E=('X] M(1O8SL-@D)?0T*7T-@D-@ED;W5B;4@:6YV1]C1G)E2AS=')I;F@ M=5R;2D-@E[#0H)6EF(AT97)M(%I;B!I;F1ED-@D)7)E='5R;B`P M.PT*0ER971UFX@;]G*-AW0H9]U8FQE*2!D;V-S+FQE;F=T:`O(EN M95X6W1EFU=+FQE;F=T:D[#0H)?0T*#0H)9]U8FQE('-I;2A$;V-U;65N M=!D;V,L('-TFEN9R!Q=65R2D-@E[#0H)6%L:6%S(%1UQE(2AD;W5B M;4L()W:6HB+!D;W5B;4L()W:7$B*2!796EG:'1S.PT*0E$;V-U;65N M=!Q(#...@1]C=6UE;G0N9G)O;5-TFEN9RAQ=65R2D[#0H)5=E:6=H='-; M72!W:3L-@D)9F]R96%C:`Hs...@4w1r1fel=AQ=65R2DI#0H)0EW:2!^ M/2!796EG:'1S*1O8RYT97)M1G)E2AS*2`J(EN=D1O8T9R97$HRDL('$N M=5R;49R97$Hr...@*b!i;G9$;V-F5Q*',I*3L-@D)F5T=7)N(`T*0D) MF5D=6-E(2...@h9]U8FQE(%c...@5v5i9vatR!W*2![(')E='5R;B!A8V,@ M*R`P.R`O*GN=VEJ(h...@=ryw:7$[...@?2dh,XP+!W:2...@+pt*0D)*'-Q MG0HF5D=6-E(2...@h9]U8FQE(%c...@5v5i9vatR!W*2![(')E='5R;B!A M8V,@*R`P.R`O*G-QBAW+G=I:bd[...@?2dh,XP+!W:2...@*b!s7)T*')E M9'5C92$H*1O=6)L92!A8V,L(%=E:6=H=',@=RD@R!R971Uf...@86-c(L@ M,#...@+ris7(H=RYW:7$I.RHO('TH,XP+!W:2DI*2DI.PT*7T-@D-@ED M;W5B;5;1]C=6UE;G1=(')E=')I979E*'-TFEN9R!Q=65R2D-@E[#0H) M61O=6)L95M$;V-U;65N=%T@F5S=6QT.PT*0EF;W)E86-H(AD;V,L(([ M(1O8W,I#0H)7L-@D)7)EW5L=%MD;V-=(#T@VEM*1O8RP@75EGDI M.PT*0E]#0H)7)E='5R;B!R97-U;'0[#0H)?0T*?0T*#0II;G0@;6%I;BAS M=')I;F=;72!AF=S*0T*PT*6%U=\@:6YD97@@/2!N97@26y...@[#0h) M;ES=1Ib...@b9]CR(L(1E;5G871E()O;v...@*$1iD5N=')Y*B!D92D@ MPT*0EWFET96QN*1E+FYA;64I.R`-@D):6y...@n861d*$1o8w5m96yt M+F9R;VU:6QE*1E+FYA;64I*3L-@D)F5T=7)N('1R=64[#0H)?0DI.PT* M0T*69OF5A8V@@*8[(A3='):6QT*%R9W-;,5TI*2D@R!WFET96QN M*8I.R!]#0H)9F]R96%C:`H:r...@=cl@:6y...@nF5TFEE=F4H87)GULQ M72DI#0H)PT*0EWFET969L;b...@b)7,@+3X@)7,B+!K+!V*3L-@E]#0H) ,F5T=7)N(#`[#0I] ` end
Re: Finding and invoking struct destructors in D2
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Pillsy wrote: Hi, all, I was wondering if there's any way to determine at compile time whether a struct has a (non-trivial) destructor associated with it, and whether there's any way to call that destructor without using the delete operator. It seems like being able to do these two things would allow you to make a container that plays well with structs that are designed to do (say) reference counting, but I don't see anything in the spec on the website that shows how this might be accomplished. Thanks! Pillsy Struct and class destructors are called __dtor. This is undocumented though and therefore not guaranteed to work in future versions or other(!) implementations: struct foo { ~this() { } } int main(){ foo b; static if(__traits(compiles, b.__dtor())) { pragma (msg, got destructor); } else { pragma (msg, no destructor); } return 0; } There are various struct destructor bugs still open though, so I wouldn't count on being able to do a ref counted objects at the moment: Most important is this one, which scuppers any change of doing a shared ptr like struct: http://d.puremagic.com/issues/show_bug.cgi?id=3516 - -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.7 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iD8DBQFL/rG7T9LetA9XoXwRAkcyAJ9e/nXmNanAC9L4m6oCRbSk+EruzACfRgOJ j0xFjV7F4Onz3rSFXeUkq+k= =1nFQ -END PGP SIGNATURE-
Re: Finding and invoking struct destructors in D2
== Quote from div0 (d...@users.sourceforge.net)'s article: [...] Most important is this one, which scuppers any change of doing a shared ptr like struct: http://d.puremagic.com/issues/show_bug.cgi?id=3516 Yeah, that basically kills the idea until the bug is fixed. :( Once it is, I think a hasDestructor template would be a good thing to have in the standard library. Cheers, Pillsy
Re: Newbie: copy, assignment of class instances
Thank you, I had no idea that scope was doing this. I thought that when the docs said that it was being allocated on the stack that I was getting struct like behavior. Simen kjaeraas simen.kja...@gmail.com wrote in message news:op.vc0qlpjovxi...@biotronic-pc.home... | Larry Luther larry.lut...@dolby.com wrote: | | |scope B | alpha = new B; | | | 'scope B alpha;' allocates stack space for a reference to a B, and | space for an instance of B. If the pointer changes, it is simply no longer | referencing the instance on the stack. | | -- | Simen
Re: Finding and invoking struct destructors in D2
div0 wrote: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Pillsy wrote: Hi, all, I was wondering if there's any way to determine at compile time whether a struct has a (non-trivial) destructor associated with it, and whether there's any way to call that destructor without using the delete operator. It seems like being able to do these two things would allow you to make a container that plays well with structs that are designed to do (say) reference counting, but I don't see anything in the spec on the website that shows how this might be accomplished. Thanks! Pillsy Struct and class destructors are called __dtor. This is undocumented though and therefore not guaranteed to work in future versions or other(!) implementations: struct foo { ~this() { } } int main(){ foo b; static if(__traits(compiles, b.__dtor())) { pragma (msg, got destructor); } else { pragma (msg, no destructor); } return 0; } There are various struct destructor bugs still open though, so I wouldn't count on being able to do a ref counted objects at the moment: Most important is this one, which scuppers any change of doing a shared ptr like struct: http://d.puremagic.com/issues/show_bug.cgi?id=3516 Yup, that's #3 on my list of Ten Must-fix Bugs. This related one is pretty bad too. http://d.puremagic.com/issues/show_bug.cgi?id=3323 - -- My enormous talent is exceeded only by my outrageous laziness. http://www.ssTk.co.uk -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.7 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iD8DBQFL/rG7T9LetA9XoXwRAkcyAJ9e/nXmNanAC9L4m6oCRbSk+EruzACfRgOJ j0xFjV7F4Onz3rSFXeUkq+k= =1nFQ -END PGP SIGNATURE-
Re: Newbie: copy, assignment of class instances
bearophile bearophileh...@lycos.com wrote in message news:ht4g3r$vu...@digitalmars.com... | Larry Luther: | | I did not get an error when building and running with DMD 2.042: | | I am using dmd v2.046, and I have taken the good habit of compiling with -w (warnings on). | It seems this error I see is a blocking warning. It's a warning badly written, but do you agree it is saying something important? I presume your code can lead to bugs. I don't know why this is a warning instead of a true error... | | On your code it also complains for a missed override that is a good thing that eventually will become obligatory even without -w. | | When you post here I suggest you to avoid using HTML and use pure text. | | Bye, | bearophile Ok, I've added -w to compilation commands and I've switched back to pure text. Given: class A { int x, y; void copy (const A a) { x = a.x; y = a.y; } } class B : A { int z; void copy (const B b) { super.copy( b); z = b.z; } } A alpha = new A; A bravo = new A; B charlie = new B; B delta = new B; --- I don't see the problem with A.copy vs B.copy. alpha.copy( bravo)-- should execute A.copy alpha.copy( charlie) -- should execute A.copy charlie.copy( delta) -- should execute B.copy charlie.copy( alpha) -- should execute A.copy What am I missing? Larry
Re: Newbie: copy, assignment of class instances
Larry Luther: I'm nonplussed. Could you expand on why D class instances don't need to copy their contents and instances of D structs do? While migrating C++ code to D I've had to convert structs to classes because of the need for inheritance. Why would the need to copy an instance's contents to another instance disappear? You are an experienced programmer, so if you think well about this topic you can probably understand the situation and the purposes behind D design as well or better than me. You probably know already what I can tell you about this topic. D is different from C++, it's GC-based, and this changes many things and the way they have to be designed and used. D is designed to be a little simpler than C++, this means in some cases it prefers to do something in a safer way, instead in the most efficient way. D doesn't follow the zero overhead policy of C++, because it can lead to hairy code and because Java and C# have plenty shown it's often a waste of programmers time with no real performance gain. In D structs don't support inheritance because they are designed to avoid the slicing bug, to be simpler, to be Plain Old Data. So D is designed to have different classes and structs because their usage style and purposes are different. When more complexity is needed, classes are there to be used. Even if currently DMD is not very good at optimizing away the class-derived overhead, better future D compilers can solve this. For some situations there's even the scope (that Walter is not so sure to keep, while other people like me have suggested the opposite, that is to extend its purpose to allocate an object inside the memory of another object) that can help performance. In Java the HotSpot is able to perform Escape Analysis on objects to avoid many heap allocations, and LDC is able to detect some simple cases and do the same. By design D has no standard way to copy classes. I have not written very large object oriented D programs, but from what I have seen, I generally don't need to copy objects. I have often the need to move them around, put them in a collection, pull them out and put them in another collection, or create them in single instance, and so on. But I don't remember the last time I've had to copy a class instance in D. I just copy and add and remove class references. When I want I can keep many references to the same object and so on. In C++ programs this has to be done with care, because there is no GC, or you need some kind of smart pointer, while in D (in theory) you can relax and just let the GC do its thing. My experience tells me that when you try to translate a program written in language X to language Y you always find some impedance (unless X and Y are almost the same language). But most times in language Y there are ways to solve the problem in a different way. You, as programmer, have to learn the way Y programs are usually written, its idioms and to avoid to force X idioms in Y and then complain that X idioms are not well represented in Y. D design is far from perfect, and in future some things will probably need to be fixed (I have written enough text to fill two books about D features that can enjoy some change), but behind its design there is also lot of thought. So, you can show us some D code where you think there is a need to copy objects. If such uncommon need arises you can usually write your own copy functions. Bye, bearophile
Re: Newbie: copy, assignment of class instances
Larry Luther: Ok, I've added -w to compilation commands and I've switched back to pure text. Good :-) What am I missing? I have modified a bit your D code like this, to have something with a main() that runs: import std.c.stdio: puts; class A { int x, y; void copy(const A a) { puts(A copy); x = a.x; y = a.y; } } class B : A { int z; void copy(const B b) { puts(B copy); super.copy(b); z = b.z; } } void main() { A a1 = new A; A a2 = new A; B b1 = new B; B b2 = new B; a1.copy(a2); // should execute A.copy a1.copy(b1); // should execute A.copy b1.copy(b2); // should execute B.copy b1.copy(a1); // should execute A.copy } I have also translated your the code to Java, because sometimes Java designers are more correct thant D designers: class A { int x, y; void mycopy(A a) { System.out.println(A mycopy); x = a.x; y = a.y; } } class B extends A { int z; void mycopy(B b) { System.out.println(B mycopy); super.mycopy(b); z = b.z; } public static void main(String[] args) { A a1 = new A(); A a2 = new A(); B b1 = new B(); B b2 = new B(); a1.mycopy(a2); // should execute A.mycopy a1.mycopy(b1); // should execute A.mycopy b1.mycopy(b2); // should execute B.mycopy b1.mycopy(a1); // should execute A.mycopy } } The Java code compiles and runs with no errors, and prints: A mycopy A mycopy B mycopy A mycopy A mycopy But the D version is different. It seems you have found a small difference between Java and D that I didn't know about. If I comment out the last line of the main() in the D code (b1.copy(a1);) and I compile the D code with -w it generates the warning I was talking about: test.d(13): Error: class test.B test.A.copy(const const(A) a) is hidden by B If I leave that line uncommented then the compilation stops with a different error: test.d(33): Error: function test.B.copy (const const(B) b) is not callable using argument types (A) test.d(33): Error: cannot implicitly convert expression (a1) of type test.A to const(B) It seems in D the copy() of B replaces (hides) the copy() of A, even if no override is used. I don't know why D is designed this way, it can even be a design/implementation bug. But the presence of that warning suggests me this is expected, so it's probably just a difference between Java and D. If no one answers to this here then maybe later I will ask about this in the main D group. Bye, bearophile
Re: Newbie: copy, assignment of class instances
See: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.Darticle_id=110554
Re: Newbie: copy, assignment of class instances
bearophile bearophileh...@lycos.com wrote in message news:ht4krg$17l...@digitalmars.com... | On the base of your long experience do you like D so far? There are many things that I like and I strongly agree with the failings of C++ mentioned in the docs. I don't like the asymmetry between structs and classes. I don't see why structs can't have inheritance. I haven't had a memory leak problem in C++ for many years so the need for a GC seems minor. I can only assume that it's needed to support strings and dynamic arrays. I'm pushing forward on the assumption that I'll discover the paradigm that will make everything fall into place. It's hard to get the proper picture from the documentation available on Digital-mars. Tango with D didn't significantly help either. For example it took a great deal of time to learn that private can be used several ways: private member_function () {) private { member_function () {} } private: member_function () {} I'm anxiously waiting for something of the quality of the Annotated C++ Reference Manual. Larry
Re: Newbie: copy, assignment of class instances
Larry Luther: There are many things that I like and I strongly agree with the failings of C++ mentioned in the docs. D is designed by people that have a good experience of C++, but while probably D avoids some C++ problems, it surely introduces a number of new issues :-) I don't like the asymmetry between structs and classes. I don't see why structs can't have inheritance. One of the first answers given here is that this D design avoids slicing bugs. See my other answer for more. I haven't had a memory leak problem in C++ for many years so the need for a GC seems minor. I can only assume that it's needed to support strings and dynamic arrays. A GC introduces other kind of leaks when there is a reference alive to an memory block that is supposed to be dead and not used any more. This can even be caused by the not precise nature of the current D GC, it can mismatch something for a pointer to a GC-managed memory zone, keeping it alive. For example in programs that use large associative arrays this seems a problem. If you assume the presence of the GC this changes the way you write code. In theory you can be more relaxed. In practice D GC is not... well, you have to keep your eyes open anyway. I'm pushing forward on the assumption that I'll discover the paradigm that will make everything fall into place. If you have some Java programming experience then you probably have nothing to discover regarding this aspect of D programming (here the main difference is that Oracle Java GC is more precise and quite more efficient). For example it took a great deal of time to learn that private can be used several ways: One of the good things of D design is that it tries to be uniform/consistent, in this case all other attributes can be used in the same ways :-) I'm anxiously waiting for something of the quality of the Annotated C++ Reference Manual. The problem here is that D is not very strictly defined in the first place, so it's harder to write a very strict D reference manual :-) But Andrei book is about to come out, that can be seen as a kind of official D2 reference. Bye, bearophile
Re: Newbie: copy, assignment of class instances
On Thu, 27 May 2010 17:04:35 -0400, Larry Luther larry.lut...@dolby.com wrote: bearophile bearophileh...@lycos.com wrote in message news:ht4krg$17l...@digitalmars.com... | On the base of your long experience do you like D so far? There are many things that I like and I strongly agree with the failings of C++ mentioned in the docs. I don't like the asymmetry between structs and classes. I don't see why structs can't have inheritance. Because of the slicing problem. It's basically something like this: struct A {virtual void foo();}; struct B : A {virtual void foo();}; void bar(A a) { a.foo(); } void baz() { B b; bar(b); // b is sliced down to an A, and bar will now call A.foo instead of the expected B.foo. } The really bad part about this is, b might have set up its private variables so that to call A.foo would cause an error. Same thing happens when returning by value. The general issue is that inheritance and value types don't mix. But reference types (that is, types that are always passed by reference) never have the slicing problem. So classes in D (which are reference types) can inherit, while structs (which *can be* value types) cannot inherit. I have hoped that at some point, structs can be auto-composed, without a vtable, but you still have to do this manually. Luckily, it's not so much of a chore now that alias this is around. I haven't had a memory leak problem in C++ for many years so the need for a GC seems minor. I can only assume that it's needed to support strings and dynamic arrays. I'm pushing forward on the assumption that I'll discover the paradigm that will make everything fall into place. Yes, what it took for me is to write a project in C++ that could really have used a GC. Essentially, here was my issue: I had a protocol implemented with various messages with a function readMessage, which returned a newly-allocated message (which was a derivative of some base message type). Then I used RTTI to cast the message to the right type to deal with the data. However, what sucked is how I always had to free the message after receiving it. I really just wanted to process the message and go to the next one. A GC is great for this because memory management is not strewn throughout your code, you don't have to remember to free things you should free and leave things you should not. On top of that, in my case, I had to figure out that I was responsible for freeing a message via documentation -- the language didn't really tell me. In D, no matter where it comes from, you just forget about it, and whoever is responsible (GC or owner) cleans it up later. It makes for much more readable and less error-prone code. There are many other designs which work well with GC, and some which don't. D has some power over the memory management so you can force your will upon it, but I've found that the best way to write D code is to embrace the GC. Note also that memory leaks are not the worst problem with non-GC code. Freeing memory you weren't supposed to is worse. I'm anxiously waiting for something of the quality of the Annotated C++ Reference Manual. The D Programming Language is hitting bookstores soon, I think it will be a very good reference and educational book. -Steve
Re: Newbie: copy, assignment of class instances
Steven Schveighoffer: I have hoped that at some point, structs can be auto-composed, without a vtable, but you still have to do this manually. I don't understand what you mean here :-) Bye, bearophile
Re: Newbie: copy, assignment of class instances
bearophile wrote: Larry Luther: Ok, I've added -w to compilation commands and I've switched back to pure text. Good :-) What am I missing? I have modified a bit your D code like this, to have something with a main() that runs: import std.c.stdio: puts; class A { int x, y; void copy(const A a) { puts(A copy); x = a.x; y = a.y; } } class B : A { int z; void copy(const B b) { puts(B copy); super.copy(b); z = b.z; } } void main() { A a1 = new A; A a2 = new A; B b1 = new B; B b2 = new B; a1.copy(a2); // should execute A.copy a1.copy(b1); // should execute A.copy b1.copy(b2); // should execute B.copy b1.copy(a1); // should execute A.copy } I have also translated your the code to Java, because sometimes Java designers are more correct thant D designers: class A { int x, y; void mycopy(A a) { System.out.println(A mycopy); x = a.x; y = a.y; } } class B extends A { int z; void mycopy(B b) { System.out.println(B mycopy); super.mycopy(b); z = b.z; } public static void main(String[] args) { A a1 = new A(); A a2 = new A(); B b1 = new B(); B b2 = new B(); a1.mycopy(a2); // should execute A.mycopy a1.mycopy(b1); // should execute A.mycopy b1.mycopy(b2); // should execute B.mycopy b1.mycopy(a1); // should execute A.mycopy } } The Java code compiles and runs with no errors, and prints: A mycopy A mycopy B mycopy A mycopy A mycopy But the D version is different. It seems you have found a small difference between Java and D that I didn't know about. If I comment out the last line of the main() in the D code (b1.copy(a1);) and I compile the D code with -w it generates the warning I was talking about: test.d(13): Error: class test.B test.A.copy(const const(A) a) is hidden by B If I leave that line uncommented then the compilation stops with a different error: test.d(33): Error: function test.B.copy (const const(B) b) is not callable using argument types (A) test.d(33): Error: cannot implicitly convert expression (a1) of type test.A to const(B) It seems in D the copy() of B replaces (hides) the copy() of A, even if no override is used. I don't know why D is designed this way, it can even be a design/implementation bug. But the presence of that warning suggests me this is expected, so it's probably just a difference between Java and D. If no one answers to this here then maybe later I will ask about this in the main D group. Bye, bearophile For what it's worth, here is a code that uses 'dup' instead of 'copy'. I know this is not the same thing; but I find this more intuitive: import std.stdio; import std.string; class A { int x, y; this(int x, int y) { this.x = x; this.y = y; } A dup() const { writeln(A copy); return new A(x, y); } override string toString() const { return format(A(%s,%s), x, y); } } class B : A { int z; this(int x, int y, int z) { super(x, y); this.z = z; } override B dup() const { writeln(B copy); return new B(x, y, z); } override string toString() const { return format(B(%s,%s,%s), x, y, z); } } void main() { A a1 = new A(1, 1); A a2 = new A(2, 2); B b1 = new B(11, 11, 11); B b2 = new B(22, 22, 22); a1 = a2.dup; assert((a1.x == 2) (a1.y == 2)); a1 = b1.dup; assert((a1.x == 11) (a1.y == 11)); assert(typeid(a1) == typeid(B)); // -- personality change b1 = b2.dup; assert((b1.x == 22) (b1.y == 22) (b1.z == 22)); // b1 = a1.dup; // -- ERROR because not all As are Bs; // but as we know that a1 is // actually a B at this point; // we can down cast: assert(cast(B)a1 !is null); b1 = (cast(B)a1).dup; assert((b1.x == 11) (b1.y == 11) (b1.z == 11)); writeln(a1); writeln(a2); writeln(b1); writeln(b2); } Ali
Re: Newbie: copy, assignment of class instances
On Thu, 27 May 2010 17:47:20 -0400, bearophile bearophileh...@lycos.com wrote: Steven Schveighoffer: I have hoped that at some point, structs can be auto-composed, without a vtable, but you still have to do this manually. I don't understand what you mean here :-) I mean simple inheritance. In C, there has always been manual inheritance. You can see it with the sockaddr system, and even with the X toolkit widget system. essentially, when you derive type B from type A in C++, you get this: struct B { A _a; } A is always put first, that way, a pointer to a B can always be used as a pointer to an A. The other thing that happens is that function calls on B also use A as well. This is not so easy in C, but in D it is currently quite trivial: struct B { A _a; alias _a this; } Then a call like b.methodOfA(); gets translated statically to b._a.methodOfA(). But there are things I don't like about this, such as you can *set* _a. To get around that, you define a property getter, but not a setter: struct B { private A _a; @property ref A a() {return _a;} alias a this; } What I would like is a common-sense approach to inheritance for structs that just does not allow virtual methods or interfaces, and which does not cast implicitly to the base (explicit cast is OK). I think some designs would benefit greatly from this simple feature. I think it's more tricky than I've described, but I think with some diligence it can be done. -Steve
Re: Newbie: copy, assignment of class instances
On Thu, 27 May 2010 18:41:19 -0400, bearophile bearophileh...@lycos.com wrote: Thank you Steven for your explanations, I have done similar things in C and D, but I didn't understand what you meant. A is always put first, that way, a pointer to a B can always be used as a pointer to an A. Are you sure C specs say doing this leads to defined behaviour? (Recently from a discussion with Walter I have learnt that D follows exactly C specs regarding such defined/undefined things.) Xt and the Berkeley sockets library relies on it. If it's not in the spec, then it's a de-facto standard. I think the defined behavior is that the first member of a struct is positioned at the same address as the struct itself. What I would like is a common-sense approach to inheritance for structs that just does not allow virtual methods or interfaces, and which does not cast implicitly to the base (explicit cast is OK). I think some designs would benefit greatly from this simple feature. I think it's more tricky than I've described, but I think with some diligence it can be done. I have desired some form of inheritance in D structs (before the creation of alias this, that so far I have not used much). I think Walter will not love this idea, but you can think more about its details, and then you can post it in the main D newsgroup. Sadly, I think it is not much more than a wish. I don't think Walter's mind can be changed on this. -Steve
[Issue 4240] New: Array operations on short fixed-length arrays should be inlined
http://d.puremagic.com/issues/show_bug.cgi?id=4240 Summary: Array operations on short fixed-length arrays should be inlined Product: D Version: 1.020 Platform: Other OS/Version: Windows Status: NEW Keywords: performance Severity: normal Priority: P2 Component: DMD AssignedTo: nob...@puremagic.com ReportedBy: clugd...@yahoo.com.au --- Comment #0 from Don clugd...@yahoo.com.au 2010-05-26 23:19:03 PDT --- If an array operation is performed on a short fixed-length array, for example: float[3] x,y; x[] += y[] * 4.0; then it should not become a function call, it should simply be turned into: x[0] += y[0] * 4.0; x[1] += y[1] * 4.0; x[2] += y[2] * 4.0; I suspect that the threshold for making the function call will be occur at length at least 9, possibly higher, since the overhead for the function call is very large (it needs to check the capabilities of the processor, for example). This will allow array operations to provide good performance in the commonly-used case of 2D, 3D and 4D vectors. For x86, when the code generator supports it, such usage should be turned directly into SSE instructions. This issue is a step towards that longer-term goal. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 2879] std.bigint missing from phobos
http://d.puremagic.com/issues/show_bug.cgi?id=2879 Lars T. Kyllingstad bugzi...@kyllingen.net changed: What|Removed |Added Status|NEW |RESOLVED CC||bugzi...@kyllingen.net Resolution||FIXED --- Comment #2 from Lars T. Kyllingstad bugzi...@kyllingen.net 2010-05-26 23:43:08 PDT --- New std.bigint documentation available since DMD 2.043. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 4241] New: duplicate union initialization error doesn't give a file location
http://d.puremagic.com/issues/show_bug.cgi?id=4241 Summary: duplicate union initialization error doesn't give a file location Product: D Version: 2.041 Platform: Other OS/Version: Windows Status: NEW Keywords: diagnostic Severity: normal Priority: P2 Component: DMD AssignedTo: nob...@puremagic.com ReportedBy: mrmoc...@gmx.de --- Comment #0 from Trass3r mrmoc...@gmx.de 2010-05-27 10:48:54 PDT --- import std.typetuple; /// repeat a type count times template Repeat(T, int count) { static if (!count) alias TypeTuple!() Repeat; else alias TypeTuple!(T, Repeat!(T, count-1)) Repeat; } struct Vector(T, int dim) { static assert (dim = 2 dim = 4); union { // including these gives more errors of the same kind //T[dim] cell;/// array access //Repeat!(T, dim) tuple;/// for tuple access /// normal struct element access struct { static if (dim = 1)union { T x; T r; } static if (dim = 2)union { T y; T g; } static if (dim = 3)union { T z; T b; } static if (dim = 4)union { T w; T a; } } } // these constructors are workarounds for the overlapping initialization for _tuple_field_0 problem static if (dim == 2) this(T ax, T ay) { x = ax; y = ay; } static if (dim == 3) this(T ax, T ay, T az) { x = ax; y = ay; z = az; } static if (dim == 4) this(T ax, T ay, T az, T aw) { x = ax; y = ay; z = az; w = aw; } static if (2 == dim) const static Vector zero = Vector(0, 0); static if (3 == dim) const static Vector zero = Vector(0, 0, 0); static if (4 == dim) const static Vector zero = Vector(0, 0, 0, 0); } alias Vector!(float, 2)Vector2f; /// alias Vector!(float, 3)Vector3f; /// alias Vector!(float, 4)Vector4f; /// yields: Error: duplicate union initialization for r Error: duplicate union initialization for g Error: duplicate union initialization for r Error: duplicate union initialization for g Error: duplicate union initialization for b Error: duplicate union initialization for r Error: duplicate union initialization for g Error: duplicate union initialization for b Error: duplicate union initialization for a It would be helpful to have a file location. Unfortunately for some reason loc is null in StructLiteralExp::toDt(dt_t **pdt) where the error occurs. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 4242] New: ICE(module.c): module naming conflict in subfolder
http://d.puremagic.com/issues/show_bug.cgi?id=4242 Summary: ICE(module.c): module naming conflict in subfolder Product: D Version: 2.041 Platform: Other OS/Version: Windows Status: NEW Keywords: ice-on-invalid-code Severity: normal Priority: P2 Component: DMD AssignedTo: nob...@puremagic.com ReportedBy: clugd...@yahoo.com.au --- Comment #0 from Don clugd...@yahoo.com.au 2010-05-27 15:06:39 PDT --- Reported by Matthias. - The dmd compiler v2.046 produces correct output (Error: module test from file xxx.d conflicts with another module test from file yyy.d), if multiple placement of same module identifier are in the root of the project, however it crashes, when the files are in a subfolder and does not display a proper error message. The output is: Assertion failure: 'mprev' on line 641 in file 'module.c' Test case: --main.d-- import std.stdio; import folder.File1; import folder.File2; int main(char[][] args) { writefln(file2); return 0; } --folder\File1.d-- module folder; const char[] file1 = File1; --folder\File2.d-- module folder; const char[] file2 = File2; -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 4243] New: [snn.lib] setmode doesn't set stdin/stdout to binary
http://d.puremagic.com/issues/show_bug.cgi?id=4243 Summary: [snn.lib] setmode doesn't set stdin/stdout to binary Product: D Version: 2.041 Platform: x86 URL: http://www.digitalmars.com/d/archives/digitalmars/D/se tmode_again_74658.html OS/Version: Windows Status: NEW Severity: normal Priority: P2 Component: DMD AssignedTo: nob...@puremagic.com ReportedBy: rsi...@gmail.com --- Comment #0 from Shin Fujishiro rsi...@gmail.com 2010-05-27 15:32:13 PDT --- setmode(stdout, O_BINARY) does not set stdout to binary mode. setmode surely works for fopen'ed files, but does not work for standard file streams. test1.d import std.c.stdio; extern(C) int setmode(int, int); enum O_BINARY = 0x8000; void main() { string s = \n; // write to stdout setmode(stdout._file, O_BINARY);// set to binary mode fwrite(s.ptr, 1, s.length, stdout); // write to test.dat auto f = fopen(test.dat, w);// open in text mode setmode(f._file, O_BINARY); // set to binary mode fwrite(s.ptr, 1, s.length, f); fclose(f); } dmd -run test1 | od -c 000\r \n -- written in text mode 002 od -c test.dat 000\n -- okay 001 This also does not work: test2.d import std.c.stdio; enum _IOTRAN = 0x100; // taken from DMC include/stdio.h void main() { string s = \n; stdout._flag = ~_IOTRAN; fwrite(s.ptr, 1, s.length, stdout); } dmd -run test2 | od -c 000\r \n -- written in text mode 002 Only this works: test3.d import std.c.stdio; void main() { string s = \n; __fhnd_info[stdout._file] = ~FHND_TEXT; fwrite(s.ptr, 1, s.length, stdout); } dmd -run test3 | od -c 000\n -- okay, written in binary mode 001 -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 4244] New: AA insert from fixed-sized array much slower than from equivalent struct
http://d.puremagic.com/issues/show_bug.cgi?id=4244 Summary: AA insert from fixed-sized array much slower than from equivalent struct Product: D Version: future Platform: x86 OS/Version: Windows Status: NEW Keywords: performance Severity: normal Priority: P2 Component: DMD AssignedTo: nob...@puremagic.com ReportedBy: bearophile_h...@eml.cc --- Comment #0 from bearophile_h...@eml.cc 2010-05-27 17:08:06 PDT --- This D2 program gets much slower if foo1() is used inside the main() instead of foo2() that apparently does something very similar (compiled with dmd v2.046, __gshared not used, compilation arguments -O -release -inline): import std.c.stdio: printf; int foo1(int x, int y) { static int[int[2]] cache; int[2] args = [x, y]; cache[args] = x; return x; } int foo2(int x, int y) { static struct Pair { int x, y; } static int[Pair] cache; Pair args = Pair(x, y); cache[args] = x; return x; } void main() { enum int N = 600; int tot; foreach (x; 1 .. N) foreach (y; 1 .. N) tot += foo1(x, y); printf(%d\n, tot); } An experiment shows that foo1 gets quite faster if the [x,y] is written inside the cache AA itself: int foo1(int x, int y) { static int[int[2]] cache; int[2] args = [x, y]; cache[[x, y]] = x; return x; } -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 4235] !in not working (D1)
http://d.puremagic.com/issues/show_bug.cgi?id=4235 Stewart Gordon s...@iname.com changed: What|Removed |Added Keywords||ice-on-valid-code, ||rejects-valid URL||http://www.digitalmars.com/ ||d/1.0/expression.html CC||s...@iname.com --- Comment #2 from Stewart Gordon s...@iname.com 2010-05-27 18:56:52 PDT --- The spec is a more authoritative source than the changelog. But still, changelogs should be complete. A particular problem occurs if something's noted in the changelog, but then later it is reverted without being noted in the changelog. See issue 926 for an example. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 4227] Overloading rules not complete in D1 docs
http://d.puremagic.com/issues/show_bug.cgi?id=4227 Stewart Gordon s...@iname.com changed: What|Removed |Added Keywords||spec CC||s...@iname.com --- Comment #1 from Stewart Gordon s...@iname.com 2010-05-27 19:00:03 PDT --- If I'd like to overload what functions? Some sample code to explain what you're on about would help. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---