Re: DConf 2013 Closing Keynote: Quo Vadis by Andrei Alexandrescu
On Sunday, 30 June 2013 at 03:29:06 UTC, Walter Bright wrote: On 6/29/2013 5:08 AM, Joseph Rushton Wakeling wrote: True, distribution was mainly by physical mail. There was some via BBS's and Usenet, but these were severely limited by bandwidth. I'd receive bug reports by fax, paper listings, and mailed floppies. This was also the heyday of the BBC Micro in UK schools, and I remember well the shelves full of books of sample programs in BBC Basic. We had lots of fun typing them up, working out how they worked, and then twisting them to our more evil designs.
Re: DConf 2013 Closing Keynote: Quo Vadis by Andrei Alexandrescu
On Monday, 1 July 2013 at 21:20:39 UTC, Walter Bright wrote: On 7/1/2013 2:04 PM, Brad Roberts wrote: Actually, Boost was specifically chosen because it didn't require attribution when redistributing. If BSD hadn't had that clause we probably would be using it instead. That was indeed another important reason for it. But we were well aware of and approved of the idea that people could take it and make closed source versions. It was always clear (and logical) to me why the core libraries were permissively licensed, but the no-need-to-give-attribution-for-non-source-distribution feature was a subtlety I hadn't considered before.
Re: DConf 2013 Closing Keynote: Quo Vadis by Andrei Alexandrescu
On Tuesday, 2 July 2013 at 05:21:35 UTC, Joakim wrote: On Monday, 1 July 2013 at 21:29:21 UTC, John Colvin wrote: On Monday, 1 July 2013 at 17:45:59 UTC, Joakim wrote: I wouldn't call closing source that they legally allowed to be closed antisocial. I'd call their contradictory, angry response to what their license permits antisocial. :) Just because you're doing something legal doesn't mean you're not being antisocial. Read my previous post. Of course it's possible for a license to technically allow something but for the authors to disapprove of it, not that its antisocial to simply do something they disapprove of. But, as I said earlier, the BSD crowd does not publicly broadcast that they disapprove of closing source. In fact, they will occasionally link to press releases about contributions back from corporations who closed the source. For people using the BSD license to then get mad when yet another person comes along to close source is the only antisocial behavior I'm seeing here. It'd be one thing if they publicly said that while the BSD license allows closing source, they're against it. Feel free to provide such a public statement, you won't find it. It's only after you talk to them privately about closing source that you realize how many of them are against it. As I've said repeatedly, I don't much care that their behavior is so antisocial, :) as long as its legal to close source. But it is pretty funny to cast that tag on somebody else, who is simply doing what their license allows and what their press releases trumpet. It's a pretty psychopathic attitude to conflate legality and morality, it's effectively saying I have the moral right to do whatever I can get away with On the contrary, it's a pretty psychopathic attitude to make such claims about morality when 1. nobody was talking about morality 2. the BSD crowd doesn't publicly talk about their problems with closing source either, whether they think it's immoral or antisocial or whatever. This is all a bit moot as I was making a general point, not specifically related to BSD. However, in their case, I think it is perfectly fine that some don't like closed source personally, but as a group they decide to endorse it. A group where everyone is forced to agree on everything isn't an organisation, it's a cult. I think what I'm really trying to say is this: A license is a description of what you will *allow*, not what you *want*. I personally like to take in to account what people *want* me to do, not just what they will *allow* me to do.
Re: Why implicit conversion of string literal to char[] does not works?
On Tuesday, 2 July 2013 at 09:11:44 UTC, Michal Minich wrote: Sorry for posting to announce. In future please post these questions to digitalmars.D.learn The reason you can't implicitly convert a string to a char[] is because string is an alias to immutable(char)[] Therefore, you would be providing a mutable window to immutable data, which is disallowed unless you *explicitly* ask for it (see below). You can explicitly cast string to char[], but it is undefined behaviour to modify the contents of the result (i.e. don't cast away immutable unless you absolutely have to and even then be very very careful).
Re: Announcing bottom-up-build - a build system for C/C++/D
On Monday, 1 July 2013 at 03:26:22 UTC, Graham St Jack wrote: On Thu, 27 Jun 2013 22:49:41 +, Graham St Jack wrote: Fixed the problem, and also: * split bub.d up into several smaller files, * added a Makefile to bootstrap the building of bub, and * added a bub.cfg and Bubfile as a trivial example of how to use bub. Please add an install: target to the Makefile. Thank you.
Re: Why implicit conversion of string literal to char[] does not works?
On Tue, 02 Jul 2013 12:33:14 +0100, Michal Minich michal.min...@gmail.com wrote: On Tuesday, 2 July 2013 at 11:29:05 UTC, Dicebot wrote: On Tuesday, 2 July 2013 at 11:26:59 UTC, Michal Minich wrote: But ... I'm asking only about implicit conversion of string literal, not arbitrary expressions of string type. char[] str = abc.dup; Thanks, that is workaround I didn't know about. I'm really interested about reasons why it doesn't works (without dup/cast). At some point it had to be disabled. But I really cannot find a reason why that would be useful. It is done for performance reasons. On UNIX the compiler will put the literal abc into read only memory. It could/should do the same on windows but doesn't yet (I believe). So, the compiler is treating them as such, by giving them the type immutable(char)[] (AKA string). And, the spec should, if it doesn't, define string literals to be immutable. In older versions of DMD we didn't have string AKA immutable(char), in fact at one point we didn't have immutable at all. At that time, abc was typed as char[] and people on UNIX systems ran headlong into an access violation attempting to write to ROM :p R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Re: Why implicit conversion of string literal to char[] does not works?
On Tuesday, 2 July 2013 at 11:26:59 UTC, Michal Minich wrote: On Tuesday, 2 July 2013 at 10:09:10 UTC, John Colvin wrote: The reason you can't implicitly convert a string to a char[] is because string is an alias to immutable(char)[] Therefore, you would be providing a mutable window to immutable data, which is disallowed unless you *explicitly* ask for it (see below). would be - might be no, would be is correct. char is mutable, immutable(char) is not. By definition char[] is a mutable view of data, immutable(char)[] is not. You can explicitly cast string to char[], but it is undefined behaviour to modify the contents of the result ok (i.e. don't cast away immutable unless you absolutely have to and even then be very very careful). This is not correct. You should can not cast when you 'absolutely have to' but when you can prove by means not available to compiler that the data being casted are in fact mutable. And the 'proving' of this is what you should be careful about. Eek... no, unless i'm misunderstanding you or you made a typo, that's not the case at all. Don't mutate anything that has a live (and used?)* immutable reference to it. Just because the data was mutable before being cast to immutable, doesn't mean you can just cast away immutable and mutate it. Or, alternatively presented: You can cast to or away from immutable when you can prove by any means that the data being casted are not mutated through any reference after the creation of or before the final use of any immutable references. Erring on the safe side, you might want to wait for the immutable references to be actually dead and gone before any mutation. * Would like some clarification on whether it is the usage of the immutable reference or the lifetime that counts, if anyone knows for sure.
Re: Why implicit conversion of string literal to char[] does not works?
On Tuesday, 2 July 2013 at 13:07:40 UTC, Regan Heath wrote: It is done for performance reasons. On UNIX the compiler will put the literal abc into read only memory. It could/should do the same on windows but doesn't yet (I believe). So, the compiler is treating them as such, by giving them the type immutable(char)[] (AKA string). And, the spec should, if it doesn't, define string literals to be immutable. Ok I understand. What I did as a first thing when I get error on char[] x = a was char x = cast(char[])a, Which was obviously incorrect - as the a was/should be placed in rom. So if this expression is allays wrong - casting string literal to mutable, then compiler should emit an error on this (If one implementation (dmd/win) makes this valid, it still doesn't mean compiler should honor implementation over specification - amusing it is specified that strings go into rom...) Also, given you explanation, I see it as good to type auto x = a as string, but give explicit notation char[] x = a - I don't see reason to not allow string literal to be typed as both char[] and string at the same time, and convert to char[] - and also place in ram, if explicitly asked. The only reason that comes now to mi mind is when working with old code base - before auto and immutable(char)[] .. the code had to use char[] x = a, but these must be all eliminated by now
Re: Why implicit conversion of string literal to char[] does not works?
On Tuesday, 2 July 2013 at 13:33:10 UTC, Michal Minich wrote: Ok I understand. What I did as a first thing when I get error on char[] x = a was char x = cast(char[])a, Which was obviously incorrect - as the a was/should be placed in rom. So if this expression is allays wrong - casting string literal to mutable, then compiler should emit an error on this explicit cast means a order from a programmer type system, I know what I am doing, don't even try to bother me. You should never use casts to simply suppress errors (unless absolutely sure) in the very first place.
Re: Why implicit conversion of string literal to char[] does not works?
On Tue, 02 Jul 2013 14:33:09 +0100, Michal Minich michal.min...@gmail.com wrote: On Tuesday, 2 July 2013 at 13:07:40 UTC, Regan Heath wrote: It is done for performance reasons. On UNIX the compiler will put the literal abc into read only memory. It could/should do the same on windows but doesn't yet (I believe). So, the compiler is treating them as such, by giving them the type immutable(char)[] (AKA string). And, the spec should, if it doesn't, define string literals to be immutable. Ok I understand. What I did as a first thing when I get error on char[] x = a was char x = cast(char[])a, Which was obviously incorrect - as the a was/should be placed in rom. So if this expression is allays wrong - casting string literal to mutable, then compiler should emit an error on this (If one implementation (dmd/win) makes this valid, it still doesn't mean compiler should honor implementation over specification - amusing it is specified that strings go into rom...) As Dicebot has replied, cast() is the mechanism the programmer uses to force the compiler to do what s/he wants regardless of what it thinks. The compiler assumes that if cast() is used that the programmer knows what they're doing. Only use cast() if you have no other option. In this simple case, the compiler could detect the error, or as you say below take the cast(char[]) as a hint to place the a in RAM instead. But, 99.9% of cases are more complex than this simple one, so the cost/benefit of detecting the error make it very low priority, perhaps never to be implemented. Likewise for the place in RAM idea. Both/either would be nice, but neither is necessary now provide a lot of benefit. Also, given you explanation, I see it as good to type auto x = a as string, but give explicit notation char[] x = a - I don't see reason to not allow string literal to be typed as both char[] and string at the same time, and convert to char[] - and also place in ram, if explicitly asked. To explicitly place a in RAM you would write char[] x = a.dup; Or: char[] x = new char[1]; x[0] = 'a'; The only reason that comes now to mi mind is when working with old code base - before auto and immutable(char)[] .. the code had to use char[] x = a, but these must be all eliminated by now Old code using char[] x = a was technically invalid (it just happened to run ok on windows, or linux if no mutation was done) and will now error as such. For old code raising this error the correct solution .. - if mutable is required is to add .dup. - if mutable is not required is to replace char[] with string or auto. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Re: Why implicit conversion of string literal to char[] does not works?
On Tuesday, 2 July 2013 at 13:39:36 UTC, Dicebot wrote: On Tuesday, 2 July 2013 at 13:33:10 UTC, Michal Minich wrote: Ok I understand. What I did as a first thing when I get error on char[] x = a was char x = cast(char[])a, Which was obviously incorrect - as the a was/should be placed in rom. So if this expression is allays wrong - casting string literal to mutable, then compiler should emit an error on this explicit cast means a order from a programmer type system, I know what I am doing, don't even try to bother me. You should never use casts to simply suppress errors (unless absolutely sure) in the very first place. I completely agree. The other thing is, for the less aware programmers, a warning on non-linux and a error on linux might be nice. As this cast (on linux), will _allways_ result in undefined behavior. It is something compiler can easily tell, and advice use .dup instead of cast...
Re: Why implicit conversion of string literal to char[] does not works?
On Tuesday, 2 July 2013 at 09:10:33 UTC, Michal Minich wrote: void main () { char[] str = abc; // Error: cannot implicitly convert expression (abc) // of type string to char[] } I thought there is no harm in that? char[] str = ['a', 'b', 'c']; This will only allocate once without placing data in object file. This is caused by obsolete Cism moved into modern language to treat string literals as constant objects (perhaps reasoning was made in 1980s in memory constraints of those times). Ideally char[] str = abc should be as normal as int[] arr = [0,1,2] allowing to play with data as much as you wish.
Re: Automatic typing
On 7/1/13 7:35 PM, JS wrote: On Tuesday, 2 July 2013 at 02:15:09 UTC, Andrei Alexandrescu wrote: On 7/1/13 6:29 PM, JS wrote: Would would be nice is an experimental version of D where would could easily extend the language to try out such concepts to see if they truly are useful and how difficult to implement. e.g., I could attempt to add said feature, it could be merged with the experimental compiler, those interested can download the compiler and test the feature out... all without negatively affecting D directly. If such features could be implemented dynamically then it would probably be pretty powerful. I don't think such a feature would make it in D, even if the implementation cost was already sunken (i.e. an implementation was already done and one pull request away). Ascribing distinct objects to the same symbol is a very core feature that affects and is affected by everything else. We'd design a lot of D differently if that particular feature were desired, and now the fundamentals of the design are long frozen. For a very simple example, consider: auto a = 2.5; // fine, a is double ... a = 3; No, not under what I am talking about. You can't downgrade a type, only upgrade it. a = 3, a is still a float. Using the concept I am talking about, your example does nothing new. but reverse the numbers: auto a = 3; a = 2.5; and a is now a float, and your logic then becomes correct EXCEPT a is expanded, which is safe. I really don't know how to make it any clearer but I'm not sure if anyone understands what I'm talking about ;/ You can definitely assume you are being well understood. That's going to break a lot of code because of e.g. calls to overloaded functions in between changes of type. Just drop this. Not only it won't make it into D, it's also not particularly interesting. Andrei
Re: Automatic typing
Steven Schveighoffer wrote: There are very good reasons not to do this, even if possible. Especially if the type can change. +1 This sort of inference can only lead to problems down the line, IMO.
Re: SIMD on Windows
Jonathan Dunlap: Thanks Jerro, I went ahead and used a pointer reference to ensure it's being saved back into the array (http://dpaste.dzfl.pl/52710926). Two things: 1) still showing zero time delta 2) On windows 7 x74, using a SAMPLE_AT size of 3 or higher will cause the program to immediately quit with no output at all. Even the first statement of writeln in the constructor doesn't execute. Have you taken a look at the asm? Bye, bearophile
UFCS and constructors
Coming back from learn here. There was an example where somebody accidentally called a constructor via UFCS. I am kind of surprised that it worked. I thought UFCS was for functions only, and that constructors (specifically) were off limits. Am I mistaken? Is UFCS explicitly allowed for constructors? Or did we kind of forget to take it into account? One of the big problems with allowing UFCS and constructors is that a . which meant scope can now mean function call. If I remember correctly, that is the reason why qualified calls (eg 'a'.std.uni.toLower()) aren't allowed in UFCS (Am I correct?), but with constructors, you get the same problem: Allow me to demonstrate: import std.stdio; struct Bar { struct S { int i; } enum j = 1; } struct S { int[10] i; } void main() { writeln(Bar.S()); (1) writeln(Bar.j.S()); (2) } (1) is a standard scope call: instantiate a Bar.S. This prints S(0). (2) is actually: get the value j from Bar, and then UFCS construct an S using that J. This prints: S([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) Furthermore, I find UFCS construction confusing on the grounds that there is no actual constructor function eg: this(...) call: This is just aggregate initialization, which looks *very* confusing when written that way. So to sum up the question: Was UFCS + constructors are really desired feature? Was it taken into account? Do we want to keep it? In particular, the standard workaround of free function constructor (EG Take vs take) would serve much better here.
Re: UFCS and constructors
monarch_dodra: Is UFCS explicitly allowed for constructors? Or did we kind of forget to take it into account? I think it's allowed, but such design decisions should be written in a kind of document... instead of just in the D front end source code. See also: http://d.puremagic.com/issues/show_bug.cgi?id=9857 Bye, bearophile
Re: UFCS and constructors
On Tuesday, July 02, 2013 09:35:38 monarch_dodra wrote: Coming back from learn here. There was an example where somebody accidentally called a constructor via UFCS. I am kind of surprised that it worked. I thought UFCS was for functions only, and that constructors (specifically) were off limits. Am I mistaken? Is UFCS explicitly allowed for constructors? Or did we kind of forget to take it into account? I'm not sure that it was ever decided one way or the other so much as happened into being due to how UFCS was implemented. I know that it's come up before, and folks were arguing on both sides. Personally, I think that it's a horrible idea. - Jonathan M Davis
Re: UFCS and constructors
On Tuesday, 2 July 2013 at 07:35:39 UTC, monarch_dodra wrote: One of the big problems with allowing UFCS and constructors is that a . which meant scope can now mean function call. Just for the interest - try to guess what following in D may be: a.b = c.d(); This is a good example how overloaded D syntax is. (1) is a standard scope call: instantiate a Bar.S. This prints S(0). (2) is actually: get the value j from Bar, and then UFCS construct an S using that J. This prints: S([1, 1, 1, 1, 1, 1, 1, 1, 1, 1]) Furthermore, I find UFCS construction confusing on the grounds that there is no actual constructor function eg: this(...) call: This is just aggregate initialization, which looks *very* confusing when written that way. So to sum up the question: Was UFCS + constructors are really desired feature? Was it taken into account? Do we want to keep it? I think this worth bug issue. Even if this behavior would be proven to be correct (I guess many wish it wouldn't), bugzilla request could be posted as an ask to provide use case in D documentation site to show this behavior explicitly.
Re: UFCS and constructors
On Tuesday, 2 July 2013 at 08:16:38 UTC, Jonathan M Davis wrote: On Tuesday, July 02, 2013 09:35:38 monarch_dodra wrote: Coming back from learn here. There was an example where somebody accidentally called a constructor via UFCS. I am kind of surprised that it worked. I thought UFCS was for functions only, and that constructors (specifically) were off limits. Am I mistaken? Is UFCS explicitly allowed for constructors? Or did we kind of forget to take it into account? I'm not sure that it was ever decided one way or the other so much as happened into being due to how UFCS was implemented. I know that it's come up before, and folks were arguing on both sides. Personally, I think that it's a horrible idea. - Jonathan M Davis We are 2. that is horrible.
Re: memory allocation in dmd
On Saturday, 22 June 2013 at 21:41:15 UTC, Walter Bright wrote: Compiling std.algorithm for unittests consumes all the memory on many machines. I've been looking into what is allocating all that memory, and it isn't so easy without adding instrumentation code anywhere. Anyone know of a convenient tool to do this on Linux? (valgrind just hangs, or at least I gave up on it after 6 hours) I did a check on the CTFE part of it. You can do this by setting SHOWPERFORMANCE to 1 in the top of interpret.c. This produces: $ dmd -c -unittest std.algorithm CTFE Performance max call depth = 20 max stack = 63 array allocs = 356 assignments = 45356 That's actually not so terrible. The number of assignments gives a rough idea of how many CTFE statements are executed (almost everything interesting is an assignment). Most of the assignments are IntegerExpressions, of about 8 bytes, so it's under a megabyte in total. Note that there are very few array allocations, they are the thing that can really chew up memory quickly in CTFE. So although CTFE generally leaks memory like the Exxon Valdez leaks oil, I don't think it's to blame in this particular case.
Re: UDP enhancement
On Tuesday, 2 July 2013 at 04:49:55 UTC, estew wrote: It's location in the class my not be the same but that is, in general, irrelevant unless you are messing with the bits of the class. Actually we do this a lot in C++ where I work to ensure proper alignment. We are also starting to do this in D where we have C++ - D bindings so we can make our D structs exactly match our C++ structs in memory. Personally I see less benefit over: public @property int value; This approach is nice. It can be used both when layout is important and when it is don't care and is clearer. I can look at the struct and immediately read its memory footprint. Your suggested proposal cannot be used when layout is important as it is left to the compiler. It would require a workaround to coerce the compiler into submission, or additional compiler circuitry making it even more complex and slowing it down. Or just use the old way. Just because one extends a feature does not mean the old feature is removed. If you need to hack up the bits just explicitly allocate the field... simple as that.
Re: UFCS and constructors
On 07/02/2013 09:35 AM, monarch_dodra wrote: Furthermore, I find UFCS construction confusing on the grounds that there is no actual constructor function eg: this(...) call: This is just aggregate initialization, Aggregate initialization is the job of the constructor. It is a default constructor call. which looks *very* confusing when written that way. I disagree, even though the example appears to be specifically designed to confuse. Actual usage looks like this: import std.stdio, std.bigint void main(){ writeln(2.BigInt ^^ 123456); } So to sum up the question: Was UFCS + constructors are really desired feature? UFCS allows foo(a,b) to be written as a.foo(b), if 'foo' is not a member of a. Was it taken into account? I guess so. Do we want to keep it? There is no reason to artificially ban it. In particular, the standard workaround of free function constructor What is the difference? (EG Take vs take) would serve much better here. take is not a free function constructor.
Re: UFCS and constructors
On 07/02/2013 09:35 AM, monarch_dodra wrote: ... One of the big problems with allowing UFCS and constructors is that a . which meant scope can now mean function call. ... I missed this point. 'One of the drawbacks of UFCS is that bar.foo which meant scope lookup or opDispatch instantiation or alias this lookup can now also mean UFCS lookup.' Fixed.
Re: UFCS and constructors
On Tuesday, 2 July 2013 at 12:57:50 UTC, Timon Gehr wrote: On 07/02/2013 09:35 AM, monarch_dodra wrote: ... One of the big problems with allowing UFCS and constructors is that a . which meant scope can now mean function call. ... I missed this point. 'One of the drawbacks of UFCS is that bar.foo which meant scope lookup or opDispatch instantiation or alias this lookup can now also mean UFCS lookup.' Fixed. That is an issue, we have all of this, and prioritization mechanism is implementation defined right now.
Re: UFCS and constructors
2013/7/2 deadalnix deadal...@gmail.com On Tuesday, 2 July 2013 at 08:16:38 UTC, Jonathan M Davis wrote: On Tuesday, July 02, 2013 09:35:38 monarch_dodra wrote: Coming back from learn here. There was an example where somebody accidentally called a constructor via UFCS. I am kind of surprised that it worked. I thought UFCS was for functions only, and that constructors (specifically) were off limits. Am I mistaken? Is UFCS explicitly allowed for constructors? Or did we kind of forget to take it into account? I'm not sure that it was ever decided one way or the other so much as happened into being due to how UFCS was implemented. I know that it's come up before, and folks were arguing on both sides. Personally, I think that it's a horrible idea. - Jonathan M Davis We are 2. that is horrible. I don't know what design decision had been there about it. Historically, there's no restriction against UFCS-callable entity. With 2.030 (released on May 11, 2009) and git head, following code completely works. void foo(int[]) {} void bar(T)(T) {} struct Foo { int[] x; } struct Bar { this(int[]) {} } struct Baz { static opCall(int[]) { return 0; } } int[] function(int[]) fp; int[] delegate(int[]) dg; struct Functor { int opCall(int[]) { return 0; } } Functor fn; void main() { fp = function(int[] x){ return x; }; dg = delegate(int[] x){ return x; }; int[] a; a.foo(); a.bar(); auto x1 = a.Foo(); auto x2 = a.Bar(); auto x3 = a.Baz(); a.fp(); a.dg(); a.fn(); } While improvement of dmd front-end code, I didn't touch it. Yes, I did never designed it... Kenji Hara
Re: Automatic typing
On Saturday, 29 June 2013 at 03:20:27 UTC, JS wrote: I don't disagree with you and I'm not saying auto is not useful. IMO though, auto is almost all convenience and very little to do with solving errors. A very simple use case is: auto x = 0; ... x = complex(1, 1) + x; which obviously is an error. Let me expand the example with this: auto x = 0; complex y; ... x = complex(1, 1) + x; // ouch, I meant the next line! y = complex(1, 1) + x; Personally, I appreciate the strengths of static typing here, forcing me to choose which of the two behaviors I meant instead of silently picking one of them. Ivan Kazmenko.
Re: UFCS and constructors
On Tuesday, 2 July 2013 at 12:46:42 UTC, Timon Gehr wrote: On 07/02/2013 09:35 AM, monarch_dodra wrote: which looks *very* confusing when written that way. I disagree, even though the example appears to be specifically designed to confuse. Actual usage looks like this: import std.stdio, std.bigint void main(){ writeln(2.BigInt ^^ 123456); } Yeah... tailored for confusion... that could be the biggest issue actually: I always get surprised when arrays are 1 item initialized, and even more so when done in a struct via aggregate initialization. I'd say *that* was actually the bigger culprit in my example, and the one that lead to my confusion, which I then blamed (or called wolf) on UFCS If it wasn't for UFCS, that would have been turned down! UFCS actually had nothing to do with it. :( Well, thanks for the explanation and debunk.
Member lookup (Was: Re: UFCS and constructors)
On 07/02/2013 03:00 PM, deadalnix wrote: On Tuesday, 2 July 2013 at 12:57:50 UTC, Timon Gehr wrote: On 07/02/2013 09:35 AM, monarch_dodra wrote: ... One of the big problems with allowing UFCS and constructors is that a . which meant scope can now mean function call. ... I missed this point. 'One of the drawbacks of UFCS is that bar.foo which meant scope lookup or opDispatch instantiation or alias this lookup can now also mean UFCS lookup.' Fixed. That is an issue, we have all of this, and prioritization mechanism is implementation defined right now. Yup. I'll go with: 1: If member is present (current scope or super class scope), use that, otherwise try opDispatch in the same scopes. Block alias this at this point. 2: If no success, loop through all alias this definitions and apply 1. for the corresponding scopes. Collect possible members. 3: Error out if multiple possible distinct members. 4: Try UFCS rewrite if no matches. (Of course, even checking whether a member is present, or looping over all alias this definitions are not entirely trivial processes themselves in the general case.) This seems to be compatible with what DMD does.
Function templates do implicit conversions for their arguments
This is a pretty big delta between C++ and D. It's going to surprise everybody coming from C++, especially when it says in TDPL (page 140) that: However, having the language attempt combinatorially at the same time implicit conversions and type deduction is a dicey proposition in the general case, so D does not attempt to do all that. D --- struct Wrap(Gift) { Gift gift; } struct Teddy { int id; Wrap!Teddy getWrapped() @property { return Wrap!Teddy(this); } alias getWrapped this; } Gift tearOpen(Gift)(Wrap!Gift wrappedGift) { return wrappedGift.gift; } void main() { auto ted = Teddy(123); auto r = tearOpen(ted); // N! Teddy! assert(r == ted); // Phew, Teddy was implicitly gift-wrapped // and we tore the wrap open, not Teddy. } C++ --- template typename Gift struct Wrap { Gift gift; }; struct Teddy { int id; operator WrapTeddy() { return WrapTeddy{*this}; } }; template typename Gift Gift tearOpen(WrapGift wrappedGift) { return wrappedGift.gift; } int main() { Teddy ted (123); tearOpen(ted); // No matching function call to 'tearOpen' } This difference between D and C++ should be noted somewhere in the documentation with big red letters.
Re: Function templates do implicit conversions for their arguments
On Tuesday, 2 July 2013 at 16:59:50 UTC, TommiT wrote: [..] C++ --- [..] Teddy ted (123); [..] That should be: Teddy ted {123};
Re: UDP enhancement
On Monday, 1 July 2013 at 01:35:40 UTC, Jonathan M Davis wrote: I believe that the way that this sort of enhancement has typically been suggested is to do something like public @property int value; which would be lowered to something like public @property int value() @safe const pure nothrow { return _value; } public @property int value(int v) @safe pure nothrow { return _value = v; } private int _value; - Jonathan M Davis As someone who uses properties almost everywhere, and almost never uses public fields, this is one of my biggest gripes with D remaining. It's incredibly annoying to have to do things like private int _width; /// Gets or sets the total width, in pixels, of this control. @property int width() const { return _width; } /// ditto @property void width(int value) { this._width = value; } Something like /// Gets or sets the total width, in pixels, of this control. @property const int width; Is just so much nicer and saves so much bloat. I feel like the current property syntax is one of those places where IDE code snippets will start to become, not necessary, but extremely useful. It's the type of manual repetition that D aims to avoid, but in this case fails at. I don't know if I agree with automatically expanding to const though. I'd like to be able to do '@property Control parent' without needing to return a const(Control) because the property is expanded to be const. Although if we had a virtual keyword, final is something that I think should be default for properties, and I think it's a mistake that the current @property doesn't infer final in the first place. Safe and nothrow are two assumptions that are probably quite safe to assume for the most part as well.
Re: UFCS and constructors
On Tuesday, July 02, 2013 14:46:41 Timon Gehr wrote: Do we want to keep it? There is no reason to artificially ban it. There's nothing artificial about it. Constructors are not normal functions and should not be treated as such. They're fundamentally different from normal functions. Also, in all other cases, UFCS involves using a free function as if it were a member function, so it's incredibly bizarre as well as inconsistent with the rest of UFCS to allow constructors to be used with it. - Jontahan M Davis
Re: UDP enhancement
On Tuesday, July 02, 2013 19:49:39 Kapps wrote: On Monday, 1 July 2013 at 01:35:40 UTC, Jonathan M Davis wrote: I believe that the way that this sort of enhancement has typically been suggested is to do something like public @property int value; which would be lowered to something like public @property int value() @safe const pure nothrow { return _value; } public @property int value(int v) @safe pure nothrow { return _value = v; } private int _value; - Jonathan M Davis As someone who uses properties almost everywhere, and almost never uses public fields, this is one of my biggest gripes with D remaining. It's incredibly annoying to have to do things like private int _width; /// Gets or sets the total width, in pixels, of this control. @property int width() const { return _width; } /// ditto @property void width(int value) { this._width = value; } Something like /// Gets or sets the total width, in pixels, of this control. @property const int width; Is just so much nicer and saves so much bloat. I feel like the current property syntax is one of those places where IDE code snippets will start to become, not necessary, but extremely useful. It's the type of manual repetition that D aims to avoid, but in this case fails at. I don't know if I agree with automatically expanding to const though. inout would probably be better then. But without that, anyone wanting to be const-correct is going to have to declare all of the getters themselves. inout isn't quite there, because there are many cases where you really do want to return const even when the object is mutable, but it would probably be a good compromise. - Jonathan M Davis
Re: Function templates do implicit conversions for their arguments
On Tuesday, 2 July 2013 at 16:59:50 UTC, TommiT wrote: D --- struct Wrap(Gift) { Gift gift; } struct Teddy { int id; Wrap!Teddy getWrapped() @property { return Wrap!Teddy(this); } alias getWrapped this; } C++ doesn't have alias this. The behavior that it should be simulating is inheritance, I'd probably fail writing C++ for this so here is some D code to translate: import std.stdio; class Wrap(Gift) { abstract Gift gift(); } class Teddy : Wrap!Teddy { int id; this(int i) { id = i; } override Teddy gift() { return this; } } Gift tearOpen(Gift)(Wrap!Gift wrappedGift) { return wrappedGift.gift; } void main() { auto ted = new Teddy(123); auto r = tearOpen(ted); // N! Teddy! assert(r == ted); // Phew, Teddy was implicitly gift-wrapped // and we tore the wrap open, not Teddy. }
Re: Function templates do implicit conversions for their arguments
On 07/02/2013 11:46 AM, Jesse Phillips wrote: C++ doesn't have alias this. The behavior that it should be simulating is inheritance But 'alias this' is also for automatic type conversions. TommiT's had implemented 'operator WrapTeddy() const' (const added by me) but C++ does not attempt that automatic type conversion. D does attempt the conversion. I think that is TommiT's point. Ali
Re: Function templates do implicit conversions for their arguments
On Tuesday, 2 July 2013 at 18:47:00 UTC, Jesse Phillips wrote: [..] The behavior that it [alias this] should be simulating is inheritance, [..] Okay. I had thought of alias this as *merely* implicit conversion. But it really makes sense that it simulates (models) inheritance and the implicit conversion (to the base type) is just a consequence of that. On Tuesday, 2 July 2013 at 18:47:00 UTC, Jesse Phillips wrote: [..] I'd probably fail writing C++ for this so here is some D code to translate: import std.stdio; class Wrap(Gift) { abstract Gift gift(); } class Teddy : Wrap!Teddy { int id; this(int i) { id = i; } override Teddy gift() { return this; } } Gift tearOpen(Gift)(Wrap!Gift wrappedGift) { return wrappedGift.gift; } void main() { auto ted = new Teddy(123); auto r = tearOpen(ted); // N! Teddy! assert(r == ted); // Phew, Teddy was implicitly gift-wrapped // and we tore the wrap open, not Teddy. } Here's what the corresponding code would be in C++: #include cassert template typename Gift class Wrap { public: virtual Gift gift() = 0; }; class Teddy : public WrapTeddy { public: int id; Teddy(int i) : id(i) { } Teddy gift() { return *this; } bool operator==(const Teddy other) const { return id == other.id; } }; template typename Gift Gift tearOpen(WrapGift wrappedGift) { return wrappedGift.gift(); } int main() { auto ted = Teddy(123); auto r = tearOpen(ted); // OK assert(r == ted); // OK return 0; }
Re: Function templates do implicit conversions for their arguments
On Tuesday, 2 July 2013 at 16:59:50 UTC, TommiT wrote: ... Slightly changed original code struct Wrap(T) { T t; } struct S { int id; Wrap!S getWrapped() { return Wrap!S(this); } alias getWrapped this; } T tearOpen(T)(Wrap!T wrappedT) { return wrappedT.t; } void main() { S ted = S(123); S r = tearOpen(ted); assert(r == ted); } Since both S(123) and tearOpen(ted) has same type and return same value comparison succeeds. tearOpen(ted) should take Wrap!T but argument has different type. Argument has alias this, so it is analyzed and since it is aliased to Wrap!S, passing succeeds. This is how alias this is designed to work. What have you surprised here?
Feature request: Path append operators for strings
How would you feel about adding the '/' binary operator and the '/=' assignment operator for strings, wstrings and dstrings? The operators would behave the same way as they do with boost::filesystem::path objects: http://www.boost.org/doc/libs/1_54_0/libs/filesystem/doc/reference.html#path-appends In short (and omitting some details) code such as: string s = C:\\Users / John; ...would be the same as: string s = C:\\Users ~ std.path.dirSeparator ~ John;
Re: UFCS and constructors
On 07/02/2013 07:58 PM, Jonathan M Davis wrote: On Tuesday, July 02, 2013 14:46:41 Timon Gehr wrote: Do we want to keep it? There is no reason to artificially ban it. There's nothing artificial about it. Constructors are not normal functions and should not be treated as such. They're fundamentally different from normal functions. Also, in all other cases, UFCS involves using a free function as if it were a member function, so it's incredibly bizarre as well as inconsistent with the rest of UFCS to allow constructors to be used with it. - Jontahan M Davis It is an artificial limitation, because you need to add an explicit check after symbol lookup to ban constructors. Analogies are always broken, but the rest of the post reads to me roughly like: Dogs are not pets, and should not be treated as such. They are fundamentally different from pets. Also, there are no other pets that bark, so it's incredibly bizarre as well as inconsistent with the rest of the notion of a 'pet' to have a pet dog. - Tmion M Gehr This has happened before. What am I missing?
Re: Feature request: Path append operators for strings
On 2013-07-02, 21:46, TommiT wrote: How would you feel about adding the '/' binary operator and the '/=' assignment operator for strings, wstrings and dstrings? The operators would behave the same way as they do with boost::filesystem::path objects: http://www.boost.org/doc/libs/1_54_0/libs/filesystem/doc/reference.html#path-appends In short (and omitting some details) code such as: string s = C:\\Users / John; ...would be the same as: string s = C:\\Users ~ std.path.dirSeparator ~ John; This would be much better done with a library type: auto s = Path(C:\\Users) / John; -- Simen
Re: Feature request: Path append operators for strings
On Tuesday, July 02, 2013 21:46:26 TommiT wrote: How would you feel about adding the '/' binary operator and the '/=' assignment operator for strings, wstrings and dstrings? The operators would behave the same way as they do with boost::filesystem::path objects: http://www.boost.org/doc/libs/1_54_0/libs/filesystem/doc/reference.html#path -appends In short (and omitting some details) code such as: string s = C:\\Users / John; ...would be the same as: string s = C:\\Users ~ std.path.dirSeparator ~ John; That's what std.path.buildPath is for. - Jonathan M Davis
Re: Function templates do implicit conversions for their arguments
On Tuesday, 2 July 2013 at 19:39:56 UTC, Maxim Fomin wrote: [..] This is how alias this is designed to work. What have you surprised here? I had started to think about alias this as C++'s implicit conversion operator. And I remembered wrong how alias this was explained in TDPL. I remembered it somehow like this: Whenever a variable der of type Derived is used where a type Base is expected, the compiler tries der.getBase also. (assuming alias getBase this; in Derived) And since a templated parameter doesn't *expect* anything, I figured it wouldn't convert. But alias this is defined in TDPL (page 265) like so: The workings of alias payload this are quite simple. Whenever a value obj of type Final!T is used in a context that would be illegal for its type, the compiler rewrites obj as obj.payload. Just an honest mistake on my part.
Re: UFCS and constructors
On Tuesday, 2 July 2013 at 19:47:07 UTC, Timon Gehr wrote: Analogies are always broken, but the rest of the post reads to me roughly like: Dogs are not pets, and should not be treated as such. They are fundamentally different from pets. Also, there are no other pets that bark, so it's incredibly bizarre as well as inconsistent with the rest of the notion of a 'pet' to have a pet dog. - Tmion M Gehr class A { this() {} void foo(){} } A a = new A; // calls ctor, not foo Of course constructors are special because not any function is called upon object construction. Same logic was made when ability to overload some operators was blocked. All operators are, well, operators but you cannot overload all of them. It appears that sometimes it does make sense to restrict operation on some particular elements of the set and sometimes not. Anyway, without final decision on this issue, there would be endless controversy between those who point on commonness of all functions and those who point on peculiarity of some of them.
Re: Feature request: Path append operators for strings
On Tuesday, 2 July 2013 at 19:56:20 UTC, Jonathan M Davis wrote: On Tuesday, July 02, 2013 21:46:26 TommiT wrote: How would you feel about adding the '/' binary operator and the '/=' assignment operator for strings, wstrings and dstrings? The operators would behave the same way as they do with boost::filesystem::path objects: http://www.boost.org/doc/libs/1_54_0/libs/filesystem/doc/reference.html#path -appends In short (and omitting some details) code such as: string s = C:\\Users / John; ...would be the same as: string s = C:\\Users ~ std.path.dirSeparator ~ John; That's what std.path.buildPath is for. - Jonathan M Davis Oh, I hadn't noticed that function. I don't know about its behaviour of dropping path components situated before a rooted path component. Throwing an Exception would seem like a better behaviour in that situation.
Re: Feature request: Path append operators for strings
On Tuesday, 2 July 2013 at 19:46:34 UTC, TommiT wrote: How would you feel about adding the '/' binary operator and the '/=' assignment operator for strings, wstrings and dstrings? The operators would behave the same way as they do with boost::filesystem::path objects: There is a *massive* difference here. boost::filesystem adds the overload for *path* objects. It doesn't add a global operator for any indiscriminate string.
Re: Feature request: Path append operators for strings
On Tuesday, 2 July 2013 at 20:31:14 UTC, monarch_dodra wrote: On Tuesday, 2 July 2013 at 19:46:34 UTC, TommiT wrote: How would you feel about adding the '/' binary operator and the '/=' assignment operator for strings, wstrings and dstrings? The operators would behave the same way as they do with boost::filesystem::path objects: There is a *massive* difference here. boost::filesystem adds the overload for *path* objects. It doesn't add a global operator for any indiscriminate string. As far as I can tell, Phobos already uses strings or const(char)[] to represent paths all over the place. So, I figured, we can't add a separate Path type at this point because that train has passed. Although, I don't know if that design would have been a better anyway. Division operator for strings doesn't make any sense, and I doubt there will ever be some other meaning for '/' that would make more sense than a directory separator for strings in the context of programming.
Re: UFCS and constructors
On 07/02/2013 10:16 PM, Maxim Fomin wrote: On Tuesday, 2 July 2013 at 19:47:07 UTC, Timon Gehr wrote: Analogies are always broken, but the rest of the post reads to me roughly like: Dogs are not pets, and should not be treated as such. They are fundamentally different from pets. Also, there are no other pets that bark, so it's incredibly bizarre as well as inconsistent with the rest of the notion of a 'pet' to have a pet dog. - Tmion M Gehr class A { this() {} void foo(){} } A a = new A; // calls ctor, not foo Of course constructors are special because not any function is called upon object construction. (We are discussing struct constructors.) Of course. I fully agree. Obviously there is a reason why those functions are called constructors. But one could now extend on the original argument, and say that eg. all the overloading rules should be different for constructors, because they are fundamentally different and should under no circumstances be treated like 'normal functions'. Do you see what the point is? This is not a valid way of justifying a breaking language change. Same logic Logics that can prove some equivalent statements are not necessarily equivalent. (In particular, it does not rule out inconsistency of one of them.) was made when ability to overload some operators was blocked. All operators are, well, operators but you cannot overload all of them. It appears that sometimes it does make sense to restrict operation on some particular elements of the set and sometimes not. ... Such restrictions need to be justified. The justification should make (at least some) sense. There is no point in heuristically designing language features from observations about other language features without applying insight. (Anyway, I do not think that overloading of a fixed set of primitive operators using specially named member functions is a good mechanism for infix notation.)
Re: Feature request: Path append operators for strings
On 7/2/2013 1:47 PM, TommiT wrote: Division operator for strings doesn't make any sense, That's why overloading / to do something completely unrelated to division is anti-ethical to writing understandable code. The classic example of this is the overloading of and for stream operations in C++.
Re: Feature request: Path append operators for strings
On Tuesday, 2 July 2013 at 21:48:54 UTC, Walter Bright wrote: On 7/2/2013 1:47 PM, TommiT wrote: Division operator for strings doesn't make any sense, That's why overloading / to do something completely unrelated to division is anti-ethical to writing understandable code. The classic example of this is the overloading of and for stream operations in C++. I've never thought of it like that. At some point I remember writing a vector type which overloaded its binary * operator to mean dot product (or cross product, I can't remember). So, you can overload an operator, but you can't overload the meaning of an operator.
Re: Feature request: Path append operators for strings
On Tuesday, 2 July 2013 at 21:48:54 UTC, Walter Bright wrote: On 7/2/2013 1:47 PM, TommiT wrote: Division operator for strings doesn't make any sense, That's why overloading / to do something completely unrelated to division is anti-ethical to writing understandable code. The classic example of this is the overloading of and for stream operations in C++. Before C came along, '' meant much less ...
Re: Feature request: Path append operators for strings
On Tuesday, 2 July 2013 at 22:28:24 UTC, TommiT wrote: I've never thought of it like that. [..] Boost Filesystem overloads the meaning of / to mean append to path. Boost Exception overloads to mean add this info to this exception. Boost Serialization overloads and to mean serialize and deserialize, and to mean either one of those. So no wonder I was under the impression that we're allowed to overload the meaning of operators.
Re: Feature request: Path append operators for strings
On Wednesday, July 03, 2013 00:55:59 TommiT wrote: So no wonder I was under the impression that we're allowed to overload the meaning of operators. Well, of course, you _can_ overload them to do different stuff. It's trivial to make most overloaded operators do something completely different from what they do normally. The argument against it is that doing so is bad practice, because it makes your code hard to understand. And for some operators (e.g. opCmp and opEquals), D actually implements the overloaded operator in a way that giving it an alternate meaning doesn't work. You _could_ do it with / though. It's just arguably bad practice to do so. But since you can get the same functonality out of a normal function without the confusion, it really doesn't make sense in general to overload operators to do something fundamentally different with a user-defined type than what they do with the built-in types. However, some people are really hung up on making everything terse or making it look like mathh or whatnot and insist on abusing operators by overloading them with completely different meanings. - Jonathan M Davis
Re: Feature request: Path append operators for strings
On 07/02/13 22:47, TommiT wrote: Division operator for strings doesn't make any sense, and I doubt there will ever be some other meaning for '/' that would make more sense than a directory separator for strings in the context of programming. Umm, $ /usr/bin/pike Pike v7.8 release 537 running Hilfe v3.5 (Incremental Pike Frontend) /a/b//c / /; (1) Result: ({ /* 5 elements */ , a, b, , c }) That's the only sane use of the division operator on string types; anything else would be extremely confusing. And this still does not mean that it would be a good idea in D. Typing out splitter() is not /that/ hard. artur
Re: Feature request: Path append operators for strings
On Tuesday, 2 July 2013 at 22:56:00 UTC, TommiT wrote: On Tuesday, 2 July 2013 at 22:28:24 UTC, TommiT wrote: I've never thought of it like that. [..] Boost Filesystem overloads the meaning of / to mean append to path. Boost Exception overloads to mean add this info to this exception. Boost Serialization overloads and to mean serialize and deserialize, and to mean either one of those. So no wonder I was under the impression that we're allowed to overload the meaning of operators. Such overloads make for code that's fast to write but hard to read, especially to outsiders. It's a tempting direction, but not a good one.
Re: Feature request: Path append operators for strings
On 7/2/2013 4:28 PM, monarch_dodra wrote: The classic example of this is the overloading of and for stream operations in C++. Or overloading ~ to mean concat ? Binary ~ has no other meaning, so it is not overloading it to mean something else.
Re: Feature request: Path append operators for strings
On Tuesday, 2 July 2013 at 21:48:54 UTC, Walter Bright wrote: On 7/2/2013 1:47 PM, TommiT wrote: Division operator for strings doesn't make any sense, That's why overloading / to do something completely unrelated to division is anti-ethical to writing understandable code. s/division/The common agreed upon semantic/ The classic example of this is the overloading of and for stream operations in C++. Or overloading ~ to mean concat ?
Re: Feature request: Path append operators for strings
On Tuesday, 2 July 2013 at 23:08:37 UTC, Artur Skawina wrote: On 07/02/13 22:47, TommiT wrote: Division operator for strings doesn't make any sense, and I doubt there will ever be some other meaning for '/' that would make more sense than a directory separator for strings in the context of programming. Umm, $ /usr/bin/pike Pike v7.8 release 537 running Hilfe v3.5 (Incremental Pike Frontend) /a/b//c / /; (1) Result: ({ /* 5 elements */ , a, b, , c }) That's the only sane use of the division operator on string types; anything else would be extremely confusing. And this still does not mean that it would be a good idea in D. Typing out splitter() is not /that/ hard. artur Perhaps an even more logical meaning for / operator for strings would be to divide the string to N equal sized parts (plus a potential remainder): abcdefg / 3 result: [ab, cd, ef, g] But your divide this string using this divider character is pretty logical too (once you know it).
optimized immutable containers
Is anyone aware of the new immutable containers in .Net framework? http://blogs.msdn.com/b/bclteam/archive/2012/12/18/preview-of-immutable-collections-released-on-nuget.aspx. While we can attach the immutable qualifier to any D containers, they will not perform nearly as well because they are essentially mutable structures. Making them immutable doesn't change the way they work, it merely forbids us to call the modifying methods. Every time we need to modify them we have to copy the entire thing which is not very efficient. The .Net immutable containers are specially optimized so that they share the underlying data as much as possible. Creating a modified copy is cheap, usually O(1) or O(logN). I think having something similar in D would make immutables much more attractive.
Re: optimized immutable containers
finalpatch: I think having something similar in D would make immutables much more attractive. I think that eventually we'll have some good immutable data structure in Phobos (based on finger trees, etc). But first probably there's a need for some mutable ones :-) Bye, bearophile
Re: UFCS and constructors
On Tuesday, 2 July 2013 at 19:47:07 UTC, Timon Gehr wrote: It is an artificial limitation, because you need to add an explicit check after symbol lookup to ban constructors. That seems very implementation defined. The lookup will gives you a class or struct declaration, so special casing the constructor is mandatory anyway.
Re: UDP enhancement
Kapps opantm2+s...@gmail.com wrote in message news:zroaabiwkaxqybrtd...@forum.dlang.org... As someone who uses properties almost everywhere, and almost never uses public fields, this is one of my biggest gripes with D remaining. It's incredibly annoying to have to do things like private int _width; /// Gets or sets the total width, in pixels, of this control. @property int width() const { return _width; } /// ditto @property void width(int value) { this._width = value; } Something like /// Gets or sets the total width, in pixels, of this control. @property const int width; Is just so much nicer and saves so much bloat. I feel like the current property syntax is one of those places where IDE code snippets will start to become, not necessary, but extremely useful. It's the type of manual repetition that D aims to avoid, but in this case fails at. I don't know if I agree with automatically expanding to const though. I'd like to be able to do '@property Control parent' without needing to return a const(Control) because the property is expanded to be const. Although if we had a virtual keyword, final is something that I think should be default for properties, and I think it's a mistake that the current @property doesn't infer final in the first place. Safe and nothrow are two assumptions that are probably quite safe to assume for the most part as well. You should probably try using template mixins, if all you need to do is expand some code.
Re: UFCS and constructors
On Tuesday, 2 July 2013 at 21:38:26 UTC, Timon Gehr wrote: Such restrictions need to be justified. The justification should make (at least some) sense. There is no point in heuristically designing language features from observations about other language features without applying insight. The whole point of UFCS is to be able to provide additional custom methods to a object (class or struct). Constructor UFCS don't fulfill that use case. Nothing is removed from the language as factories method can be introduced anyway.
Re: UFCS and constructors
deadalnix: The whole point of UFCS is to be able to provide additional custom methods to a object (class or struct). Constructor UFCS don't fulfill that use case. Nothing is removed from the language as factories method can be introduced anyway. This frames the topic in a wrong way. Constructors are not normal functions, they are special, but functional languages show us that's it's a very good idea to see them as functions. And the original point of UFCS doesn't matter much. What matters is what are the practical disadvantages of allowing UFCSyntax for constructors (like the original post in this thread), and what are their practical advantages/uses (like a handy usage in UFCS chains). Then we take a look at what's the resulting balance and we decide. And such decisions should then become the written specifics of this part of the D design. Bye, bearophile
Re: UFCS and constructors
On Wednesday, July 03, 2013 04:00:45 bearophile wrote: deadalnix: The whole point of UFCS is to be able to provide additional custom methods to a object (class or struct). Constructor UFCS don't fulfill that use case. Nothing is removed from the language as factories method can be introduced anyway. This frames the topic in a wrong way. Constructors are not normal functions, they are special, but functional languages show us that's it's a very good idea to see them as functions. And the original point of UFCS doesn't matter much. What matters is what are the practical disadvantages of allowing UFCSyntax for constructors (like the original post in this thread), and what are their practical advantages/uses (like a handy usage in UFCS chains). Then we take a look at what's the resulting balance and we decide. And such decisions should then become the written specifics of this part of the D design. The primary benefit of UFCS is generic code, because if uses UFCS, generic code doesn't have to care whether a function is a member function or a free function (particularly when that can vary drastically depending on what type is used to instantiate the template). Construction is not and cannot be generic. The closest that you could get would be a factory function, which is quite different. But constructors themselves cannot be generic. As such, using constructors with UFCS in generic code just doesn't work, meaning that the only gain that you're getting from using UFCS with constructors is that you get a slightly different syntax that you might like better for one reason or another. But I see no technical reason why it could add any benefit over simply calling the constructor normally. And as such, I think that allowing UFCS to work with constructors is definitely an anti-feature. - Jonathan M Davis
Re: UFCS and constructors
On 07/03/2013 04:12 AM, Jonathan M Davis wrote: On Wednesday, July 03, 2013 04:00:45 bearophile wrote: deadalnix: The whole point of UFCS is to be able to provide additional custom methods to a object (class or struct). Constructor UFCS don't fulfill that use case. Nothing is removed from the language as factories method can be introduced anyway. This frames the topic in a wrong way. Constructors are not normal functions, they are special, but functional languages show us that's it's a very good idea to see them as functions. And the original point of UFCS doesn't matter much. What matters is what are the practical disadvantages of allowing UFCSyntax for constructors (like the original post in this thread), and what are their practical advantages/uses (like a handy usage in UFCS chains). Then we take a look at what's the resulting balance and we decide. And such decisions should then become the written specifics of this part of the D design. The primary benefit of UFCS is generic code, because if uses UFCS, generic code doesn't have to care whether a function is a member function or a free function (particularly when that can vary drastically depending on what type is used to instantiate the template). No. Generic code has to be careful with UFCS, because every method that is called on a suitable variable via UFCS can be (accidentally) replaced by the client code. Construction is not and cannot be generic. The point is that struct constructors can be generically used like other callables. import std.stdio, std.algorithm; struct S{ int x; } void main(){ auto x = [1,2,3]; writeln(x.map!S); } There is nothing to be gained from subtly breaking this analogy. UFCS can be applied to any callable. You are probably not going to like this, but the following code also works: import std.stdio; struct S{ int opCall(int x){ return x+1; } } S s; void main(){ auto x = 1; writeln(x.s); } The closest that you could get would be a factory function, which is quite different. But constructors themselves cannot be generic. As such, using constructors with UFCS in generic code just doesn't work, meaning that the only gain that you're getting from using UFCS with constructors is that you get a slightly different syntax that you might like better for one reason or another. But I see no technical reason why it could add any benefit over simply calling the constructor normally. And as such, I think that allowing UFCS to work with constructors is definitely an anti-feature. ... To be an anti-feature it has to be harmful, not just of less benefit than some other (aspect of the) feature.
Re: D vs C++ - Where are the benchmarks?
On Monday, 1 July 2013 at 02:53:24 UTC, Jonathan M Davis wrote: On Monday, July 01, 2013 04:37:43 Mehrdad wrote: On Sunday, 30 June 2013 at 20:49:28 UTC, Peter Alexander wrote: sometimes faster Would love an example that demonstrates it! Anything involving taking a lot of substrings is likely to be faster in D thanks to slices That doesn't mean D is faster. It just means it's less painful to get the same performance. Regarding what someone else mentioned, I wasn't talking about the backend either. As an example of what I was looking for, consider that people claim a GC can be faster than manual memory management. If that's the scenario we're talking about, then what I was asking for is to see piece of _code_ (not a hand-wavy explanation!) that demonstrates GC-based code being faster than non-GC-based code. If it's a different feature (I don't know what), then I'd like to know what it is strictly in terms of performance. In other words, I know C++ is _painful_ to write fast code in, but that doesn't make it slower; it just makes it more painful. On the other hand, if you could demonstrate that e.g. the GC is faster than manual memory management, then I'd totally agree D is faster than C++.
Re: UFCS and constructors
On 07/03/2013 03:37 AM, deadalnix wrote: On Tuesday, 2 July 2013 at 19:47:07 UTC, Timon Gehr wrote: It is an artificial limitation, because you need to add an explicit check after symbol lookup to ban constructors. That seems very implementation defined. It is true for two implementations and one spec I am aware of. The lookup will gives you a class or struct declaration, Hopefully the UFCS lookup gives me a fully analysed call expression. That's the point of specifying features by rewrite rules. so special casing the constructor is mandatory anyway. Yes, the call expression needs some kind of check in order to support struct literals. Cancelling that support in some way in case the call expression happens to have been generated by an UFCS rewrite requires another check, which complicates the formal specification of UFCS for no gain.
Re: UFCS and constructors
On Wednesday, July 03, 2013 04:54:41 Timon Gehr wrote: On 07/03/2013 04:12 AM, Jonathan M Davis wrote: On Wednesday, July 03, 2013 04:00:45 bearophile wrote: deadalnix: The whole point of UFCS is to be able to provide additional custom methods to a object (class or struct). Constructor UFCS don't fulfill that use case. Nothing is removed from the language as factories method can be introduced anyway. This frames the topic in a wrong way. Constructors are not normal functions, they are special, but functional languages show us that's it's a very good idea to see them as functions. And the original point of UFCS doesn't matter much. What matters is what are the practical disadvantages of allowing UFCSyntax for constructors (like the original post in this thread), and what are their practical advantages/uses (like a handy usage in UFCS chains). Then we take a look at what's the resulting balance and we decide. And such decisions should then become the written specifics of this part of the D design. The primary benefit of UFCS is generic code, because if uses UFCS, generic code doesn't have to care whether a function is a member function or a free function (particularly when that can vary drastically depending on what type is used to instantiate the template). No. Generic code has to be careful with UFCS, because every method that is called on a suitable variable via UFCS can be (accidentally) replaced by the client code. That's the whole point! If you absolutely have to be certain that it's not calling a free function, then don't use UFCS, but the primary benefits of UFCS are making it so that generic code doesn't have to care whether a function is a free function and making it so that types can overload the behavior of free functions (e.g. having a member function find which is optimized for that type and can be used in place of std.algorithm.find). Construction is not and cannot be generic. The point is that struct constructors can be generically used like other callables. import std.stdio, std.algorithm; struct S{ int x; } void main(){ auto x = [1,2,3]; writeln(x.map!S); } There is nothing to be gained from subtly breaking this analogy. UFCS can be applied to any callable. You are probably not going to like this, but the following code also works: import std.stdio; struct S{ int opCall(int x){ return x+1; } } S s; void main(){ auto x = 1; writeln(x.s); } That is _very_ broken IMHO. It makes no sense for parens to be optional with opCall. The whole point of opCall is to overload the parens! The closest that you could get would be a factory function, which is quite different. But constructors themselves cannot be generic. As such, using constructors with UFCS in generic code just doesn't work, meaning that the only gain that you're getting from using UFCS with constructors is that you get a slightly different syntax that you might like better for one reason or another. But I see no technical reason why it could add any benefit over simply calling the constructor normally. And as such, I think that allowing UFCS to work with constructors is definitely an anti-feature. ... To be an anti-feature it has to be harmful, not just of less benefit than some other (aspect of the) feature. I _do_ think that it's harmful. It obfuscates code without adding any benefit. - Jonathan M Davis
Re: C standard libraries
It is in core.stdc. For example: import core.stdc.stdio; // stdio.h import core.stdc.stdlib;// stdlib.h etc. Thanks! I'm confused why that module isn't mentioned in the library reference page. What's the difference between core.stdc and std.c? The docs do refer to core.stdc, though std.c.stdio in Phobos' source just imports core.stdc.stdio. The duplication seems a bit weird, and I'm wondering if one method is deprecated or migth be removed in the future.
Re: Handling different types gracefully
Roderick Gibson: Variant is a possiblity. How is the performance with large containers of these, since these structures will likely hold the majority of the data in the game? You probably have to benchmark yourself. (But I have suggested an Algebraic). Bye, bearophile
Re: Eponymous template with full template syntax
On Monday, 1 July 2013 at 22:46:55 UTC, Ali Çehreli wrote: On 07/01/2013 02:10 PM, monarch_dodra wrote: That is confusing. UFCS construction: Yes. I *think* I did not know it but I can't be sure. :) AH... I looked at the threads some more: I was actually thinking about a proposal that wanted (just like UFCS), to allow non-intrusively adding constructors. So I guess UFCS and constructors are fair game? I do not like this at all...
Re: Template constraints and opAdd
John: Mass!(T,S) opAdd(Mass!(T,S) other) { If you are using D2 then don't use opAdd, use opBinary: http://dlang.org/operatoroverloading.html#Binary Time ago I added an enhancement request for a warning (that later is meant to become a deprecation) that helps avoid your problem: http://d.puremagic.com/issues/show_bug.cgi?id=10320 Bye, bearophile
Re: C standard libraries
On Monday, 1 July 2013 at 18:09:32 UTC, Jonathan M Davis wrote: On Monday, July 01, 2013 18:32:30 CJS wrote: Is there some header/module that includes declaration for all C standard libraries? I'm wondering both in general for future reference, and for the specific case of wanting to time a function and not knowing what in D--even after looking through the docs--would do something equivalent to clock and CLOCKS_PER_SEC in the C standard library time.h. If you want to time a function, checkout std.datetime.StopWatch: http://dlang.org/phobos/std_datetime.html#StopWatch +1 I really came to hate c's clock, StopWatch has been much more pleasant experience to work with.
Re: opDispatch and UFCS
On 07/02/13 02:45, cal wrote: import std.conv, std.stdio, std.algorithm; struct S { void opDispatch(string s, T...)(T t) if (s.startsWith(foo)) { writeln(s); } } void main() { S s; s.foo(); auto p = s.to!string(); // Error: s.opDispatch!(to) isn't a template } Should the constraint on opDispatch allow the UFCS to call on S? To avoid this kind of issues: struct S { template opDispatch(string s) if (s.startsWith(foo)) { void opDispatch(T...)(T t) { writeln(s); } } } And, yes, the compiler should be able to handle your simpler case too, but currently doesn't (if there are several overloads then the transformation isn't necessarily this easy). I usually end up doing something like: struct S { static bool _disp(string s) { if (s.startsWith(foo)) return true; // ... other checks, AA lookups, introspection etc. return false; } template opDispatch(string s) if (_disp(s)) { void opDispatch(T...)(T t) { writeln(s); } } } Dealing with the various frontend quirks can be fun. artur
Re: C standard libraries
Use core.stdc, and forget of std.c. Bye, bearophile What's the reason for that?
Re: C standard libraries
Gary Willoughby: What's the reason for that? Moving the C stuff in core is probably a way to remember D programmers that stuff is not normal stuff you are supposed to use in D programs. A D programmer should use the normal safer and nicer D functions. Core is there for special cases. Bye, bearophile
Re: C standard libraries
On Tuesday, 2 July 2013 at 06:33:03 UTC, CJS wrote: Thanks! I'm confused why that module isn't mentioned in the library reference page. I don't know. What's the difference between core.stdc and std.c? std.c is what it was called in earlier versions of D, before there was a clear separation between phobos as the standard library (std.*) and druntime as the runtime library (core.*). Phobos is supposed to be 100% on top of druntime, so it is optional and interchangeable with ease. The runtime, however, needed access to some C functions for its own implementation. Since it isn't allowed to depend on std.*, the C functions got moved into core.*. The older std.c is kept around just for compatibility with the old names before the move, at least as far as I know. Maybe they haven't fully deprecated it though because there's other reasons I don't know about, since it has been many years now since the move.
Re: C standard libraries
Adam D. Ruppe: The older std.c is kept around just for compatibility with the old names before the move, at least as far as I know. Maybe they haven't fully deprecated it though because there's other reasons I don't know about, since it has been many years now since the move. In D/Phobos/Dmd there is a ton of stuff that's supposed to be obsolete, that should not be used, that is deprecated, etc. I presume Walter thinks that the problems caused from keeping it and from unwanted usages of it, is smaller than the breaking troubles caused by removing it. I am person that likes to keeps things ordered and clean, so I prefer to remove old stuff after a suitable deprecation period, instead of keeping it around almost forever (like floating point special comparison operators). Bye, bearophile
Re: Handling different types gracefully
On Tuesday, 2 July 2013 at 06:54:58 UTC, bearophile wrote: Roderick Gibson: Variant is a possiblity. How is the performance with large containers of these, since these structures will likely hold the majority of the data in the game? You probably have to benchmark yourself. (But I have suggested an Algebraic). Bye, bearophile I should know the types at compile time, so I will be using it most likely, but reading the docs it looks like Algebraic is built on top of the same structure as Variant. Is there any difference in implementation?
How to get warnings about unused imports ?
Hi, How to find unused imports ? It seems the compiler doesn't do it, but is there any other tool for that? This seems like small issue, but those unused imports pile up pretty quickly Regards, Gabi
Re: Handling different types gracefully
Roderick Gibson: I should know the types at compile time, so I will be using it most likely, but reading the docs it looks like Algebraic is built on top of the same structure as Variant. Is there any difference in implementation? Take a look at the Phobos source code, it's much faster than waiting for my answer. Algebraic is built on top of VariantN. Algebraic accepts only a limited number of types, while Variant doesn't have such limitation. So Algebraic is type safe. And maybe Algebraic can ideally be implemented more efficiently than a Variant because to denote the contained type an enum suffices, instead of a TypeInfo. Please take a look at VariantN if it contains the enum or a Typeinfo or something else. Bye, bearophile
Re: Handling different types gracefully
On Tuesday, 2 July 2013 at 21:45:57 UTC, bearophile wrote: Roderick Gibson: I should know the types at compile time, so I will be using it most likely, but reading the docs it looks like Algebraic is built on top of the same structure as Variant. Is there any difference in implementation? Take a look at the Phobos source code, it's much faster than waiting for my answer. Algebraic is built on top of VariantN. Algebraic accepts only a limited number of types, while Variant doesn't have such limitation. So Algebraic is type safe. And maybe Algebraic can ideally be implemented more efficiently than a Variant because to denote the contained type an enum suffices, instead of a TypeInfo. Please take a look at VariantN if it contains the enum or a Typeinfo or something else. Bye, bearophile Thanks, I'll do that. Thanks for the help, bearophile!
Re: opDispatch and UFCS
On Tuesday, 2 July 2013 at 11:04:20 UTC, Artur Skawina wrote: To avoid this kind of issues: struct S { template opDispatch(string s) if (s.startsWith(foo)) { void opDispatch(T...)(T t) { writeln(s); } } } That's a handy workaround, thank you.
ref tuples
C++11's std::tuple includes a function std::tie that takes references to the arguments and returns a tuple that maintains the references to the arguments. Along with the usual cases where you'd want reference semantics it also enables this interesting construct for unpacking tuples. int a, b; tie(a, b) = make_tuple(1, 2); assert(a == 1 b == 2); Is there any way to do something similar with std.typecons.Tuple?
Re: opDispatch and UFCS
On Tuesday, 2 July 2013 at 00:45:23 UTC, cal wrote: import std.conv, std.stdio, std.algorithm; struct S { void opDispatch(string s, T...)(T t) if (s.startsWith(foo)) { writeln(s); } } void main() { S s; s.foo(); auto p = s.to!string(); // Error: s.opDispatch!(to) isn't a template } Should the constraint on opDispatch allow the UFCS to call on S? That's a compiler bug. http://d.puremagic.com/issues/show_bug.cgi?id=10526 Kenji Hara
Stop to! rounding?
writeln(to!double(151.42499));//prints 151.425 Is there any way to stop this rounding? Thanks, Josh
Re: Stop to! rounding?
On Wednesday, July 03, 2013 06:23:12 Josh wrote: writeln(to!double(151.42499));//prints 151.425 Is there any way to stop this rounding? No. double can't hold the value 151.42499. There are _tons_ of values that it can't hold exactly. The same goes for float and real. Floating point values are rounded all the time. Note that double d = 151.42499; writeln(d); prints exactly the same thing as your example. - Jonathan M Davis
Re: Stop to! rounding?
On Wednesday, 3 July 2013 at 04:32:15 UTC, Jonathan M Davis wrote: On Wednesday, July 03, 2013 06:23:12 Josh wrote: writeln(to!double(151.42499));//prints 151.425 Is there any way to stop this rounding? No. double can't hold the value 151.42499. There are _tons_ of values that it can't hold exactly. The same goes for float and real. Floating point values are rounded all the time. Note that double d = 151.42499; writeln(d); prints exactly the same thing as your example. - Jonathan M Davis Is there any way I would be able to hold that number then? Thanks, Josh
Re: Stop to! rounding?
On Wednesday, 3 July 2013 at 04:32:15 UTC, Jonathan M Davis wrote: On Wednesday, July 03, 2013 06:23:12 Josh wrote: writeln(to!double(151.42499));//prints 151.425 Is there any way to stop this rounding? No. double can't hold the value 151.42499. There are _tons_ of values that it can't hold exactly. The same goes for float and real. Floating point values are rounded all the time. Note that double d = 151.42499; writeln(d); prints exactly the same thing as your example. - Jonathan M Davis void main() { double d = 151.42499; assert(d == 151.42499); } The rounding occurs in writeln surely.
Re: Stop to! rounding?
On Wednesday, July 03, 2013 07:04:47 cal wrote: On Wednesday, 3 July 2013 at 04:32:15 UTC, Jonathan M Davis wrote: On Wednesday, July 03, 2013 06:23:12 Josh wrote: writeln(to!double(151.42499));//prints 151.425 Is there any way to stop this rounding? No. double can't hold the value 151.42499. There are _tons_ of values that it can't hold exactly. The same goes for float and real. Floating point values are rounded all the time. Note that double d = 151.42499; writeln(d); prints exactly the same thing as your example. - Jonathan M Davis void main() { double d = 151.42499; assert(d == 151.42499); } The rounding occurs in writeln surely. That's true because _both_ of the floating point values there get rounded to 151.425, and 151.425 is equal to 151.425. writeln is not doing anything wrong. I highly suggest that you read this: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html - Jonathan M Davis
Re: Stop to! rounding?
On 07/02/2013 10:09 PM, Jonathan M Davis wrote: On Wednesday, July 03, 2013 07:04:47 cal wrote: void main() { double d = 151.42499; assert(d == 151.42499); } The rounding occurs in writeln surely. That's true because _both_ of the floating point values there get rounded to 151.425, The value that can be stored is not 151.42499, nor 151.425. import std.stdio; import std.conv; void main() { auto a = to!double(151.42499); writefln(%.60f, a); } Prints: 151.4249908194547262974083423614501953125000 writeln is not doing anything wrong. True. It is using its default floating point precision, 6. Ali
Re: Stop to! rounding?
On Wednesday, 3 July 2013 at 05:10:03 UTC, Jonathan M Davis wrote: On Wednesday, July 03, 2013 07:04:47 cal wrote: On Wednesday, 3 July 2013 at 04:32:15 UTC, Jonathan M Davis wrote: On Wednesday, July 03, 2013 06:23:12 Josh wrote: writeln(to!double(151.42499));//prints 151.425 Is there any way to stop this rounding? No. double can't hold the value 151.42499. There are _tons_ of values that it can't hold exactly. The same goes for float and real. Floating point values are rounded all the time. Note that double d = 151.42499; writeln(d); prints exactly the same thing as your example. - Jonathan M Davis void main() { double d = 151.42499; assert(d == 151.42499); } The rounding occurs in writeln surely. That's true because _both_ of the floating point values there get rounded to 151.425, and 151.425 is equal to 151.425. writeln is not doing anything wrong. I highly suggest that you read this: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html - Jonathan M Davis import std.stdio; void main() { double d = 151.42499; writefln(%.10f, d); }
Re: Stop to! rounding?
On Tue, Jul 02, 2013 at 10:14:33PM -0700, Ali Çehreli wrote: [...] import std.stdio; import std.conv; void main() { auto a = to!double(151.42499); writefln(%.60f, a); } I wouldn't write it like that; IMO it's better to write: writefln(%.*f, double.dig, a); So that you don't give the wrong impression that there are more digits than are actually there. Using double.dig also lets you see all the digits that *are* there, not a rounded value, that the OP was complaining about. T -- The easy way is the wrong way, and the hard way is the stupid way. Pick one.
[Issue 10491] Type inference for function arguments with default value
http://d.puremagic.com/issues/show_bug.cgi?id=10491 bearophile_h...@eml.cc changed: What|Removed |Added Status|NEW |RESOLVED Resolution||WONTFIX --- Comment #5 from bearophile_h...@eml.cc 2013-07-02 00:29:40 PDT --- OK, closed. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 7227] [] syntax for empty associative array too?
http://d.puremagic.com/issues/show_bug.cgi?id=7227 --- Comment #5 from bearophile_h...@eml.cc 2013-07-02 00:33:38 PDT --- (In reply to comment #3) This patch has chosen the [] syntax over the [:] syntax. But I prefer the [:] syntax, because it's more precise. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 10475] destructor is called on 'for' loop variable even when initialization failed
http://d.puremagic.com/issues/show_bug.cgi?id=10475 --- Comment #6 from github-bugzi...@puremagic.com 2013-07-02 00:43:41 PDT --- Commits pushed to master at https://github.com/D-Programming-Language/dmd https://github.com/D-Programming-Language/dmd/commit/6c7d77f690f509255950321e3e0fec9f29d02df6 fix Issue 10475 - destructor is called on 'for' loop variable even when initialization failed https://github.com/D-Programming-Language/dmd/commit/aaf64112624abab1f6cc8f610223f6e12b525e09 Merge pull request #2286 from 9rnsr/fix10475 Issue 10475 - destructor is called on 'for' loop variable even when initialization failed -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 7227] [] syntax for empty associative array too?
http://d.puremagic.com/issues/show_bug.cgi?id=7227 --- Comment #6 from bearophile_h...@eml.cc 2013-07-02 00:46:28 PDT --- Having two obvious syntaxes to do the same thing is not so good. So I suggest to also introduce a warning for the usage of null as associative array literal: void foo(int[int]) {} void main() { foo(null); int[int][] aas = [null]; aas[0] = [1: 2, 2: 3]; } = test.d(3): Warning: explicit [:] empty associative array literal is better than null, that will be deprecated test.d(4): Warning: explicit [:] empty associative array literal is better than null, that will be deprecated (The wording of such warning message is modelled on another warning message: test.d(3): Warning: explicit element-wise assignment (a)[] = 2 is better than a = 2) (This warning is not meant to be kept. Later this warning is meant to become a deprecation, and later an error). -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 10320] Warning for old-style operator overloading methods definition
http://d.puremagic.com/issues/show_bug.cgi?id=10320 --- Comment #1 from bearophile_h...@eml.cc 2013-07-02 01:01:58 PDT --- Cases like in this thread show that it's important to give a warning now: http://forum.dlang.org/thread/hwfzaysrfxiiumppx...@forum.dlang.org -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---
[Issue 5207] Immutability is broken in constructors
http://d.puremagic.com/issues/show_bug.cgi?id=5207 --- Comment #3 from Lars T. Kyllingstad bugzi...@kyllingen.net 2013-07-02 02:01:08 PDT --- I'm not suggesting that the assignment be prohibited. Rather, I think it should be illegal to *access* the variable before it is initialised. If the current behaviour is by design, consider this an enhancement request. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email --- You are receiving this mail because: ---