digitalmars.D - Why D is annoying =P
- Mehrdad (12/12) Oct 24 2012 I couldn't find a better title, sorry.
- Timon Gehr (2/13) Oct 24 2012 http://d.puremagic.com/issues/show_bug.cgi?id=3789
- Mehrdad (3/4) Oct 24 2012 Ouch, bug since 2010...
- Andrej Mitrovic (3/4) Oct 24 2012 Struct fields are compared by address by default if no opEquals is
- Andrej Mitrovic (3/7) Oct 24 2012 Well I mean for reference types. Or something like that. To put it
- Mehrdad (6/16) Oct 24 2012 Yeah, and my attempts to get around it don't seem to help:
- Mehrdad (8/12) Oct 24 2012 Harsh (but true, and perhaps useful) feedback...
- Jacob Carlborg (4/8) Oct 24 2012 Everything in C++ is specified as undefined behavior :)
- Mehrdad (6/13) Oct 24 2012 lol.
- H. S. Teoh (19/28) Oct 24 2012 [...]
- Mehrdad (11/26) Oct 24 2012 Yeah, I was a little aware that AAs were semi-broken, but I
- Mehrdad (3/5) Oct 24 2012 Case in point: there's no way to tell an arbitrary object/struct
- H. S. Teoh (9/15) Oct 24 2012 Huh? All objects implement toHash(). If the default toHash() doesn't
- Mehrdad (4/15) Oct 24 2012 Not Tuples, apparently. (I didn't mean Object, I mean "object" in
- H. S. Teoh (14/32) Oct 24 2012 Well, Object implements toHash(). Other things don't, but with UFCS you
- H. S. Teoh (29/57) Oct 24 2012 The AA implementation badly needs to be revamped. But the problem is
- Mehrdad (32/49) Oct 24 2012 The last time I checked two RedBlackTrees for equality, they
- H. S. Teoh (17/30) Oct 24 2012 Try this:
- Mehrdad (2/30) Oct 24 2012 Wouldn't that do a bitwise comparison?
- Mehrdad (2/3) Oct 24 2012 sorry, I mean bitwise _hash_
- H. S. Teoh (12/47) Oct 24 2012 Umm, the idea of a hash is to *quickly* compute a value that's (mostly)
- Mehrdad (4/7) Oct 24 2012 I don't understand what you're saying.
- Mehrdad (28/28) Oct 24 2012 Is there any reason why we don't have something like this in
- Mehrdad (38/38) Oct 24 2012 Better example:
- Timon Gehr (12/14) Oct 24 2012 import std.stdio;
- Mehrdad (3/20) Oct 24 2012 I'm on my phone so I can't test it right now, but I'm wondering
- Ellery Newcomer (19/25) Oct 25 2012 Dang.
- H. S. Teoh (10/41) Oct 25 2012 Hmph. This is what I don't like about the built-in ==. Its semantics are
- Ellery Newcomer (3/6) Oct 25 2012 Well, if nobody else is going to take it
- Era Scarecrow (3/4) Oct 24 2012 So should I drop a project I'm working on and go to C++? That
- Mehrdad (5/10) Oct 24 2012 Well if it's been working for you then there's obviously no
- Andrei Alexandrescu (3/11) Oct 24 2012 OK let's stop this. There's a bug that needs fixing, is all.
- Mehrdad (8/10) Oct 24 2012 Sorry, yeah. It was just that I came across it so much that I
- Jonathan M Davis (7/8) Oct 24 2012 And as bad as things may be now, they're _way_ better than they were a c...
- Era Scarecrow (9/15) Oct 24 2012 You can always work around what does and doesn't work; Although
- Mehrdad (11/22) Oct 24 2012 Well I mean, yeah, you can obviously implement your own data
- Era Scarecrow (10/20) Oct 24 2012 I have no intention of writing a different version of phobos or
- H. S. Teoh (10/13) Oct 24 2012 Huh? Why would you drop classes in favor of structs? They are used for
- Era Scarecrow (10/16) Oct 24 2012 Indeed. Instead of interfaces you'd use templates, OO doesn't
- H. S. Teoh (31/44) Oct 24 2012 [...]
- Mehrdad (2/2) Oct 24 2012 Funny, I was actually building a (GLR) parser, too.
- H. S. Teoh (31/34) Oct 24 2012 Oh. You should've said so earlier -- for such specific applications, you
- Mehrdad (19/19) Oct 24 2012 Haha thanks a bunch for the advice. :) I was actually intending
- H. S. Teoh (6/12) Oct 24 2012 [...]
- Mehrdad (7/18) Oct 24 2012 Hmm, why would I prefer a struct over a Tuple?
- Philippe Sigaud (2/4) Oct 24 2012 H. S. Teoh, Mehrdad: are your codebases in a public website?
- Mehrdad (10/16) Oct 24 2012 Nope.
- Mehrdad (8/8) Oct 24 2012 Actually, I think I might as well send you a link to something I
- Philippe Sigaud (2/6) Oct 25 2012 Thanks :)
- Timon Gehr (2/4) Oct 24 2012 Yes I can.
- Mehrdad (4/9) Oct 24 2012 So you made your own AA and Set implementations instead of trying
- Timon Gehr (3/12) Oct 24 2012 It is actually hard to miss them.
- Jacob Carlborg (6/13) Oct 24 2012 I haven't read the rest of thread yet but if you're not happy the the
- Walter Bright (3/14) Oct 24 2012 The compare for associative arrays is to compare the members.
- Mehrdad (5/7) Oct 24 2012 Thanks for the reply.
- Jonathan M Davis (11/12) Oct 24 2012 Which definitely seems inherently broken. Doing that only works if the s...
- Dejan Lekic (5/26) Oct 25 2012 +1
- deadalnix (5/17) Oct 26 2012 That will broke code.
- Jonathan M Davis (30/52) Oct 27 2012 ing
- H. S. Teoh (13/24) Oct 27 2012 [...]
- Rob T (48/58) Oct 29 2012 There is a problem with floating point memebers, since nan values
- H. S. Teoh (6/8) Oct 29 2012 This is IEEE specification. There is no problem.
- Rob T (10/17) Oct 29 2012 If struc comparisions compare value by value, and both have Nan
- Mehrdad (5/25) Oct 29 2012 I understand the problem, but it doesn't seem related to structs
- Rob T (35/42) Oct 30 2012 True at the level of float by float comparisons, but not
- Jonathan M Davis (6/12) Oct 30 2012 Structs never were just PODs in D. They have _way_ more capabilities to ...
- Rob T (9/23) Oct 30 2012 I do understand what you are saying, however the docs in here
- Jonathan M Davis (5/8) Oct 30 2012 It's in the online docs:
- Tobias Pankrath (3/7) Oct 30 2012 It's hard to find because it can not be overloaded.
- H. S. Teoh (14/24) Oct 30 2012 Sigh, one of these days I'm gonna have to rewrite many of these pages.
- Tobias Pankrath (9/26) Oct 30 2012 I agree, that the online docs are insufficient for learning the
- Jacob Carlborg (6/15) Oct 30 2012 A language needs several types of documentation. Reference documentation...
- H. S. Teoh (27/43) Oct 30 2012 [...]
- Jens Mueller (21/55) Oct 28 2012 =3D=3D
- Jacob Carlborg (7/11) Oct 28 2012 Fixing bugs can always break code and I don't think any version scheme
- H. S. Teoh (10/23) Oct 24 2012 [...]
- Jonathan M Davis (8/14) Oct 25 2012 Actually, slight correction. Pointers are fine too. I'd expect to have t...
- Jonathan M Davis (4/6) Oct 27 2012 That presupposes that the language has any beauty to begin with. It coul...
- Nick Sabalausky (3/10) Oct 28 2012 Did someone say "PHP"? ;)
- H. S. Teoh (5/17) Oct 28 2012 I thought I heard "Javascript"... :-P
- Era Scarecrow (3/6) Oct 28 2012 Both seem to have their own issues, although I'd say javascript
- Jacob Carlborg (4/6) Oct 29 2012 You can run JavaScript on the server too.
- H. S. Teoh (6/12) Oct 28 2012 [...]
I couldn't find a better title, sorry. But yeah, I've spent too many hours on hunting down problems like these... Could someone explain what's going on? Thanks! import std.stdio; struct S { int[int] aa; } void main() { writeln( [1: 2] == [1: 2] ); // true writeln(S([1: 2]) == S([1: 2])); // false } (I'm on Windows DMD v2.060.)
Oct 24 2012
On 10/24/2012 09:17 PM, Mehrdad wrote:I couldn't find a better title, sorry. But yeah, I've spent too many hours on hunting down problems like these... Could someone explain what's going on? Thanks! import std.stdio; struct S { int[int] aa; } void main() { writeln( [1: 2] == [1: 2] ); // true writeln(S([1: 2]) == S([1: 2])); // false } (I'm on Windows DMD v2.060.)http://d.puremagic.com/issues/show_bug.cgi?id=3789
Oct 24 2012
On Wednesday, 24 October 2012 at 19:25:47 UTC, Timon Gehr wrote:http://d.puremagic.com/issues/show_bug.cgi?id=3789Ouch, bug since 2010... (Thanks for the link.)
Oct 24 2012
On 10/24/12, Mehrdad <wfunction hotmail.com> wrote:Could someone explain what's going on? Thanks!Struct fields are compared by address by default if no opEquals is defined. http://d.puremagic.com/issues/show_bug.cgi?id=3789
Oct 24 2012
On 10/24/12, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:On 10/24/12, Mehrdad <wfunction hotmail.com> wrote:Well I mean for reference types. Or something like that. To put it bluntly: It's brokeeen.Could someone explain what's going on? Thanks!Struct fields are compared by address by default if no opEquals is defined. http://d.puremagic.com/issues/show_bug.cgi?id=3789
Oct 24 2012
On Wednesday, 24 October 2012 at 19:28:36 UTC, Andrej Mitrovic wrote:On 10/24/12, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:Yeah, and my attempts to get around it don't seem to help: auto a = [1:1], b = [1:1]; writeln(a == b); // true writeln(a in [a:0]); // nullOn 10/24/12, Mehrdad <wfunction hotmail.com> wrote:Well I mean for reference types. Or something like that. To put it bluntly: It's brokeeen.Could someone explain what's going on? Thanks!Struct fields are compared by address by default if no opEquals is defined. http://d.puremagic.com/issues/show_bug.cgi?id=3789
Oct 24 2012
On Wednesday, 24 October 2012 at 19:32:08 UTC, Mehrdad wrote:Yeah, and my attempts to get around it don't seem to help: auto a = [1:1], b = [1:1]; writeln(a == b); // true writeln(a in [a:0]); // nullHarsh (but true, and perhaps useful) feedback... I feel like this is a *perfect* example of the kinds of things that turn people off of D. I don't know what to expect code like this to do (unlike in C++, where everything is clearly defined in the specs), and when it seems to do what I want, it really turns out to be a bug in the library that it seemed to work in the first place. :(
Oct 24 2012
On 2012-10-24 21:37, Mehrdad wrote:I don't know what to expect code like this to do (unlike in C++, where everything is clearly defined in the specs), and when it seems to do what I want, it really turns out to be a bug in the library that it seemed to work in the first place. :(Everything in C++ is specified as undefined behavior :) -- /Jacob Carlborg
Oct 24 2012
On Wednesday, 24 October 2012 at 20:04:24 UTC, Jacob Carlborg wrote:On 2012-10-24 21:37, Mehrdad wrote:lol. I meant more like, it's clear in C++ which operations need to be implemented in order for an object to be hashable, for instance. I can't figure out how hashing works in D at all.I don't know what to expect code like this to do (unlike in C++, where everything is clearly defined in the specs), and when it seems to do what I want, it really turns out to be a bug in the library that it seemed to work in the first place. :(Everything in C++ is specified as undefined behavior :)
Oct 24 2012
On Wed, Oct 24, 2012 at 09:17:09PM +0200, Mehrdad wrote: [...]Could someone explain what's going on? Thanks! import std.stdio; struct S { int[int] aa; } void main() { writeln( [1: 2] == [1: 2] ); // true writeln(S([1: 2]) == S([1: 2])); // false }[...] I don't know if there is any struct-specific problem here, but AA comparison right now is horribly horribly broken (search on the bug tracker for "AA" and you'll see a bunch of issues on that end). You're incredibly lucky that two AA literals actually compared equal. In some cases, not even that is guaranteed. I've tried to clean up the AA code but it's a tangled messy ugly labyrinth with fragile hacks sprinkled in, and didn't get to the point where it's ready to commit. One major obstacle is that parts of it are implemented in compiler hacks, and part of it is schizophrenically duplicated in object_.d, not necessarily consistently, and it's just Not Nice in general. That it works at all is reason enough to be thankful. I don't expect things to be pretty once you start poking into the intricacies of AA's, sad to say. T -- People tell me I'm stubborn, but I refuse to accept it!
Oct 24 2012
On Wednesday, 24 October 2012 at 19:34:15 UTC, H. S. Teoh wrote:I don't know if there is any struct-specific problem here, but AA comparison right now is horribly horribly broken (search on the bug tracker for "AA" and you'll see a bunch of issues on that end). You're incredibly lucky that two AA literals actually compared equal. In some cases, not even that is guaranteed.Yeah, I was a little aware that AAs were semi-broken, but I thought, hey, if it seems to work then it obviously works. Turns out that wasn't so true. :\I've tried to clean up the AA code but it's a tangled messy ugly labyrinth with fragile hacks sprinkled in, and didn't get to the point where it's ready to commit. One major obstacle is that parts of it are implemented in compiler hacks, and part of it is schizophrenically duplicated in object_.d, not necessarily consistently, and it's just Not Nice in general. That it works at all is reason enough to be thankful. I don't expect things to be pretty once you start poking into the intricacies of AA's, sad to say.Yeah, the trouble is, none of the set-based data types (including maps) in D seem to be working... - AAs are broken - AssociativeArray is the same as above, I think? - RedBlackTree is useless (how do I keep a "set of sets"?) etc. So you can't really write a real program in D, to put it blunty.
Oct 24 2012
On Wednesday, 24 October 2012 at 19:41:42 UTC, Mehrdad wrote:So you can't really write a real program in D, to put it bluntly.Case in point: there's no way to tell an arbitrary object/struct to give you its hash code.
Oct 24 2012
On Wed, Oct 24, 2012 at 09:50:18PM +0200, Mehrdad wrote:On Wednesday, 24 October 2012 at 19:41:42 UTC, Mehrdad wrote:Huh? All objects implement toHash(). If the default toHash() doesn't satisfy you, override it with your own. You can just use rt.util.hash.hashOf for structs. Use UFCS to make it callable as toHash(). Implement your own toHash() where hashOf isn't good enough. Problem solved. T -- Once bitten, twice cry...So you can't really write a real program in D, to put it bluntly.Case in point: there's no way to tell an arbitrary object/struct to give you its hash code.
Oct 24 2012
On Wednesday, 24 October 2012 at 20:07:49 UTC, H. S. Teoh wrote:On Wed, Oct 24, 2012 at 09:50:18PM +0200, Mehrdad wrote:Not Tuples, apparently. (I didn't mean Object, I mean "object" in the general sense.)On Wednesday, 24 October 2012 at 19:41:42 UTC, Mehrdad wrote:Huh? All objects implement toHash().So you can't really write a real program in D, to put it bluntly.Case in point: there's no way to tell an arbitrary object/struct to give you its hash code.You can just use rt.util.hash.hashOf for structs.Will try, thanks for the pointer.
Oct 24 2012
On Wed, Oct 24, 2012 at 10:09:36PM +0200, Mehrdad wrote:On Wednesday, 24 October 2012 at 20:07:49 UTC, H. S. Teoh wrote:Well, Object implements toHash(). Other things don't, but with UFCS you can endow them with toHash(). :)On Wed, Oct 24, 2012 at 09:50:18PM +0200, Mehrdad wrote:Not Tuples, apparently. (I didn't mean Object, I mean "object" in the general sense.)On Wednesday, 24 October 2012 at 19:41:42 UTC, Mehrdad wrote:Huh? All objects implement toHash().So you can't really write a real program in D, to put it bluntly.Case in point: there's no way to tell an arbitrary object/struct to give you its hash code.hashOf works for pretty much anything (it's just a byte-based algo). So it's not just structs, you can pass anything to it. Using UFCS to map toHash() to hashOf will give you toHash() for literally everything, which is apparently what you want (though I question the wisdom of wanting a hash value of *everything*, including objects representing network resources, the OS, etc., but hey, you can do it if you *really* want to). T -- It won't be covered in the book. The source code has to be useful for something, after all. -- Larry WallYou can just use rt.util.hash.hashOf for structs.Will try, thanks for the pointer.
Oct 24 2012
On Wednesday, 24 October 2012 at 20:15:07 UTC, H. S. Teoh wrote:hashOf works for pretty much anything (it's just a byte-based algo).Byte-based? what about Set!(Tuple!(int, string)) s; s[tuple(1, "hi")] = 1; writeln(tuple(1, "hi".dup) in s); // null or not?
Oct 24 2012
On Wednesday, 24 October 2012 at 20:18:07 UTC, Mehrdad wrote:On Wednesday, 24 October 2012 at 20:15:07 UTC, H. S. Teoh wrote:my bad, I mixed up AA and sets. That was supposed to insert the item, not map it to 1. Would it work?hashOf works for pretty much anything (it's just a byte-based algo).Byte-based? what about Set!(Tuple!(int, string)) s; s[tuple(1, "hi")] = 1; writeln(tuple(1, "hi".dup) in s); // null or not?
Oct 24 2012
On Wed, Oct 24, 2012 at 09:41:41PM +0200, Mehrdad wrote:On Wednesday, 24 October 2012 at 19:34:15 UTC, H. S. Teoh wrote:The AA implementation badly needs to be revamped. But the problem is that it's non-trivial, may break existing code, etc.. I do have a (semi) working version of a prospective AA replacement, though: https://github.com/quickfur/New-AA-implementation You might be able to make use of it if you're willing to live with broken IFTI (which is no big deal if you just explicitly type what you instantiate the AA with).I don't know if there is any struct-specific problem here, but AA comparison right now is horribly horribly broken (search on the bug tracker for "AA" and you'll see a bunch of issues on that end). You're incredibly lucky that two AA literals actually compared equal. In some cases, not even that is guaranteed.Yeah, I was a little aware that AAs were semi-broken, but I thought, hey, if it seems to work then it obviously works. Turns out that wasn't so true. :\Yes it's the same. It's not meant to be used directly by user code, though. The two are supposed to be the same.I've tried to clean up the AA code but it's a tangled messy ugly labyrinth with fragile hacks sprinkled in, and didn't get to the point where it's ready to commit. One major obstacle is that parts of it are implemented in compiler hacks, and part of it is schizophrenically duplicated in object_.d, not necessarily consistently, and it's just Not Nice in general. That it works at all is reason enough to be thankful. I don't expect things to be pretty once you start poking into the intricacies of AA's, sad to say.Yeah, the trouble is, none of the set-based data types (including maps) in D seem to be working... - AAs are broken - AssociativeArray is the same as above, I think?- RedBlackTree is useless (how do I keep a "set of sets"?)What's wrong with RedBlackTree? You can just do something like: RedBlackTree!(RedBlackTree!MySet) setOfSets; [...]So you can't really write a real program in D, to put it blunty.That's a bit harsh. It's not hard to write your own hash implementation in D, given the expressiveness of its templates and compile-time features. The bugginess of the built-in AA is lamentable, definitely, but it doesn't *prevent* you from writing your own data structures. All programmers worth their salt should be able to roll their own where the current implementation is inadequate, anyway. ;-) In any case, as they say in the open source community, patches are always welcome. Plus, you *can* use AA's for all sorts of stuff in general, if you just avoid some of the most glaring bugs. It only takes 15 minutes to write your own opEquals() in a struct that wraps around an AA, and it's equally fast to parametrize that struct to take arbitrary types, and provide wrapper functions that work around the current bugs. None of the current issues are showstoppers, as annoying as they may be. T -- Do not reason with the unreasonable; you lose by definition.
Oct 24 2012
On Wednesday, 24 October 2012 at 20:03:44 UTC, H. S. Teoh wrote:What's wrong with RedBlackTree? You can just do something like: RedBlackTree!(RedBlackTree!MySet) setOfSets;The last time I checked two RedBlackTrees for equality, they seemed to have reference semantics...[...]Sorry, just saying what I experienced :(So you can't really write a real program in D, to put it blunty.That's a bit harsh.It's not hard to write your own hash implementation in DI beg to differ, see belowgiven the expressiveness of its templates and compile-time features. The bugginess of the built-in AA is lamentable, definitely, but it doesn't *prevent* you from writing your own data structures.It does. There's simply no mechanism to hash an arbitrary thing in D. (hashOf, which Andrej just mentioned, is an internal thing, right? aka a hack, which I was not aware of)All programmers worth their salt should be able to roll their own where the current implementation is inadequate, anyway. ;-)Well, there's different issues involved... - Can I? Yes. - Will I? No, it takes more time than it's worthIn any case, as they say in the open source community, patches are always welcome.Yeah, it's just that I can't figure out even the basics of hashing in D (above), so I can't really patch something because then it'll turn out to be working in a different way than I expect.It only takes 15 minutes to write your own opEquals() in a struct that wraps around an AAI've spent longer than that right now and still haven't been able to (but I haven't tried the hashOf hack yet). Maybe you can fill in the blanks? struct Set(T) { int[T] dict; hash_t toHash() const { typeof(return) r = 0; foreach (item; this.dict.keys) { ??? // what should be here? } return r; } }
Oct 24 2012
On Wed, Oct 24, 2012 at 10:16:27PM +0200, Mehrdad wrote: [...]struct Set(T) { int[T] dict; hash_t toHash() const { typeof(return) r = 0; foreach (item; this.dict.keys) { ??? // what should be here? } return r; } }Try this: hash_t toHash() const { hash_t h = 0; foreach (item; this.dict.keys) { // We use a commutative operation here (+) so // that the order of keys don't matter. h += hashOf(&item, item.sizeof); } return h; } T -- What do you get if you drop a piano down a mineshaft? A flat minor.
Oct 24 2012
On Wednesday, 24 October 2012 at 20:37:08 UTC, H. S. Teoh wrote:On Wed, Oct 24, 2012 at 10:16:27PM +0200, Mehrdad wrote: [...]Wouldn't that do a bitwise comparison?struct Set(T) { int[T] dict; hash_t toHash() const { typeof(return) r = 0; foreach (item; this.dict.keys) { ??? // what should be here? } return r; } }Try this: hash_t toHash() const { hash_t h = 0; foreach (item; this.dict.keys) { // We use a commutative operation here (+) so // that the order of keys don't matter. h += hashOf(&item, item.sizeof); } return h; } T
Oct 24 2012
On Wednesday, 24 October 2012 at 20:38:08 UTC, Mehrdad wrote:Wouldn't that do a bitwise comparison?sorry, I mean bitwise _hash_
Oct 24 2012
On Wed, Oct 24, 2012 at 10:38:07PM +0200, Mehrdad wrote:On Wednesday, 24 October 2012 at 20:37:08 UTC, H. S. Teoh wrote:Umm, the idea of a hash is to *quickly* compute a value that's (mostly) unique for a given object. In most cases, the bit representation is good enough. If you want a thorough recursive comparison of all subobjects, you should overload opEquals and use that instead. Or use compile-time reflection to iterate over every member of the given object and recursively iterate and hash them. Though I fail to see the point of it, since it defeats the purpose of a hash in the first place - you might as well just do the usual recursive compare instead. T -- Never step over a puddle, always step around it. Chances are that whatever made it is still dripping.On Wed, Oct 24, 2012 at 10:16:27PM +0200, Mehrdad wrote: [...]Wouldn't that do a bitwise comparison?struct Set(T) { int[T] dict; hash_t toHash() const { typeof(return) r = 0; foreach (item; this.dict.keys) { ??? // what should be here? } return r; } }Try this: hash_t toHash() const { hash_t h = 0; foreach (item; this.dict.keys) { // We use a commutative operation here (+) so // that the order of keys don't matter. h += hashOf(&item, item.sizeof); } return h; } T
Oct 24 2012
On Wednesday, 24 October 2012 at 20:47:30 UTC, H. S. Teoh wrote:Umm, the idea of a hash is to *quickly* compute a value that's (mostly) unique for a given object. In most cases, the bit representation is good enough.I don't understand what you're saying. hash(tuple("foo".dup)) MUST be equal to hash(tuple("foo".dup")). Bitwise hashing makes no sense whatsoever.
Oct 24 2012
Is there any reason why we don't have something like this in Phobos? hash_t toHash(T)(in T t) if (isIntegral!(T) || isSomeChar!(T)) { return t; } hash_t toHash(T)(in T[] t) { typeof(return) h = 0; foreach (item; t) { h = h * 37 + item.toHash(); } return h; } hash_t toHash(T)(in T t) if (!isIntegral!(T) && !isSomeChar!(T) && !isArray!(T)) { typeof(return) h = 0; foreach (ref a; t.tupleof) { h = h * 37 + a.toHash(); } return h; } hash_t toHash(T...)(in Tuple!(T) t) { typeof(return) h = 0; foreach (item; t) { h = h * 37 + item.toHash(); } return h; }
Oct 24 2012
Better example: private import std.traits, std.typecons, std.typetuple; hash_t toHash(T)(in T t) if (isIntegral!(T) || isSomeChar!(T)) { return t; } hash_t toHash(T)(in T[] t) { typeof(return) h = 0; foreach (item; t) { h = (h * 37) ^ item.toHash(); } return h; } hash_t toHash(V, K)(in V[K] t) { typeof(return) h = 0; foreach (k, v; t) { h ^= k.toHash(); } return h; } hash_t toHash(T)(in T t) if (!isIntegral!(T) && !isSomeChar!(T) && !isArray!(T) && !isAssociativeArray!(T)) { typeof(return) h = 0; foreach (ref a; t.tupleof) { h = (h * 37) ^ a.toHash(); } return h; } void main() { import std.stdio; writeln(tuple("hi", [[1: 2].keys.dup], [1: 2, 8: 4]).toHash()); writeln(tuple("hi", [[1: 2].keys.dup], [1: 2, 8: 4]).toHash()); // same thing as above } We really _need_ something like this in Phobos IMHO.
Oct 24 2012
On 10/24/2012 10:16 PM, Mehrdad wrote:... Maybe you can fill in the blanks?import std.stdio; struct Set(T){ int[T] dict; hash_t toHash() const{ typeof(return) r = 0; foreach(item; this.dict.keys){ r+=typeid(T).getHash(&item); } return r; } }
Oct 24 2012
On Wednesday, 24 October 2012 at 21:55:11 UTC, Timon Gehr wrote:On 10/24/2012 10:16 PM, Mehrdad wrote:I'm on my phone so I can't test it right now, but I'm wondering how that would possibly work correctly for Tuples and such?... Maybe you can fill in the blanks?import std.stdio; struct Set(T){ int[T] dict; hash_t toHash() const{ typeof(return) r = 0; foreach(item; this.dict.keys){ r+=typeid(T).getHash(&item); } return r; } }
Oct 24 2012
On 10/24/2012 01:16 PM, Mehrdad wrote:On Wednesday, 24 October 2012 at 20:03:44 UTC, H. S. Teoh wrote:Dang. import std.container; import std.stdio; void main() { auto a = make!(RedBlackTree!int)(1,2,3,4); auto b = make!(RedBlackTree!int)(1,2,3,4); writeln(a == b); } prints false Explanation: RedBlackTree doesn't override opEquals. Either file an enhancement request or use equal(a[], b[]), depending on whether opEquals *should* have reference semantics. Actually, it shouldn't, since that would differ from array/string opEquals semantics. SList works Array works Oop. DList goes into infinite loop. Dibs on this bug report.What's wrong with RedBlackTree? You can just do something like: RedBlackTree!(RedBlackTree!MySet) setOfSets;The last time I checked two RedBlackTrees for equality, they seemed to have reference semantics...
Oct 25 2012
On Thu, Oct 25, 2012 at 06:34:32PM -0700, Ellery Newcomer wrote:On 10/24/2012 01:16 PM, Mehrdad wrote:Hmph. This is what I don't like about the built-in ==. Its semantics are inconsistent once you leave the realm of ints and floats and other numerical types. I think this one is worthy of a bug report.On Wednesday, 24 October 2012 at 20:03:44 UTC, H. S. Teoh wrote:Dang. import std.container; import std.stdio; void main() { auto a = make!(RedBlackTree!int)(1,2,3,4); auto b = make!(RedBlackTree!int)(1,2,3,4); writeln(a == b); } prints false Explanation: RedBlackTree doesn't override opEquals. Either file an enhancement request or use equal(a[], b[]), depending on whether opEquals *should* have reference semantics.What's wrong with RedBlackTree? You can just do something like: RedBlackTree!(RedBlackTree!MySet) setOfSets;The last time I checked two RedBlackTrees for equality, they seemed to have reference semantics...Actually, it shouldn't, since that would differ from array/string opEquals semantics.Yeah, Jonathan is right, "==" should *always* do a deep compare, and leave "is" to do a shallow compare. Anything else is inconsistent, and leads to all kinds of pathological bugs. T -- Любишь кататься - люби и саночки возить.
Oct 25 2012
On 10/25/2012 09:19 PM, H. S. Teoh wrote:Hmph. This is what I don't like about the built-in ==. Its semantics are inconsistent once you leave the realm of ints and floats and other numerical types. I think this one is worthy of a bug report.Well, if nobody else is going to take it http://d.puremagic.com/issues/show_bug.cgi?id=8896
Oct 25 2012
On Wednesday, 24 October 2012 at 19:41:42 UTC, Mehrdad wrote:So you can't really write a real program in D, to put it blunty.So should I drop a project I'm working on and go to C++? That isn't something I look forward to doing...
Oct 24 2012
On Wednesday, 24 October 2012 at 21:55:53 UTC, Era Scarecrow wrote:On Wednesday, 24 October 2012 at 19:41:42 UTC, Mehrdad wrote:Well if it's been working for you then there's obviously no reason to. :) I couldn't say the same thing, though.So you can't really write a real program in D, to put it blunty.So should I drop a project I'm working on and go to C++? That isn't something I look forward to doing...
Oct 24 2012
On 10/24/12 8:53 PM, Mehrdad wrote:On Wednesday, 24 October 2012 at 21:55:53 UTC, Era Scarecrow wrote:OK let's stop this. There's a bug that needs fixing, is all. AndreiOn Wednesday, 24 October 2012 at 19:41:42 UTC, Mehrdad wrote:Well if it's been working for you then there's obviously no reason to. :) I couldn't say the same thing, though.So you can't really write a real program in D, to put it blunty.So should I drop a project I'm working on and go to C++? That isn't something I look forward to doing...
Oct 24 2012
On Thursday, 25 October 2012 at 01:01:10 UTC, Andrei Alexandrescu wrote:OK let's stop this. There's a bug that needs fixing, is all. AndreiSorry, yeah. It was just that I came across it so much that I wanted to put it on the radar here, to let you guys know what sorts of problems you'd run into when you try using D. It was meant to be honest feedback, that's all... I realize it was negative hopefully it was at least constructive. Any opinions on my proposed "fixed" version, which used .tupleof?
Oct 24 2012
On Wednesday, October 24, 2012 21:01:11 Andrei Alexandrescu wrote:OK let's stop this. There's a bug that needs fixing, is all.And as bad as things may be now, they're _way_ better than they were a couple of years ago (or even a year ago). The situation isn't perfect, but it's constantly improving. It's becoming rarer and rarer for programmers to run into compiler bugs. You can actually write plenty of programmers now without running into any, whereas before, you'd run into them all the time. - Jonathan M Davis
Oct 24 2012
On Thursday, 25 October 2012 at 02:55:20 UTC, Jonathan M Davis wrote:On Wednesday, October 24, 2012 21:01:11 Andrei Alexandrescu wrote:Yeah that's definitely very true. :) Sorry that the negative feedback seems to drown out anything that looks positive... but I've definitely noticed the improvement (and that's what makes me come back and try writing a program in D every once in a while). Props to you guys for the work!OK let's stop this. There's a bug that needs fixing, is all.And as bad as things may be now, they're _way_ better than they were a couple of years ago (or even a year ago). The situation isn't perfect, but it's constantly improving. It's becoming rarer and rarer for programmers to run into compiler bugs. You can actually write plenty of programmers now without running into any, whereas before, you'd run into them all the time. - Jonathan M Davis
Oct 24 2012
Le 25/10/2012 03:35, Jonathan M Davis a écrit :On Wednesday, October 24, 2012 21:01:11 Andrei Alexandrescu wrote:Is this a joke ? That is true that many bug get solved, but I encounter compiler bugs almost on a daily basis, and a lot of workaround are present in my codebase. I'm ready to heard that I run into more bugs due to my coding style or whatever, but I have hard time to understand how running into compiler bugs can be rarer and rarer. You can actually write plenty of programmers now withoutOK let's stop this. There's a bug that needs fixing, is all.And as bad as things may be now, they're _way_ better than they were a couple of years ago (or even a year ago). The situation isn't perfect, but it's constantly improving. It's becoming rarer and rarer for programmers to run into compiler bugs.running into any, whereas before, you'd run into them all the time. - Jonathan M Davis
Oct 26 2012
On Thursday, 25 October 2012 at 00:53:31 UTC, Mehrdad wrote:On Wednesday, 24 October 2012 at 21:55:53 UTC, Era ScarecrowYou can always work around what does and doesn't work; Although preferably you shouldn't have to. I can only think that the best way to support the D language is simply to use it. If there's several programs that really get attention that shows the flexibility and use of D then it's more likely to be used. My biggest obstacle(s) right now is time & memory. With new issues coming up it makes you think in different directions, which all makes sense once you look for them.So should I drop a project I'm working on and go to C++? That isn't something I look forward to doing...Well if it's been working for you then there's obviously no reason to. :) I couldn't say the same thing, though.
Oct 24 2012
On Thursday, 25 October 2012 at 01:36:00 UTC, Era Scarecrow wrote:On Thursday, 25 October 2012 at 00:53:31 UTC, Mehrdad wrote:Well I mean, yeah, you can obviously implement your own data structures, and eventually, your own version of Phobos, even. The trouble is, then you're fighting the framework, and nothing integrates with anything else. Some data structure expects a toHash() instance method, another expects .hashOf, another getHash(), another getHashCode(), another might say hashCode(), and yet another might just expect a template specialization, like in C++. So the point is, yes, it's possible. It's not that I can't work around it, but it defeats the whole purpose of switching to D.On Wednesday, 24 October 2012 at 21:55:53 UTC, Era ScarecrowYou can always work around what does and doesn't work; Although preferably you shouldn't have to.So should I drop a project I'm working on and go to C++? That isn't something I look forward to doing...Well if it's been working for you then there's obviously no reason to. :) I couldn't say the same thing, though.
Oct 24 2012
On Thursday, 25 October 2012 at 01:50:05 UTC, Mehrdad wrote:Well I mean, yeah, you can obviously implement your own data structures, and eventually, your own version of Phobos, even. The trouble is, then you're fighting the framework, and nothing integrates with anything else. Some data structure expects a toHash() instance method, another expects .hashOf, another getHash(), another getHashCode(), another might say hashCode(), and yet another might just expect a template specialization, like in C++. So the point is, yes, it's possible. It's not that I can't work around it, but it defeats the whole purpose of switching to D.I have no intention of writing a different version of phobos or breaking the framework. I'll work within the framework as much as possible; Working around the issues usually ends up force casting something so you can get the job done (but you still need to honor the type's original contract). I'll just hope my data processing won't require anything that's broken or going to be depreciated, I've already dropped using std.stream for ranges instead. Dropping classes in favor of structs.
Oct 24 2012
On Thu, Oct 25, 2012 at 04:08:21AM +0200, Era Scarecrow wrote: [...]I'll just hope my data processing won't require anything that's broken or going to be depreciated, I've already dropped using std.stream for ranges instead. Dropping classes in favor of structs.Huh? Why would you drop classes in favor of structs? They are used for two different purposes. Classes are for when you need polymorphism: inheritance, overloading, interfaces, all the trappings of OO programming. Structs are for when you need value types that doesn't need OO-style manipulations. Not the same thing. T -- One Word to write them all, One Access to find them, One Excel to count them all, And thus to Windows bind them. -- Mike Champion
Oct 24 2012
On Thursday, 25 October 2012 at 02:19:39 UTC, H. S. Teoh wrote:Huh? Why would you drop classes in favor of structs? They are used for two different purposes. Classes are for when you need polymorphism: inheritance, overloading, interfaces, all the trappings of OO programming. Structs are for when you need value types that doesn't need OO-style manipulations. Not the same thing.Indeed. Instead of interfaces you'd use templates, OO doesn't change really all that much. There's also large amounts of memory consumption that just isn't needed for data that hasn't and/or isn't going to change. More often I'm thinking structs w/templates are more powerful than classes. I'm experimenting with a polymorphic struct. Run-time price is a couple enum checks if there's multiple functions that might qualify, and slightly different calling for those polymorphic types.
Oct 24 2012
On Thu, Oct 25, 2012 at 04:46:04AM +0200, Era Scarecrow wrote:On Thursday, 25 October 2012 at 02:19:39 UTC, H. S. Teoh wrote:[...] Used correctly, *classes* with templates can be pretty powerful too. Recently I wrote an expression parser that can either parse the expression into a tree, or compute its value on-the-fly. I didn't like the idea of duplicating the parser code for both usages, so I decided to turn the parser into a template that would do one or the other. The template would call a static class method at key points during the parse, which alleviates the parser from knowing (or caring) what was done with the parsed expression -- the method could build a tree, or evaluate the expression, etc.. While I was coding that, I realized that lots of code is still being duplicated -- for example, to implement building a tree with +, -, *, and / operators _and_ to evaluate the same operators on-the-fly, required that operator-specific code be written in both classes. That was when I realized that I can leverage inheritance by factoring the operator-specific code into the base class, and overriding the static method in the derived class so that when the parser was instantiated with the base class, it built an expression tree, whereas when instantiated with the derived class, it would evaluate the expression. And moreover, the return type of the parser would be the derived class, so the caller doesn't even need to downcast to read the computed value. And all the while, the derived class can also be used as leaf nodes in the full expression tree, when building the latter. So even though things like templated virtual methods don't work, you *can* still make pretty potent combinations of templates + classes. T -- Doubtless it is a good thing to have an open mind, but a truly open mind should be open at both ends, like the food-pipe, with the capacity for excretion as well as absorption. -- Northrop FryeHuh? Why would you drop classes in favor of structs? They are used for two different purposes. Classes are for when you need polymorphism: inheritance, overloading, interfaces, all the trappings of OO programming. Structs are for when you need value types that doesn't need OO-style manipulations. Not the same thing.Indeed. Instead of interfaces you'd use templates, OO doesn't change really all that much. There's also large amounts of memory consumption that just isn't needed for data that hasn't and/or isn't going to change. More often I'm thinking structs w/templates are more powerful than classes.
Oct 24 2012
Funny, I was actually building a (GLR) parser, too. Keeping track of duplicate item sets was what tripped me up.
Oct 24 2012
On Thu, Oct 25, 2012 at 05:34:05AM +0200, Mehrdad wrote:Funny, I was actually building a (GLR) parser, too. Keeping track of duplicate item sets was what tripped me up.Oh. You should've said so earlier -- for such specific applications, you don't _need_ a fully generalized solution to the AA hash problem. You can just implement your own .toHash methods on the structs/objects your parser uses, and be done with it. No need to try to accomodate every single type D has or can have -- that's the kind of thing Phobos developers have to worry about, not people who have a specific application in mind. I've learnt from hard experience that premature generalization is just as evil as premature optimization. (Believe me, I'm a sucker for completely general solutions too -- I like killing ants with nuclear warheads, proverbially speaking, just for the feeling of confidence that that it would've also worked in the hypothetical scenario of levelling an entire city.) You usually end up completely frustrated that the system/language you're using just doesn't have that one last bit of homogeneity for your generalization to fully work, and eventually the project never gets off the ground. But in many cases, I've learned, this is all needless pain. Write the case-specific code first, and then refactor and generalize it afterwards. Works much better, I find, and you have a tangible product to speak of from the get-go, instead of spending countless hours writing a generic framework that eventually never gets used. Plus, when you actually have a *working* codebase, exactly which generalizations will work, and which are just castles in the air, tend to be a lot more obvious than when you're just sketching the product on the drawing board. Just my slightly more than $0.02. :) T -- English has the lovely word "defenestrate", meaning "to execute by throwing someone out a window", or more recently "to remove Windows from a computer and replace it with something useful". :-) -- John Cowan
Oct 24 2012
Haha thanks a bunch for the advice. :) I was actually intending it to be a quick hack, not a highly-generalized thing. So I thought, hey, I'll just use a Tuple!(string, q{symbol}, size_t, q{iRule}, size_t, q{iSymbol}) to denote an "LR Item". So an "item set" became RedBlackTree!(Tuple!(...)), but that didn't work because of the reference semantics. So I tried int[Tuple!(...)], and hence the story. (I actually even scrapped the idea of using a 'set' and just used an array. Screw the O(n) performance. But one of my goals was getting the code to be concise (the idea was to use CTFE + mixins/templates to generate some optimized code with switch statements for the parser), but sprinkling it with all the sort()s and all the code required to switch from hashtables to arrays just made it too ugly/indecipherable for me to continue working on it.) etc. But yeah, thanks for the advice, I'll keep it in mind. :)
Oct 24 2012
On Thu, Oct 25, 2012 at 06:21:02AM +0200, Mehrdad wrote:Haha thanks a bunch for the advice. :) I was actually intending it to be a quick hack, not a highly-generalized thing. So I thought, hey, I'll just use a Tuple!(string, q{symbol}, size_t, q{iRule}, size_t, q{iSymbol}) to denote an "LR Item".[...] Hmm, why are you using Tuple? Shouldn't you be using a struct? T -- People tell me I'm stubborn, but I refuse to accept it!
Oct 24 2012
On Thursday, 25 October 2012 at 04:39:28 UTC, H. S. Teoh wrote:On Thu, Oct 25, 2012 at 06:21:02AM +0200, Mehrdad wrote:Hmm, why would I prefer a struct over a Tuple? I see it as, like, coordinates -- the index of the symbol in the production, and the index of the production for a given nonterminal symbol. So tuple(x, y, z) kinda made sense. Especially since I was going back/forth between D & Python.Haha thanks a bunch for the advice. :) I was actually intending it to be a quick hack, not a highly-generalized thing. So I thought, hey, I'll just use a Tuple!(string, q{symbol}, size_t, q{iRule}, size_t, q{iSymbol}) to denote an "LR Item".[...] Hmm, why are you using Tuple? Shouldn't you be using a struct? T
Oct 24 2012
On Thu, Oct 25, 2012 at 5:34 AM, Mehrdad <wfunction hotmail.com> wrote:Funny, I was actually building a (GLR) parser, too. Keeping track of duplicate item sets was what tripped me up.H. S. Teoh, Mehrdad: are your codebases in a public website?
Oct 24 2012
On Thursday, 25 October 2012 at 05:11:38 UTC, Philippe Sigaud wrote:On Thu, Oct 25, 2012 at 5:34 AM, Mehrdad <wfunction hotmail.com> wrote:Nope. I'll consider releasing it when I make it decent, but right now, there's really nothing to put anywhere. (I've probably re-started like 6 times now, like twice with each language. Each one had its own downfalls; I tried D because I thought it would have great opportunities with CTFE and mixins. But so far the code has always been ugly and I've run into the problem of not really wanting to debug my own code.)Funny, I was actually building a (GLR) parser, too. Keeping track of duplicate item sets was what tripped me up.H. S. Teoh, Mehrdad: are your codebases in a public website?
Oct 24 2012
Actually, I think I might as well send you a link to something I https://gist.github.com/203f8d65b60fe2d75339 Grab it before it's gone ;) I might delete it at some point. It was meant to be my stab at what I _thought_ a "recursive ascent-descent parser" should do. I really have no idea if it's correct or not, so be careful. I also don't know if the code is buggy or not, so... yeah.
Oct 24 2012
On Thu, Oct 25, 2012 at 7:51 AM, Mehrdad <wfunction hotmail.com> wrote:Actually, I think I might as well send you a link to something I had in https://gist.github.com/203f8d65b60fe2d75339 Grab it before it's gone ;) I might delete it at some point.Thanks :)
Oct 25 2012
On 10/24/2012 09:41 PM, Mehrdad wrote:... So you can't really write a real program in D, to put it blunty.Yes I can.
Oct 24 2012
On Wednesday, 24 October 2012 at 22:00:27 UTC, Timon Gehr wrote:On 10/24/2012 09:41 PM, Mehrdad wrote:So you made your own AA and Set implementations instead of trying to use Photos? Or did you never run into these problems?... So you can't really write a real program in D, to put it blunty.Yes I can.
Oct 24 2012
On 10/25/2012 12:22 AM, Mehrdad wrote:On Wednesday, 24 October 2012 at 22:00:27 UTC, Timon Gehr wrote:I have written a custom hash map.On 10/24/2012 09:41 PM, Mehrdad wrote:So you made your own AA and Set implementations instead of trying to use Photos?... So you can't really write a real program in D, to put it blunty.Yes I can.Or did you never run into these problems?It is actually hard to miss them.
Oct 24 2012
On 2012-10-24 21:41, Mehrdad wrote:Yeah, the trouble is, none of the set-based data types (including maps) in D seem to be working... - AAs are broken - AssociativeArray is the same as above, I think? - RedBlackTree is useless (how do I keep a "set of sets"?) etc. So you can't really write a real program in D, to put it blunty.I haven't read the rest of thread yet but if you're not happy the the collections in D or Phobos, Tango has a collection package and Steven Schveighoffer has a collection library (don't remember where though). -- /Jacob Carlborg
Oct 24 2012
On 10/24/2012 12:17 PM, Mehrdad wrote:I couldn't find a better title, sorry. But yeah, I've spent too many hours on hunting down problems like these... Could someone explain what's going on? Thanks! import std.stdio; struct S { int[int] aa; } void main() { writeln( [1: 2] == [1: 2] ); // true writeln(S([1: 2]) == S([1: 2])); // false } (I'm on Windows DMD v2.060.)The compare for associative arrays is to compare the members. The default compare for structs is a bit compare of the contents.
Oct 24 2012
On Wednesday, 24 October 2012 at 20:32:00 UTC, Walter Bright wrote:The default compare for structs is a bit compare of the contents.Thanks for the reply. And hmm, that should be changed IMO. ;) Bitwise comparison is nearly useless.
Oct 24 2012
On Wednesday, October 24, 2012 13:31:14 Walter Bright wrote:The default compare for structs is a bit compare of the contents.Which definitely seems inherently broken. Doing that only works if the struct only contains integral types, character types, or bool. Nothing else will compare properly that way. It really needs to work like arrays do (or are supposed to anyway) and compare each member according to == and only fallback to an outright bitwise compare when it knows that the results would be identical (i.e. because all of the members are integral types, character types, bool, or other structs which hold only integral types, character types, or bool - be it directly or in other structs that they hold). Bitwise comparison is the is operator's job, not ==. - Jonathan M Davis
Oct 24 2012
On Thursday, 25 October 2012 at 02:12:58 UTC, Jonathan M Davis wrote:On Wednesday, October 24, 2012 13:31:14 Walter Bright wrote:+1 I can only agree with this. People who monitor the NG know about the problem but it is probably very confusing to D newbies.The default compare for structs is a bit compare of the contents.Which definitely seems inherently broken. Doing that only works if the struct only contains integral types, character types, or bool. Nothing else will compare properly that way. It really needs to work like arrays do (or are supposed to anyway) and compare each member according to == and only fallback to an outright bitwise compare when it knows that the results would be identical (i.e. because all of the members are integral types, character types, bool, or other structs which hold only integral types, character types, or bool - be it directly or in other structs that they hold). Bitwise comparison is the is operator's job, not ==. - Jonathan M Davis
Oct 25 2012
Le 25/10/2012 04:12, Jonathan M Davis a écrit :On Wednesday, October 24, 2012 13:31:14 Walter Bright wrote:That will broke code. But That is the way to go IMO. D needs to evolve to make things more consistent in general. Still not doable without a proper versionning scheme.The default compare for structs is a bit compare of the contents.Which definitely seems inherently broken. Doing that only works if the struct only contains integral types, character types, or bool. Nothing else will compare properly that way. It really needs to work like arrays do (or are supposed to anyway) and compare each member according to == and only fallback to an outright bitwise compare when it knows that the results would be identical (i.e. because all of the members are integral types, character types, bool, or other structs which hold only integral types, character types, or bool - be it directly or in other structs that they hold). Bitwise comparison is the is operator's job, not ==. - Jonathan M Davis
Oct 26 2012
On Friday, October 26, 2012 19:46:16 deadalnix wrote:Le 25/10/2012 04:12, Jonathan M Davis a =C3=A9crit :theOn Wednesday, October 24, 2012 13:31:14 Walter Bright wrote:The default compare for structs is a bit compare of the contents.=20 Which definitely seems inherently broken. Doing that only works if =ingstruct only contains integral types, character types, or bool. Noth=rrayselse will compare properly that way. It really needs to work like a==3D=3Ddo (or are supposed to anyway) and compare each member according to=theand only fallback to an outright bitwise compare when it knows that=egralresults would be identical (i.e. because all of the members are int=graltypes, character types, bool, or other structs which hold only inte=s thattypes, character types, or bool - be it directly or in other struct=.they hold). Bitwise comparison is the is operator's job, not =3D=3D=TDPL clearly states that each of the struct's members are supposed to b= e=20 checked for equality (see section 7.1.5.2, p. 258 - 259). It's outright= a bug=20 for structs to be checked for equality with a bitwise comparison when t= he=20 bitwise comparison does not do exactly what =3D=3D would have done had = each and=20 every member variable been compared with =3D=3D. And as with all bugs, = fixing it=20 could break code which depends on the buggy behavior. But given the nat= ure of=20 this bug, I seriously question that much of anyone thought that the =3D= =3D on=20 structs was supposed to do anything other than what TDPL states that it= should=20 and that pretty much no one was expecting it to do a bitwise comparison= . So,=20 if anything, this will _fix_ far more code than it breaks. - Jonathan M Davis=20 - Jonathan M Davis=20 That will broke code. =20 But That is the way to go IMO. D needs to evolve to make things more consistent in general. =20 Still not doable without a proper versionning scheme.
Oct 27 2012
On Sat, Oct 27, 2012 at 07:52:37PM -0700, Jonathan M Davis wrote: [...]TDPL clearly states that each of the struct's members are supposed to be checked for equality (see section 7.1.5.2, p. 258 - 259). It's outright a bug for structs to be checked for equality with a bitwise comparison when the bitwise comparison does not do exactly what == would have done had each and every member variable been compared with ==. And as with all bugs, fixing it could break code which depends on the buggy behavior. But given the nature of this bug, I seriously question that much of anyone thought that the == on structs was supposed to do anything other than what TDPL states that it should and that pretty much no one was expecting it to do a bitwise comparison. So, if anything, this will _fix_ far more code than it breaks.[...] +1. I have to say I was surprised to find out about this after I started using D; after first reading TDPL, I had the impression that it was supposed to do the "right thing" (and the right thing being == on each field, which I assumed the compiler would optimize into a bitwise compare where possible). Let's fix this. T -- He who does not appreciate the beauty of language is not worthy to bemoan its flaws.
Oct 27 2012
On Sunday, 28 October 2012 at 05:28:20 UTC, H. S. Teoh wrote:I have to say I was surprised to find out about this after I started using D; after first reading TDPL, I had the impression that it was supposed to do the "right thing" (and the right thing being == on each field, which I assumed the compiler would optimize into a bitwise compare where possible). Let's fix this.There is a problem with floating point memebers, since nan values will always compare false. There's other things in D that bother me, such as how struc pointers are managed, where they sometimes behave exactly like class references, but not always. The inconsistent behaviour is a trap for the programmer to fall into, and it leads to subtle hard to find errors. For example: struct S { int a; ~this() {} } class C { int a; ~this() {} } // identical behaviour auto Sp = new S; auto Cr = new C; // identical behaviour writeln(Sp.a); writeln(Cr.a); // identical behaviour auto Sp2 = Sp; auto Cr2 = Cr; writeln(Sp2.a); writeln(Cr2.a); // ? assert(Sp2 == Sp); assert(Cr2 == Cr); // different behaviour! clear(Sp); clear(Cr); Last two line compile OK, but clear(Sp) does not invoke the destructor while clear(Cr) does. clear(*Sp) works, but why allow clear(Sp) if it's a pointless operation? Is this a bug in the compiler or with the language design? Subtle differences like this are very nasty. The code should behave identically for both the struct pointer and the class reference, and if this is not poosible for some obscure reason, then the compiler should fail at the clear(Sp) line. If I invoke with clear(*Sp) it works, but the inconsistency makes template code that takes in both a struct or a class impossible to do (or at best needlessly difficult to do). --rt
Oct 29 2012
On Mon, Oct 29, 2012 at 06:34:14PM +0100, Rob T wrote: [...]There is a problem with floating point memebers, since nan values will always compare false.This is IEEE specification. There is no problem. T -- Frank disagreement binds closer than feigned agreement.
Oct 29 2012
On Monday, 29 October 2012 at 18:39:41 UTC, H. S. Teoh wrote:On Mon, Oct 29, 2012 at 06:34:14PM +0100, Rob T wrote: [...]If struc comparisions compare value by value, and both have Nan values in one member variable, then the two otherwise completely identical structs will always compare false even though they are identical. I think it would be best to have the ability to compare structs in two ways, one as struct equivalence, which would be the default method, the other as vale by value equivalence, which would have to be programmer defined through overload of == operator. --rtThere is a problem with floating point memebers, since nan values will always compare false.This is IEEE specification. There is no problem. T
Oct 29 2012
On Monday, 29 October 2012 at 19:55:41 UTC, Rob T wrote:On Monday, 29 October 2012 at 18:39:41 UTC, H. S. Teoh wrote:I understand the problem, but it doesn't seem related to structs at all. Any two attempts to compare two default-valued floats will fail, irrespective of whether or not they're inside structs.On Mon, Oct 29, 2012 at 06:34:14PM +0100, Rob T wrote: [...]If struc comparisions compare value by value, and both have Nan values in one member variable, then the two otherwise completely identical structs will always compare false even though they are identical. I think it would be best to have the ability to compare structs in two ways, one as struct equivalence, which would be the default method, the other as vale by value equivalence, which would have to be programmer defined through overload of == operator. --rtThere is a problem with floating point memebers, since nan values will always compare false.This is IEEE specification. There is no problem. T
Oct 29 2012
On Tuesday, 30 October 2012 at 02:27:30 UTC, Mehrdad wrote:I understand the problem, but it doesn't seem related to structs at all. Any two attempts to compare two default-valued floats will fail, irrespective of whether or not they're inside structs.True at the level of float by float comparisons, but not necessarilly true when struct by struct bit pattern compares are done. My original understandiong of the struct type in D, is that it is defined as a POD which means == (without override) is done as a simple bit pattern compare, rather than doing a value by value compare of member data types. If this is the case, then two structs with default valued equivalent float types should compare equal, even though a value by value compare would compare not equal.TDPL clearly states that each of the struct's members are supposed to be checked for equality (see section 7.1.5.2, p. 258 - 259).So I guess that the POD definition of struct was changed at some point? If so, then how are value by value compares performed when unions are involved? What about when there are member pointers, and other structures that cannot be compared in a meaningful way by default? I guess the question is if the bit pattern comparision of structs has sufficient justification to be worth having as the default behaviour, or if there is more value attempting a value by value comparision, even though in many situations it may be pointless to attempt either strategy. In my experience, I cannot recall doing very many direct struct comparisons either as a complete value by value compare or as a full bit pattern compare, I just never found it to be all that useful, no matter, I can try and imagine both strategies being useful in some situations. With operator overloading you can have both strategies, but only if bit pattern compare is the default stategy, plus with overloading, compare can do exactly what you want to make sense out of unions and pointers, etc. So we should be good as is. I would expect that most times no one compares structs fully by value or by bit pattern anyway, to do so very often is difficult for me to imagine, but I could be wrong. --rt
Oct 30 2012
On Tuesday, October 30, 2012 08:14:59 Rob T wrote:Structs never were just PODs in D. They have _way_ more capabilities to them than that. If you want bitwise comparison, then use the is operator. That's what it's for. - Jonathan M DavisTDPL clearly states that each of the struct's members are supposed to be checked for equality (see section 7.1.5.2, p. 258 - 259).So I guess that the POD definition of struct was changed at some point?
Oct 30 2012
On Tuesday, 30 October 2012 at 07:22:30 UTC, Jonathan M Davis wrote:On Tuesday, October 30, 2012 08:14:59 Rob T wrote:I do understand what you are saying, however the docs in here describe structs as POD's, with the capabilities you mention. http://dlang.org/glossary.html#podStructs never were just PODs in D. They have _way_ more capabilities to them than that.TDPL clearly states that each of the struct's members are supposed to be checked for equality (see section 7.1.5.2, p. 258 - 259).So I guess that the POD definition of struct was changed at some point?If you want bitwise comparison, then use the is operator. That's what it's for.Where can I find an up-to-date language reference? What I'm reading does not seem to be up to date or complete. For example, I never saw mention of the "is" operator until now. --rt
Oct 30 2012
On Tuesday, October 30, 2012 08:37:47 Rob T wrote:Where can I find an up-to-date language reference? What I'm reading does not seem to be up to date or complete. For example, I never saw mention of the "is" operator until now.It's in the online docs: http://dlang.org/expression.html It's in the "Identity Expressions" section. The best reference is TDPL though. - Jonathan M Davis
Oct 30 2012
Where can I find an up-to-date language reference? What I'm reading does not seem to be up to date or complete. For example, I never saw mention of the "is" operator until now. --rtIt's hard to find because it can not be overloaded. Look here: http://dlang.org/expression.html#IdentityExpression In TDPL it's explained as well.
Oct 30 2012
On Tue, Oct 30, 2012 at 08:57:01AM +0100, Tobias Pankrath wrote:Sigh, one of these days I'm gonna have to rewrite many of these pages. I find them very hard to navigate and very unfriendly to newbies, because very basic information (like what 'is' is) is buried deep in long verbose infodumps of diverse language features, with no indication at all which are fundamental concepts and which are just details. It's virtually impossible to find what you're looking for unless you already know what it is. TDPL lays things out in a much saner fashion, but how many newbies actually own the book? We need the online docs to be just as newbie-friendly. T -- MSDOS = MicroSoft's Denial Of ServiceWhere can I find an up-to-date language reference? What I'm reading does not seem to be up to date or complete. For example, I never saw mention of the "is" operator until now. --rtIt's hard to find because it can not be overloaded. Look here: http://dlang.org/expression.html#IdentityExpression In TDPL it's explained as well.
Oct 30 2012
Sigh, one of these days I'm gonna have to rewrite many of these pages. I find them very hard to navigate and very unfriendly to newbies, because very basic information (like what 'is' is) is buried deep in long verbose infodumps of diverse language features, with no indication at all which are fundamental concepts and which are just details. It's virtually impossible to find what you're looking for unless you already know what it is. TDPL lays things out in a much saner fashion, but how many newbies actually own the book? We need the online docs to be just as newbie-friendly.I agree, that the online docs are insufficient for learning the language. But that's the case for phobos, too. Both are just a listings of what is there and don't give you any overview of what design decisions were made and what implications they have. Just take a look std.container. I hope that Ali Çehreli efforts will be midterm solution at least for the language docs. Maybe he should credits by linking from the homepage to his book.
Oct 30 2012
On 2012-10-30 17:09, Tobias Pankrath wrote:I agree, that the online docs are insufficient for learning the language. But that's the case for phobos, too. Both are just a listings of what is there and don't give you any overview of what design decisions were made and what implications they have. Just take a look std.container. I hope that Ali Çehreli efforts will be midterm solution at least for the language docs. Maybe he should credits by linking from the homepage to his book.A language needs several types of documentation. Reference documentation (basically what we have now), higher level documentation, tutorials and examples. -- /Jacob Carlborg
Oct 30 2012
On Tue, Oct 30, 2012 at 08:50:50PM +0100, Jacob Carlborg wrote:On 2012-10-30 17:09, Tobias Pankrath wrote:[...] I contend that much of the current documentation isn't even up to reference standard. Incompleteness, for one thing. Things like Throwable and Exception aren't even documented right now (though this has been fixed in git HEAD). I'm sure there are many other fundamental holes. And a randomly-sorted list of unrelated module items does not constitute a reference, either. It has to be at least sorted alphabetically, or preferably, by logical categories. And things like class members need to be properly indented (I think this was fixed recently) instead of being flattened out, making it impossible to discern whether it belongs to the previous declaration or the global module scope. Moreover, nested classes/structs, etc., need to be put AFTER simpler members. It's basically unreadable when, for example, two int members are separated by the docs of a 2-page nested struct. And don't even get me started on navigability. Dumping a morass of modules NEED to have docs split into separate pages. A 10-page infodump of randomly sorted items is simply impossible to use effectively. Clickable identifiers would be nice, so that you don't have to separately navigate and lookup a particular symbol when you're not sure what it means, while trying to keep track of where you left off (and I thought we were in the age of automation...). T -- The right half of the brain controls the left half of the body. This means that only left-handed people are in their right mind. -- Manoj SrivastavaI agree, that the online docs are insufficient for learning the language. But that's the case for phobos, too. Both are just a listings of what is there and don't give you any overview of what design decisions were made and what implications they have. Just take a look std.container. I hope that Ali ehreli efforts will be midterm solution at least for the language docs. Maybe he should credits by linking from the homepage to his book.A language needs several types of documentation. Reference documentation (basically what we have now), higher level documentation, tutorials and examples.
Oct 30 2012
Jonathan M Davis wrote:On Friday, October 26, 2012 19:46:16 deadalnix wrote:aysLe 25/10/2012 04:12, Jonathan M Davis a =C3=A9crit :On Wednesday, October 24, 2012 13:31:14 Walter Bright wrote:The default compare for structs is a bit compare of the contents.=20 Which definitely seems inherently broken. Doing that only works if the struct only contains integral types, character types, or bool. Nothing else will compare properly that way. It really needs to work like arr==3D=3Ddo (or are supposed to anyway) and compare each member according to =heand only fallback to an outright bitwise compare when it knows that t=ralresults would be identical (i.e. because all of the members are integ=altypes, character types, bool, or other structs which hold only integr=thattypes, character types, or bool - be it directly or in other structs ==20=20 TDPL clearly states that each of the struct's members are supposed to be=they hold). Bitwise comparison is the is operator's job, not =3D=3D. =20 - Jonathan M Davis=20 That will broke code. =20 But That is the way to go IMO. D needs to evolve to make things more consistent in general. =20 Still not doable without a proper versionning scheme.checked for equality (see section 7.1.5.2, p. 258 - 259). It's outright a=bug=20for structs to be checked for equality with a bitwise comparison when the==20bitwise comparison does not do exactly what =3D=3D would have done had ea=ch and=20every member variable been compared with =3D=3D. And as with all bugs, fi=xing it=20could break code which depends on the buggy behavior. But given the natur=e of=20this bug, I seriously question that much of anyone thought that the =3D==3D on=20structs was supposed to do anything other than what TDPL states that it s=hould=20and that pretty much no one was expecting it to do a bitwise comparison. =So,=20if anything, this will _fix_ far more code than it breaks.I was looking for that section. 3789 is clearly a bug and should be fixed as soon as possible. Votes indicate how important a bug should be. But duplicates are also a good indicator. This bug has six duplicates. Jens
Oct 28 2012
On 2012-10-26 19:46, deadalnix wrote:That will broke code. But That is the way to go IMO. D needs to evolve to make things more consistent in general. Still not doable without a proper versionning scheme.Fixing bugs can always break code and I don't think any version scheme can help here. But what a version scheme can help with is when changing the API. When you add a new function, that won't break any code. Removing a function will break code. -- /Jacob Carlborg
Oct 28 2012
On Wed, Oct 24, 2012 at 10:12:48PM -0400, Jonathan M Davis wrote:On Wednesday, October 24, 2012 13:31:14 Walter Bright wrote:[...] The built-in AA's suffer from the same problem. Which is why sometimes, if you use a struct as key, entries cannot be found because the key being looked up is bitwise different from any key in the AA, but they have the same value (e.g., the struct has a reference to two distinct objects that have the same value). T -- Food and laptops don't mix.The default compare for structs is a bit compare of the contents.Which definitely seems inherently broken. Doing that only works if the struct only contains integral types, character types, or bool. Nothing else will compare properly that way. It really needs to work like arrays do (or are supposed to anyway) and compare each member according to == and only fallback to an outright bitwise compare when it knows that the results would be identical (i.e. because all of the members are integral types, character types, bool, or other structs which hold only integral types, character types, or bool - be it directly or in other structs that they hold). Bitwise comparison is the is operator's job, not ==.
Oct 24 2012
On Wednesday, October 24, 2012 22:12:48 Jonathan M Davis wrote:On Wednesday, October 24, 2012 13:31:14 Walter Bright wrote:Actually, slight correction. Pointers are fine too. I'd expect to have to overload opEquals to get deep comparisons for those (and I expect that the same happens with arrays), but basically anything which isn't an integral value of some kind (which pointers essentially are) won't compare properly if the default opEquals for structs is doing the same as the is operator like it is right now. - Jonathan M DavisThe default compare for structs is a bit compare of the contents.Which definitely seems inherently broken. Doing that only works if the struct only contains integral types, character types, or bool. Nothing else will compare properly that way.
Oct 25 2012
On Saturday, October 27, 2012 22:30:25 H. S. Teoh wrote:He who does not appreciate the beauty of language is not worthy to bemoan its flaws.That presupposes that the language has any beauty to begin with. It could just be one big flaw. ;) - Jonathan M Davis
Oct 27 2012
On Sat, 27 Oct 2012 22:42:21 -0700 Jonathan M Davis <jmdavisProg gmx.com> wrote:On Saturday, October 27, 2012 22:30:25 H. S. Teoh wrote:Did someone say "PHP"? ;)He who does not appreciate the beauty of language is not worthy to bemoan its flaws.That presupposes that the language has any beauty to begin with. It could just be one big flaw. ;)
Oct 28 2012
On Mon, Oct 29, 2012 at 01:28:51AM -0400, Nick Sabalausky wrote:On Sat, 27 Oct 2012 22:42:21 -0700 Jonathan M Davis <jmdavisProg gmx.com> wrote:I thought I heard "Javascript"... :-P T -- In theory, there is no difference between theory and practice.On Saturday, October 27, 2012 22:30:25 H. S. Teoh wrote:Did someone say "PHP"? ;)He who does not appreciate the beauty of language is not worthy to bemoan its flaws.That presupposes that the language has any beauty to begin with. It could just be one big flaw. ;)
Oct 28 2012
On Monday, 29 October 2012 at 05:43:43 UTC, H. S. Teoh wrote:On Mon, Oct 29, 2012 at 01:28:51AM -0400, Nick Sabalausky wrote:Both seem to have their own issues, although I'd say javascript is worse than PHP. (at least PHP runs on the server).Did someone say "PHP"? ;)I thought I heard "Javascript"... :-P
Oct 28 2012
On 2012-10-29 07:42, Era Scarecrow wrote:Both seem to have their own issues, although I'd say javascript is worse than PHP. (at least PHP runs on the server).You can run JavaScript on the server too. -- /Jacob Carlborg
Oct 29 2012
On Sat, Oct 27, 2012 at 10:42:21PM -0700, Jonathan M Davis wrote:On Saturday, October 27, 2012 22:30:25 H. S. Teoh wrote:[...] Wait, are you saying that D is one big flaw? ;-) T -- Ph.D. = Permanent head DamageHe who does not appreciate the beauty of language is not worthy to bemoan its flaws.That presupposes that the language has any beauty to begin with. It could just be one big flaw. ;)
Oct 28 2012