Re: Link time optimization in D
Walter Bright wrote: The link-time optimization is essentially compiling the whole project anyway, That makes no sense. so I don't see how you're saving any time with it over D's approach. You save time by recompiling only files that have changes. More importantly, what if you only have access to the object files? -- Michiel Helvensteijn
Re: Link time optimization in D
Adam Ruppe wrote: You save time by recompiling only files that have changes. But, then the whole program goes through the process again anyway to perform the optimization. You save a little time in skipping parts of the front end for unchanged file, but the whole backend process has to happen anyway. That `backend' process is not the compilation process all over again. It's not even the optimizer phase all over again. It's just the extra optimizations that could not be performed on a file-by-file basis. Or at least it should be. -- Michiel Helvensteijn
Re: The D license
Jesse Phillips wrote: There is really nothing wrong with the opening of the license other than it being more direct than any other license. Yeah. The Software was not designed to operate after December 31, 1999. That's not wrong. Hehe. I still find that part of the license so ridiculously funny. I'm actually thinking of writing a new software license myself: Do not use it in a box. Do not use it with a fox. Do not use it with a mouse. Do not use it in a house. Do not use it here or there. Do not use it anywhere. -- Michiel Helvensteijn
Re: The D license
Jesse Phillips wrote: There is really nothing wrong with the opening of the license other than it being more direct than any other license. Yeah. The Software was not designed to operate after December 31, 1999. That's not wrong. It isn't wrong, just because it is after 2000 doesn't mean the software was designed to work in this millennium. Sure, the software has proven itself, but doesn't make the statement invalid. The language and compiler are still now being worked on under this license, aren't they? Yet the statement is not invalid? Since we are now living after December 31, 1999 (and we haven't invented time travel), that suggests to me that the software is not being designed to operate at all. That's, if not wrong, completely silly. -- Michiel Helvensteijn
Re: The D license
Nick Sabalausky wrote: Michiel's rhyme is a reference to, and slight modification of, the children's book by Dr. Seuss Green Eggs and Ham (I had that as a kid). I didn't know it as a kid. But it is referenced so often in popular television series and such, I eventually had to look it up. It's a catchy rhyme. The Scarlet Pimpernel is often referenced too. He's mentioned in at least Black Adder the Third and The Simpsons (where he is pitted against Zorro). Who says people need literary education? We just need TV. ;-) -- Michiel Helvensteijn
Re: Good Contract programming idiom?
bearophile wrote: What do you think? Do you agree that's better to use exceptions like this to test arguments in public methods (instead of using asserts in preconditions)? Short answer: No! Longer answer: It depends. With exceptions, your methods and constructors basically double as a test of input validity. You can catch the exception and recover. And if this is part of the behavioral specification, that's fine. But I suspect these exceptions are not supposed to be caught, and are only used as makeshift release mode assertions. That's not nice. Preconditions are part of the public interface, and D should treat them better. Even in release mode, I'd want to keep the runtime checks, except if we have static proof of total correctness at every call site, in which case runtime checks are redundant. If the programmer is deadset on removing runtime checks for unproven assertions, he should have to compile with the --dangerous-unchecked-assertions flag. -- Michiel Helvensteijn
Re: Evaluation order
Walter Bright wrote: This is because to me, any asymmetric choice of evaluation order would be arbitrary and wrong. What's so special about left-to-right? Arbitrary, yes. Wrong? no - specifying it removes another source of potential user bugs. Left-to-right is natural because that's the way we read things. I'm sure you are aware that entire cultures read things right-to-left. Anyway, don't think I don't see your reasoning. I can argue your point: * Even though both are equally well-defined behavioral contracts, many people will understand a fixed sequential order better than non-deterministic choice, so might cause more bugs in the latter case. * D already contains English keywords and English libraries. It's already dominantly western, so left-to-right won't be unexpected. I just have this quest for a beautiful and elegant programming language. In such a language, the order of side-effects should not matter in any operation (not just function calls). Operators that are commutative in math (and, or, +, *) should be commutative in the programming language too, regardless of side-effects and short-circuiting (which would still be possible, ask me how). But I understand why D places more value on practicality than beauty and elegance. -- Michiel Helvensteijn
Re: Evaluation order
bearophile wrote: C specifications do not define the order of evaluation for function arguments. It can be left-to-right, right-to-left or anything else and is unspecified. Thus any code which relies on this order of evaluation is not portable. D can solve this problem as I think Java has done, just specifying it, and forcing the compiler to produce hypothetically a bit less efficient code in some situations. Another strategy to solve this problem that's possible in D (and not possible in C) is to allow only pure expressions inside function calls. So in a function call you can put pure expressions like x+5 or calls to pure functions. And then the D compiler is free to leave unspecified the order of evaluation of function arguments. I would prefer that the evaluation order be officially specified as non-deterministic. That is, the standard guarantees that the observable behavior be equivalent to some sequential order of evaluation. For example: void f() {} f(x = 1, x = 2); assert(x == 1 || x == 2); It's the same as what C does, just more formally defined. The compiler is free to choose the most efficient implementation that satisfies the contract. This is because to me, any asymmetric choice of evaluation order would be arbitrary and wrong. What's so special about left-to-right? -- Michiel Helvensteijn
Re: Array operation for computing the dot product?
bearophile wrote: Indeed. The difficult question is, what would the syntax be? What about the simper: x.dot(y) I don't like symmetric operations with an asymmetric syntax. Better: dot(x, y) Even better: dot_product(x, y) Funner: sum(x .* y) -- Michiel Helvensteijn
Re: Function calls
Bill Baxter wrote: byLine() is a function. It changes the state of stdin. Calling it consecutively will in general result in different return values. If there were two guys: stdin.currentLine (property) and stdin.nextLine(), it would be a different story. That's not how it works, I think. Just calling byLine() by itself only returns a range struct. Consuming things from that range is what changes the state of stdin. Ah, my bad. I was guessing. Still, returning a handle from a property that can change the state of the originating object is.. iffy. -- Michiel Helvensteijn
Re: Function calls
Andrei Alexandrescu wrote: I agree. So where's the consensus? Things seemed so clear when people were beaten with @property over their head. If I read the TLP correctly, @property seems not to be working correctly. @property (or any other notation marking property getters/setters) should be enforced. Functions that have it must only be invoked using property syntax. Functions that don't have it must be called with parentheses. That's the whole point. To give the designer of the class control over how it is used. The problem is people blurring the line between what's supposed to be a function and what's supposed to be a property, by abusing property syntax to invoke actions without parentheses. In reality, I believe there's not only a clear line between the two intentions, there's a demilitarized zone. You just need to enforce it. You can't have your cake and eat it too. -- Michiel Helvensteijn
Re: Google's Go
Bane wrote: It looks like to me they are making Google Goo for prestige. Search engine, browser, now programming language... Whats next? OS? Google has designed two operating systems already. Laptops? Google Laptops, Google Phones. Sure. They're just not building the hardware themselves. I myself have a Google Experience phone. Fast food franchise? I was at a programming contest once where Google sponsored the catering. Does that count? :-) -- Michiel Helvensteijn
Re: yank unary '+'?
Andrei Alexandrescu wrote: I can't imagine a use for it and removing it makes the language simpler. I disagree (...) I was mostly talking about overloading operator +. Operator + has a long history of being available for overloading in C++, which we can use to our advantage. It has been used to emulate DSLs, but I think we have much better means to define DSLs in D than to redefine all operators to mean some convention-chosen things. Ok, so it's: I can imagine only one use for it -- but I think we have a better way to do that -- and removing it will make the language simpler. How is that a better reason? I'll ask you again, because I'm really curious. Why would you remove unary plus? * I can't imagine it would make the compiler simpler to any significant degree. If the compiler is well written, unary plus will simply occupy a standard spot in a couple of lists (parser, op-function-names, ...). I doubt removing it would even make a dent in the complexity of the code. * Assuming for the moment that the D language and the D compiler are different things (which they aren't), would it make the language simpler? It would probably only confuse programmers who expect the natural counterpart to unary minus to be present. As for documentation, again, it's a matter of a single spot in a list somewhere. * It doesn't, as far as I can see, take up syntax-space that might be occupied by another more useful feature. * There are even known use-cases. Though for a simple, expected, symmetric feature such as this one, that wouldn't even be a requirement for me. (Note that I'm not especially interested in the unary plus operator per se. I'm just using it as a convenient case-study. I'm more curious about your opinion on why language features should be adopted/tossed/kept.) Best regards, -- Michiel Helvensteijn
Re: yank unary '+'?
Andrei Alexandrescu Wrote: What will removing it gain you? Sancta simplicitas. Hm.. I don't really buy that argument. I see you and Walter removing/witholding things (incomparability operators, logical operator overloading) from the language, because: I can't imagine a use for it and removing it makes the language simpler. Meanwhile, you're keeping C syntax for function-pointers around, and I'm missing syntactic sugar for my tribool. The fact that you or I think there isn't a use for a feature, doesn't mean there isn't one. Programmers keep finding new and unintended uses for language features, which is a good thing. And if you want to simplify the language, I wouldn't start with the unary + when you've still got all that C stuff around. -- Michiel Helvensteijn
Re: should postconditions be evaluated even if Exception is thrown?
Andrei Alexandrescu wrote: This may sound crazy, but if you just follow the facts that distinguish regular error handling from program correctness, you must live with the consequences. And the consequence is - a function's postcondition must be designed to take into account exceptional paths. Only in case of unrecoverable errors is the function relieved of its duty. You don't want the regular postcondition to express exceptional outcomes. However, there *should* be an exception-postcondition clause, which describes the conditions which are guaranteed to hold after an exception is thrown. int f() throws (SomeException, SomeOtherException) pre { } body { } post(int result) { } epost(SomeException x) { } epost(SomeOtherException)x) { } I believe JML does something like this. -- Michiel Helvensteijn
Re: How Nested Functions Work, part 1
language_fan wrote: I agree it would be better to allow forward references for nested functions, I just wished to point out that the current behavior is not a bug, it was built that way. That's great news actually. It might even mean that this might change some day. I still find it silly that it was built that way. Seems to me you should be able to forward-reference *any* symbol that has a value that can't change over its lifetime. Functions, const/immutable vars, typedefs, classes, etc. -- Michiel Helvensteijn
Re: How Nested Functions Work, part 1
Rainer Deyke wrote: I still find it silly that it was built that way. Seems to me you should be able to forward-reference *any* symbol that has a value that can't change over its lifetime. Functions, const/immutable vars, typedefs, classes, etc. That can lead to subtle problems in the case of functions: int i = f(); int f() { return i; } You're right, I forgot about that. You can conservatively statically forbid this. But I admit it makes the 'constant data should obviously be forward-referenceable' thing less convincing. :-) -- Michiel Helvensteijn
Re: How Nested Functions Work, part 1
Jarrett Billingsley wrote: It wouldn't even be that difficult. Basically if you treat forward-referenced nested functions as a sort of goto, the same rules should apply: a call to a nested function may not skip the initialization of any variables it depends on. When i's initializer is evaluated, it has not been declared yet, so the call to f is illegal. It also prevents other invalid use. That's what I meant, yes. Basically, any function that reads i may not be called before i is declared, nor in i's initialization. Of course, in reality, it depends on the control flow within the function. But that's holy grail stuff. So: conservatively. -- Michiel Helvensteijn
Re: How Nested Functions Work, part 1
Michiel Helvensteijn wrote: Basically, any function that reads i may not be called before i is declared, nor in i's initialization. Of course, in reality, it depends on the control flow within the function. But that's holy grail stuff. So: conservatively. Oh, you may also not take a delegate of the function before i is declared. Same reason. -- Michiel Helvensteijn
Re: With block proposal
Freeman wrote: Example: with(a) { :x = x; // Unambiguously means a.x = x :x = .x; // Unambiguously means a.x = .x } I think the plan is to get rid of 'with', and I can't say I disagree. If you can say with(a) { :x = f(); :x = g(); } you can also say { auto w = a; w.x = f(); w.x = g(); } or similar. Hardly any longer, and without the need for a whole language construct. -- Michiel Helvensteijn
Re: With block proposal
Daniel Keep wrote: you can also say { auto w = a; w.x = f(); w.x = g(); } or similar. Unless a is a value-type member of something else. That's why I said 'or similar'. Doesn't D have anything to create an alias/reference to a value-type variable? -- Michiel Helvensteijn
Re: D should disallow forward references
Adam D. Ruppe wrote: I can't take your GPL program and arbitrarily change the license to proprietary, and similarly (I assume) he can't take his proprietary license and change it to GPL. Without following the rest of the conversation: Yes, the copyright owner can release his work under more than one license, including both open and closed licenses. GPL + proprietary is fine. Qt does it, for example. -- Michiel Helvensteijn
Re: D should disallow forward references
Michiel Helvensteijn wrote: Without following the rest of the conversation: Yes, the copyright owner can release his work under more than one license, including both open and closed licenses. GPL + proprietary is fine. Qt does it, for example. I'm sorry. It seems I *should* have followed the conversation first. :-) My comment seems to be a bit irrelevant. -- Michiel Helvensteijn
Re: D should disallow forward references
grauzone wrote: Conclusion: other than trying to keep a buggy feature, that isn't going to be fixed, remove it from the language. A bit silly, since it's really quite easy. It just requires an extra compiler pass. Any constant data should be forward referenceable. That means functions, types and const (immutable, enum, etc.) symbols/vars. Seems to me like reference resolving is one of the first things that should work correctly. I'd drop everything and fix this bug before working on anything else. :-) -- Michiel Helvensteijn
Re: OT - Which Linux?
Paul D. Anderson wrote: I'm going to add Linux to my PC to get a dual-boot configuration. (I'm tired of slw start ups and want to tap into the great tools available.) The tutorial I'm looking at suggests Ubuntu. Is there a significant difference in Linux implementations? Is Ubuntu one of the better ones? Does it make a difference for running D2? It depends on what you want and how much experience you have. Ubuntu is certainly a good one to start with. Or one of its flavors. E.g. if you like KDE, go for Kubuntu. I myself have never looked back since I started using Gentoo. A bit more advanced. But a great way to learn the internals of Linux. It has a lot of online documentation and a helpful community. It also makes my system blazing fast, since every package is compiled from source. There's really no difference between distro's when it comes to running, well, most any linux application. -- Michiel Helvensteijn
Re: It's awfully quiet
Lars T. Kyllingstad wrote: I'm done! Congrats! Did your opponents give you a hard time? Congrats Andrei! Still two years to go, here. :) Four here. I'm starting September 1 this year. -- Michiel Helvensteijn
Re: Explicitly saying ref or out when invoking a function
Ary Borenszweig wrote: In C# when you define a function that takes an out or ref parameter, when invoking that function you must also specify ref or out. For example: void fun(ref uint x, double y); uint a = 1; double b = 2; fun(ref a, b); What do you think? I see what you mean, however: - swap(ref a, ref b); I think that's overly verbose for a call with very descriptive function name to begin with. - Perhaps an IDE can use formatting to show you the ref parameters. - The designer of the function can always request pointers, so the caller has to explicitly pass addresses. -- Michiel Helvensteijn
Re: Void-safety (and related things)
bearophile wrote: You can't ask a single person to be able to do everything. Are you able to implement that thing? Probably I am not able. If someone here is able and willing to do it then I suggest such person to ask Walter permission to implement it. I doubt it's the direction D wants to go. Because proving correctness at compile-time requires the holy grail, and testing correctness at runtime requires extra space for each variable and extra time for each access. -- Michiel Helvensteijn
Re: Void-safety (and related things)
Ary Borenszweig wrote: I doubt it's the direction D wants to go. Because proving correctness at compile-time requires the holy grail, and testing correctness at runtime requires extra space for each variable and extra time for each access. What do you mean by holy grail? You missed that discussion, did you? Basically, if you want to know at compile-time whether a variable is initialized, there are several possibilities: * Be overly conservative: Make sure every possible computational path has an assignment to the variable, otherwise give an error. This would throw out the baby with the bathwater. Many valid programs would cause an error. * Actually analyze the control flow: Make sure that exactly all reachable states have the variable initialized, otherwise give an error. Dubbed holy grail, because this sort of analysis is still some time off, and would allow some very cool correctness verification. -- Michiel Helvensteijn
Re: T[new]
Walter Bright wrote: But I know, unique isn't easy to implement to fit all the use cases we'd like to solve. I'm just sharing a dream. We explored unique at length, and trying to make it work would render the rest of the language nearly unusably complex. I've heard 'unique' mentioned on this group now and then. What does it mean in the context of programming languages? -- Michiel Helvensteijn
Re: proposed syntax change
Paul D. Anderson wrote: I was browsing the Python spec yesterday and came across this interesting and useful syntax: / (one slash) means floating point division, e.g. 5/2 = 2.5 even though 5 and 2 are integers // (two slashes) means integer (floor) division, e.g. 5.0//2.0 = 2.0 even though 5.0 and 2.0 are floats. Yeah, I love that distinction. As a matter of fact, I've added it to my own language. Same syntax, too, though there was some thought about using the div keyword instead. I've always been a little troubled by the standard division operator being dependent on the types of the operands. (I understand the need for it, I just didn't like it much.) Now here is an elegant (IMHO) solution. I agree. It's one of those C idiosyncrasies the world could do without. It seems to me that this could be added to D with very little effort and would add a feature to the language. Seems like trouble to me. If we ignore for the moment the fact that // is used for line comments (D could use div, for example), changing the meaning of / for integer operands would probably break many programs. Oh wait...I think // is used elsewhere. Well, we could still use it but mark it as a breaking change. Then users could simply remove all previous uses of // from their code. If they REALLY need to retain the old // functionality we could replace it with a new symbol. How about --, like Ada? Oh wait... Line-comments are very useful. My language uses |. -- Michiel Helvensteijn
Re: reddit.com: first Chapter of TDPL available for free
The compiler allows omitting type declarations only when types can be unambiguously inferred from context. That's not exactly true, is it? A small non-negative integer literal could be an integer of any width or signedness. Yet 'int' is arbitrarily chosen for some reason. There are also multiple floating point types. My points: * The line I quoted is incorrect. Int/float literals are not unambiguous. * D literals can have a suffix specifying the exact type. Perhaps that's worth mentioning. I find your style of writing a bit too informal, though easy to read. -- Michiel Helvensteijn
Re: property syntax strawman
Andrei Alexandrescu wrote: auto data = std.file.readText(filename).chomp.split; I love that too. Unfortunately, the way the water is moving, it looks like we'll lose some or all of that. That's not really true. Some of those no-parameter functions are just meant to be read-only properties instead of functions. auto data = std.file.textFrom(filename).chomped.split; -- Michiel Helvensteijn
Re: property syntax strawman
KennyTM~ wrote: auto data = std.file.readText(filename).chomp.split; I love that too. Unfortunately, the way the water is moving, it looks like we'll lose some or all of that. That's not really true. Some of those no-parameter functions are just meant to be read-only properties instead of functions. auto data = std.file.textFrom(filename).chomped.split; So to allow omission of the parenthesis of these read-only properties we do No, it's not allowing omission, it's forcing omission. That's what properties are. @property string chomped (string x) { ... } ? I don't think Walter's syntax is capable of introducing properties to these free methods, but the property attribute can. I still think an identifier is either property or function, but not both. And judging by the way the wind is blowing, attributes/annotations will not be used for properties. (However, this may make chomped = abcd valid, which is not what we want.) No, it wouldn't, since it'd be a read-only property. That means you can only read, not write. -- Michiel Helvensteijn
Re: My body is ugly [Re: Contextualizing keywords]
Pete wrote: I think this is much more elegant: # int foo(int a) { #in { # assert(a2); #} # #return a-1; # } I have to disagree. That suggests that 'in' is a scope within the body, which would have access to its local variables. Of course, it shouldn't. -- Michiel Helvensteijn
Re: My body is ugly [Re: Contextualizing keywords]
I think this is much more elegant: # int foo(int a) { #in { # assert(a2); #} # #return a-1; # } I have to disagree. That suggests that 'in' is a scope within the body, which would have access to its local variables. Of course, it shouldn't. If you make 'in' clauses 'pure' (which they are, conceptually), it works fine. But 'in' still needs read-access to the actual parameters and every visible symbol in a scope shallower than that of the function. I agree with Pete, I think that's a greatly superior syntax to what we have now. Then I assume you still want to restrict the precondition to being the first element in the body? Because putting it in there suggests that it may appear anywhere a statement can. -- Michiel Helvensteijn
Re: My body is ugly [Re: Contextualizing keywords]
Denis Koroskin wrote: Then I assume you still want to restrict the precondition to being the first element in the body? Because putting it in there suggests that it may appear anywhere a statement can. Why not? Because a function precondition indicates the set of admissible states before execution of a function. Emphasis on *before* and *function*. -- Michiel Helvensteijn
Re: My body is ugly [Re: Contextualizing keywords]
Denis Koroskin wrote: Because a function precondition indicates the set of admissible states before execution of a function. Emphasis on *before* and *function*. Allowing them anywhere inside a function body will only improve the feature. BTW, it is already allowed, just use 'debug' instead of 'in': Or just use an assertion without an enclosing scope? The difference between a precondition (in) and an arbitrary assertion inside the function body is that the precondition is part of the public interface, whereas the function implementation is not. TBH, I'd just drop the whole DBC feature from a language, it creates more problems than solves. I, on the other hand, believe it's the future of program verification. -- Michiel Helvensteijn
Re: My body is ugly [Re: Contextualizing keywords]
Don wrote: It would be strange to put outer function statements before the precondition, but that's true of any inner function. I don't see it as an inner function, but as a part of the public interface. It's an enforceable documentation of the function. -- Michiel Helvensteijn
Re: property syntax strawman
Steven Schveighoffer wrote: So your answer is, there is no ambiguity because it's not possible to access the getter/setter directly? That poses a problem for existing code which uses delegates to such functions. I'm not sure we want to lose that ability. I agree. But it's hardly up to me, is it? :-) -- Michiel Helvensteijn
Re: Contextualizing keywords
Michael Mittner wrote: For future extensibility it should be keyword type=pure SomeType foo() { /* ... */ } ;) You forgot the closing tag. -- Michiel Helvensteijn
Re: property syntax strawman
Walter Bright wrote: bool empty { ... } void empty=(bool b) { ... } The only problem is when a declaration but not definition is desired: bool empty; but oops! That defines a field. So we came up with essentially a hack: bool empty{} i.e. the {} means the getter is declared, but defined elsewhere. What do you think? It is quite hack-ish. There are ways to have your cake and eat it too. I wouldn't settle for 'bool empty{}'. -- bool empty { void set(auto value) { ... } auto get() { ... } } empty = false; // empty.set(false) auto b = empty; // auto b = empty.get() -- for example, requires no hacks and no keywords. And has the added advantage that you can still use the getter and setter methods directly. To call them or get delegates from them. -- Michiel Helvensteijn
Re: property syntax strawman
Michiel Helvensteijn wrote: -- bool empty { void set(auto value) { ... } auto get() { ... } } empty = false; // empty.set(false) auto b = empty; // auto b = empty.get() -- for example, requires no hacks and no keywords. And has the added advantage that you can still use the getter and setter methods directly. It should be noted that there is an ambiguity if the type of the property is a struct/class with members named 'get' and 'set'. As I see it, there are three ways to resolve it: * Disallow properties with such a struct/class. This seems a little bit excessive and silly. But it is one way. * The 'set' and 'get' from the property are only used for the property-calling syntax. They can not be referenced directly. The members of the struct/class would all be accessable. This would work about the same way as, for example, the suggestion from John C in this thread. And if you go down this path, you might as well condense the syntax, as he did. * The 'set' and 'get' from the property are accessable functions and they overshadow possible member functions with those names. My language uses the third way, but there is no problem with overshadowing. The 'set' and 'get' functions have the same special purpose for every type, and the property is meant to override them. I guess D could do something similar using, instead of my 'get' and 'set', D's 'this' and 'opAssign' respectively. -- Michiel Helvensteijn
Re: property syntax strawman
JPF wrote: There's at least one more solution: define the property as -- bool empty { void set(auto value) { ... } auto get() { ... } } -- but rewrite empty.get/set to empty.__get/__set. As far as I know names beginning with __ are reserved, so the returned type of the property couldn't define it. This may be acceptable. I don't much like that the double-underscore is necessary, but it may be the best solution there is. auto getter = empty.__get() You meant without the parentheses here, right? As an addition -- auto b = empty -- would then return a pointer to the returned value. That would be a pointer to a temporary value, though. Not very useful. But lexically, it works, yes. -- Michiel Helvensteijn
Re: property syntax strawman
Andrei Alexandrescu wrote: I'd like to have an easy enough syntax for defining read-only properties (often in my code). With the proposed syntax, one writes bool empty { ... } and calls it a day, but with the elaborate getters and setters there are two scopes to get through: bool empty { auto get() { ... } } which is quite some aggravation. The point is not really the grouping of elements within brackets. That just eliminates some redundancy. It can also look like the following: void empty.set(bool value) { ... } bool empty.get() { ... } and have the same meaning as my earlier example. -- Michiel Helvensteijn
Re: property syntax strawman
Andrei Alexandrescu wrote: void empty.set(bool value) { ... } bool empty.get() { ... } Yah, I was thinking the same. This is my #1 fave so far. You should read my reply to myself, though. It describes an ambiguity in the approach. Several solutions are discussed. (Just translate them from grouping to non-grouping solutions.) -- Michiel Helvensteijn
Re: property syntax strawman
Andrei Alexandrescu wrote: You should read my reply to myself, though. It describes an ambiguity in the approach. Several solutions are discussed. (Just translate them from grouping to non-grouping solutions.) My reader does not show that message. How strange. http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.Darticle_id=94712 -- Michiel Helvensteijn
Re: property syntax strawman
Andrei Alexandrescu wrote: Then in a later message you mention: bool empty.get() { ... } void empty.set(bool b) { ... } which I like and which does not seem to have difficulties; the names get and set will be never used as such. Yes, those are two notations for the same thing, and they have the same problem. Let me demonstrate: -- struct S { int get() { return 42; } }; struct T { S _s; S property.get() { return _s; } void property.set(S s) { _s = s; } } T t; auto X = t.property.get(); -- What is the type of X? It can be either S or int, depending on how D handles the situation. The ambiguity is in the possibility to directly reference the getter and setter methods. In that other subthread (the older one) I listed some possible solutions. The first is to make such a program an error. The second is not to allow a direct reference to a getter/setter (so X is an int). The third is to let the getter/setter overshadow S members (so X is an S). -- Michiel Helvensteijn
Re: Omissible Parentheses...
Leandro Lucarella wrote: Well, just take parameter-less functions then: hello .strip.toupper.replace(O, A); // HELLA Those would be fine candidates for read-only properties: hello .stripped.inupper.replace(O, A); -- Michiel Helvensteijn
Re: property syntax strawman
Andrei Alexandrescu wrote: I see. My view is that .get and .set are simply symbolic placeholders, but indeed some may get confused. In my design, they are actual functions with actual names. For D this doesn't really work. If you want symbolic placeholders, you may want to use something other than 'get' and 'set'. For example, 'in' and 'out' have been suggested by some. They are already keywords. -- Michiel Helvensteijn
Re: property syntax strawman
Michel Fortin wrote: In my design, they are actual functions with actual names. For D this doesn't really work. If you want symbolic placeholders, you may want to use something other than 'get' and 'set'. For example, 'in' and 'out' have been suggested by some. They are already keywords. One thing with in and out makes me uneasy. Imagine a setter/getter with a contract: int prop.out() out (result) { assert(result 3); } body { return something; } void prop.in(int v) in { assert(v 3); } body { something = v; } Wouldn't it be a little confusing having twice the same keyword so close but with a completly different meaning? I agree, it's far from ideal. Well, I'm sure a solution can be found. It's now just down to detail. -- Michiel Helvensteijn
Re: YAPP - D properties - voting
Andrei Alexandrescu wrote: It is ridiculous, particularly in light of the fact that no poll shows the landslide prevalence of everybody. Not everyone may agree, or understand. But if you look at it objectively, D's 'properties' cause inconsistencies, ambiguities and limitations. I'm not listing them again, since it doesn't seem to have any effect. I fully understand that the simple rewriting rules currently used were by far the easiest way to get properties into D. No extra syntax or anything. Walter probably only needed a day or two to put them into the compiler. Not much thought had to go into it. This is evident by the fact that +=, ++, etc. don't work. And then you could advertise that D had properties. Then some people started to abuse property syntax to save three keystrokes (one for the shift-key). So now all of a sudden, real properties can't ever work for D, since you'd lose your no-parentheses function-calls, and some backwards compatibility. But it is a flawed design. Many people have tried to explain this to you. But when faced with the facts, both you and Walter avoid the issue. You focus on minor mistakes in peoples posts and then ignore their real message. And often you simply never reply. Take, for example: http://www.digitalmars.com/d/archives/digitalmars/D/Reddit_why_aren_t_people_using_D_93528.html#N93753 I don't think D will soon adopt the kind of properties some of us have been advocating. You'll just treat the symptoms, I expect. This post is not meant to convince you. It simply needed to be said. I apologize for my confrontational tone. -- Michiel Helvensteijn
Re: Omissible Parentheses...
Robert Jacques wrote: I like them too (a lot). I find they increase the clarity of my code (particularly function chaining). I think that when you find you need to use function-chaining, the functions (except possibly the rightmost) are often meant to be properties/fields. That's why they would look more natural without parentheses. -- Michiel Helvensteijn
Re: Yet a new properties proposal
Sjoerd van Leent wrote: The this rules out another symbol. Unless fields use the same new symbol. Yes, but won't that reintroduce the problems that are already available? The solution is easy. You just add a second # to properties. :-) -- Michiel Helvensteijn
Re: A simple rule
downs wrote: 1) If it's a word, put it in the standard library. 2) Otherwise, put it in the compiler. What an interesting theory. For example: assert() - library. Compile-time proof of assertion/contract correctness would be far more problematic. complex - library. void - C-derived, compiler. I believe void should be a typedef of the empty type-tuple. That would be library. real - C-derived via long float, compiler. cfloat - library. for - compiler. Might as well put this one in a library, since it's easy to simulate with a while-loop. The only reason D can't is that, as far as I know, it doesn't support trailing delegate literals after a function-call, that fill the role of its last actual parameter. foreach - library. Perhaps. But that would make static analysis more problematic. T[] - compiler. I'd rather see dynamic arrays in a library. A template class that overloads the T[] notation. Isn't it true that programmers don't have any control over the allocation strategies and such of the built-in data-structures? T.dup, T.sort, T.reverse - library. Agreed on that one. But what about these: const immutable class struct typedef template ref shared Well, you get the point. It turns out to be a bit of a silly rule, doesn't it? Perhaps you meant: If it's a word, put it in the standard library, unless it belongs in the core language. :-) -- Michiel Helvensteijn
Re: Reddit: why aren't people using D?
Rainer Deyke wrote: For my money, the best solution is a simple property keyword as a function modifier. Only functions with the property modifier would be allowed to pose as fields (getters called without parens, setters called using assignment syntax). But, in all other respects, they should act just like functions. I like being able to distinguish between the property itself and its setter/getter function. May I remind the group of a possible solution I've offered before? Here it is, slightly modified to go along with the current no grouping of setters and getters trend. -- class C { int foo.get() { ... } void foo.set(int value) { ... } } C c; c.foo = 5; // c.foo.set(5); i = c.foo; // i = c.foo.get(); d = c.foo.get; // d = delegate to foo getter -- It doesn't make your eyes bleed (I think). And you have a way to distinguish between getter, setter and property. The downside for D is that get() and set() may overshadow member functions of the property type. In my own language, this is not an issue, since get() and set() are special functions that have the same meaning for each type. And overriding them is just what a property is supposed to do. -- Michiel Helvensteijn
Re: DIP4: Properties
BLS wrote: I think people got it. But it's not a property. Your one-liner seems to be equivalent to a field. Except, I guess, that you can't take the address. The whole idea of a property is that it can have non-trivial getter/setter functions. Like a read-only property of a Line, that returns its length automatically calculated from its two points. Or a getter and setter that keep a log of all accesses to the information. My favorite example is of a Color class, that internally stores its value in the RGB model, but has properties to read and change its value through the HSV and HSL models as well. ... Again, what is the difference between your one-liners and simple fields? immutable property uint theAnswer = 42; bool has_cojones; A property is much more sophisticated. The whole point is to write your own setter and getter methods. Only in very few cases do you want a property with simple field semantics. I will give you that Line class I was talking about. Tell me how you can do this with your one-liner: class Line { private: Point _a; Point _b; public: this(Point a, Point b) { _a = a; _b = b; } property float length { auto get() { float absX = abs(_a.x - _b.x); float absY = abs(_a.y - _b.y); return sqrt(absX * absX + absY * absY); } } // insert trivial properties to read/write points } You see, the length property doesn't have its own storage. It deduces its value from the points of the line. -- Michiel Helvensteijn
Re: Reddit: why aren't people using D?
bearophile wrote: Michiel Helvensteijn: I don't know a compelling use-case either. But that doesn't mean there isn't any. Nor are there any real dangers. Arbitrarily restricting the possibilities of D doesn't seem like the right way to go. Adding random features to a language just because they look cool is a terrible thing to do. This was about overloading , || and !, right? It's not a random feature. It's a logical consequence of the operator overloading system. Leaving them out is arbitrary. You will never convince me that a potentially useful feature should be left out because it could potentially be abused. By the way, I did think of a compelling use-case just yesterday. Boost has a three-valued bool type. true, false and maybe. Seems pretty logical to overload the boolean operators for it. -- Michiel Helvensteijn
Re: DIP4: Properties
Daniel Keep wrote: I used an example without trivial properties because... well, you just use member variables for that. That's why I don't see real value in adding default properties getter/setters. interface I { int opGet_value(); } You cannot use fields in an interface. You do understand that properties with automatic backing storage would probably also not be allowed in interfaces. They'd have the same memory layout problems as fields. -- Michiel Helvensteijn
Re: DIP4: Properties
Daniel Keep wrote: You do understand that properties with automatic backing storage would probably also not be allowed in interfaces. They'd have the same memory layout problems as fields. *blink* *blink* You wouldn't declare a property with automatic backing in an interface; that would be specifying implementation which you're not allowed to do. I was demonstrating why trivial properties exist in real code. It's the *class* that would declare a property with automatic storage. Ah, you're talking about the interface to a property, not the property itself. I see what you mean now. My mistake. -- Michiel Helvensteijn
Re: DIP4: Properties
BLS wrote: A one liner should do the trick too. [public] [const] property int i; I am a little bit ''' about the feedback : Is there really nobody who got it : I think people got it. But it's not a property. Your one-liner seems to be equivalent to a field. Except, I guess, that you can't take the address. The whole idea of a property is that it can have non-trivial getter/setter functions. Like a read-only property of a Line, that returns its length automatically calculated from its two points. Or a getter and setter that keep a log of all accesses to the information. My favorite example is of a Color class, that internally stores its value in the RGB model, but has properties to read and change its value through the HSV and HSL models as well. -- Michiel Helvensteijn
Re: DIP4: Properties
I think I made a few mistakes in the D code, but the point stands. -- Michiel Helvensteijn
Re: DIP4: Properties
Daniel Keep wrote: Basically, the idea is that this: interface I { int foo(); int foo(int); } becomes: interface I { int opGet_foo(); int opSet_foo(int); } It's a little better. But there's still ambiguity: interface I { int foo; int opSet_foo(int); } foo = 5; // which foo is used? To fix that one, you need to report an error when both a var and a property of the same name are declared. Even though they don't have the same name in the interface. interface I { int opGet_foo(); void delegate() opGet_opGet_foo(); } auto x = opGet_foo; Is that the function or the property? Well, perhaps this is not an actual ambiguity in D. But it sure isn't pretty: auto x = opGet_foo; // it's the property auto x = opGet_foo(); // it may be either? auto x = opGet_foo; // it's the function I just don't understand this resistance against a dedicated property syntax. -- Michiel Helvensteijn
Re: Reddit: why aren't people using D?
Jarrett Billingsley wrote: You're suggesting adding something like 25 operator overloads to every property. Can you say code bloat? It may not be necessary in simple situations where the compiler can figure out that it may use a more direct way. But I believe it is the right way to go if you want more speed out of your properties, yes. Why not just use the following solution, which has been proposed God-knows-how-many-times and already has precedence in other languages (like C#)? obj.prop op= value; Simply becomes: obj.prop.set(obj.prop.get op value); There are several issues with that suggestion: * It works only if (a op= b) always behaves the same as (a = a op b). * It would only work for op= operators. It can't do anything for arbitrary mutator methods on the type of the property. * In most situations, it will still be as slow as my suggested 'slow way', without any extra operator overloads! I will repeat my 'slow' transformation here again: obj.prop op= value; // auto temp = obj.prop.get(); // temp op= value; // obj.prop.set(value); At least with that you don't have those first two issues. -- Michiel Helvensteijn
Re: What makes D, D?
Sean Kelly wrote: Compiler writers are free to add features so long as they're compatible with the base language--just look at Microsoft's C++ compiler. What makes a D compiler a D compiler is that it conforms to the D language spec. That's not exactly true, now is it? There is no D spec. A D compiler is a D compiler if: * it is DMD, or * it translates D code the same way as DMD. -- Michiel Helvensteijn
Re: Reddit: why aren't people using D?
Walter Bright wrote: That's my problem with properties as a distinct syntax - they don't have distinct uses or behaviors. You know, I don't believe I've seen you reply specifically to any of the good points about D's properties people have been mentioning around here. I believe the list I gave you in the 'big' subthread was fairly complete. Would you please tell us what you think about each point? I'll repeat that specific section of my reply here: Why not? Seriously, what is the semantic difference? There are many reasons. Some have been floating around this newsgroup this very day. * A reference to a function should mean exactly that: a reference to the function, for use in functional programming. Instead, just the name of a function now invokes a call. * In D, foo returns a function-pointer, but that means that D is context sensitive, since its subexpression foo would return a property value. It is confusing. * What does D do if you have a property (p) that returns a delegate? Will the call p() return the delegate? Or will it call the delegate? * writefln = 5; This should just not be valid code. But it is. * Real Properties have many advantages over what looks like D's ad-hoc solution. They automatically document themselves as properties both to the programmer and to IDE's (see some other posts from today). The programmer may use them to overload certain operators and mutator functions that would speed up the program. Months ago there was a big thread about Real Properties. I myself offered a suggestion for their design. I don't remember if you ever responded. That's just a few reasons right there. D's properties lack elegance and they lack potential. PS: I don't mean to gang up on you. You're just not making yourself clear on where you stand on these points and why. -- Michiel Helvensteijn
Re: What makes D, D?
Dimitar Kolev wrote: Now why would someone want to make their own compiler instead of helping develop this one is something I do not really understand. There may be several reasons. Most important is that Walter owns the original compiler, and only he can decide what goes in and what goes out. So if you and he disagree, all you can do is start a fork. Also what is the deal with Tango, why make another library instead of extending the existing one? Same reason. -- Michiel Helvensteijn
Re: Reddit: why aren't people using D?
Walter Bright wrote: That's just a few reasons right there. D's properties lack elegance and they lack potential. Let's start with: 1. What is a property? 2. How is that different from, say, a pure function? I agree with Bill's reply to this one. Again it appears you're avoiding those specific issues I mentioned. Quite blatantly, I might add. Many people have been asking you the same thing. Do you not have a answer? -- Michiel Helvensteijn
Re: Reddit: why aren't people using D?
sensibly interact with operator overloading I have no idea. See my comments above about lazy parameter evaluation. I suggest that those operators are defined with a lazy second parameter for bools, and programmers should be allowed to overload them for other types as they please. I know of no language that allows overloading and ||. C++ does. ! too. * Tuples (no dedicated syntax, no parallel assignment, no non-flattening tuples without workarounds, no returning tuples) The flattening thing is a problem. The rest can be done with better library support. You cannot get a dedicated syntax with library support. I've mentioned I'm working on a programming language myself. I haven't mentioned its name here, because I didn't think it'd be appropriate. But with your permission I can post a link to a page describing my tuples. * Unit testing (not at compile time, You can do testing at compile time with static asserts. Not unit testing, surely. not possible to categorize) I agree that D's built-in unit testing is basic. But the fact that it exists *at all* is a huge improvement for a programming language. I firmly believe that its mere existence has been a big factor in improving the general quality of D code. Perhaps. But all these available but underpowered features make D look like a playground rather than a serious language. It's as if you think of a new feature, try it out for a week, then abandon it (I know, I'm exaggerating). The fact that you want more from unit testing is great. Unit testing has raised the bar of expectations on a language, and in that it's a home run. The fact that I want more, but you can't provide it, is a home run? :-) I maintain that D suffers greatly from its lack of a formal specification. Perhaps, but remember that most languages don't get formal specs until long after they become popular. Consider that C++ was defined by cfront for the first 10 or 12 years of its existence. That was then, this is now. In the now, we have a C++ with classes and templates and a very strict standards committee overseeing its specification. You want to know why people in the now choose C++ over D? This is one reason. Not only does the D specification feel really unstable, I admit I'm not good at writing language lawyer text. But the D1 spec isn't unstable. The feature set is set, it's pretty clear Yes, but 'pretty clear' does not a spec make. I refer you to our earlier divide/modulo discussion. You expect programmers that want details to look at the DMD source code? And when you change a formal specification, people at least know the language changes as a result. When you change the compiler, we don't know if the language has changed or not. I know that most people can distinguish between a bug and a feature. But when you want to play with the big boys, you need to make it unambiguous. Much of D's improvements appear to be small, but the aggregate is large enough that once you write a project in D, you'll find it pretty hard to go back to another language. I don't dispute that most changes D has made to C++ are good, and that the result is greater than the sum of its parts. And if it weren't for all my other complaints, this one would not be enough to keep me from D. -- Michiel Helvensteijn
Re: Reddit: why aren't people using D?
Nick Sabalausky wrote: Not apt-get easy of course, Linux Gentoo does have DMD in portage, by the way. apt-get easy. Or, to be more precise, emerge easy. -- Michiel Helvensteijn
Re: Reddit: why aren't people using D?
Andrei Alexandrescu wrote: So the solution in D would then be to always use struct? No, because value semantics seems to come at the price of inheritance. Why? C++ seems to handle inheritance in value types just fine. I think C++ does not handle inheritance in value types all that well, in fact the way it deals with the collision is pretty gruesome. It's all dark corners and dangers and caveats and puzzling behavior. Walter said something similar. I'm curious, which collision are you referring to? Which dark corners and dangers and caveats and puzzling behavior? Can you explain? Or perhaps refer me to a web location that explains? Thanks. -- Michiel Helvensteijn
Re: Reddit: why aren't people using D?
Andrei Alexandrescu wrote: The issues are discussed in the book C++ Coding Standards and also in More Effective C++. Part of the problem is slicing, which you may want to google for. I'm aware of slicing. I didn't really think of it as a problem. But now that you mention it, I suppose it can be confusing. And perhaps violate class invariants. There may be a solution. What I'm thinking now is that in the background, the heap may be used, as long as this is transparent to the programmer. i.e. assignment still makes a copy, comparison still compares the objects, not the addresses. But a base class value variable still has a superclass object in the background. This requires some thinking. Thanks for the clarification. -- Michiel Helvensteijn
Re: Reddit: why aren't people using D?
can't recall ever seeing anyone use it, though. Until there's a compelling use case for it, not just it being a nice idea, I'll stick with my belief it's a bad idea. I don't know a compelling use-case either. But that doesn't mean there isn't any. Nor are there any real dangers. Arbitrarily restricting the possibilities of D doesn't seem like the right way to go. You cannot get a dedicated syntax with library support. Of course that's true, but why is a dedicated syntax better than Tuple!( ...) ? See my link just below. If tuples are available in the core language just like that, people will feel much more comfortable using them in any situation. I've mentioned I'm working on a programming language myself. I haven't mentioned its name here, because I didn't think it'd be appropriate. But with your permission I can post a link to a page describing my tuples. Sure. http://code.google.com/p/mist/wiki/Tuples You can use static asserts to, at compile time, check the result of any computation, including function calls, that the compiler is able to execute at compile time. It sounds perfectly usable as unit tests to me, and in fact I do use static assert that way. Can you allocate stuff on the heap? If not, you can't do proper unit testing at compile-time. Perhaps I should have said that the unit-tests should be run automatically just after compilation and they should not be part of the program executable. They don't actually need to run 'at compile-time'. Yes, but 'pretty clear' does not a spec make. I refer you to our earlier divide/modulo discussion. We're going to fix the modulo thing. But the C++ standard leaves it implementation defined. How is that better? It's not. And you understand that the modulo thing is only a symptom, right? I've found another mistake by accident just today. See the issue report I filed. Sure, the D spec has gaps in it. But the C++ standard also has large gaps of uselessness in it. I agree. But at least you can count on C++ to do as specified. Where it doesn't give any guarantees, it specifies that also. With D it's mostly guesswork and experimentation. -- Michiel Helvensteijn
Re: Reddit: why aren't people using D?
Lutger wrote: There have been a lot of discussions on this topic in the past but I can't recall any conclusions. Perhaps some brave soul would dare to write a DIP on properties? Property DIPs have been offered in the newsgroup in the past, only before they were called DIPs. I also offered a possible design: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.Darticle_id=81759 Feel free to modify and/or DIPify it. -- Michiel Helvensteijn
Re: Reddit: why aren't people using D?
Bill Baxter wrote: I've always thought properties should work somewhat like this: property int length { get() { return this.len; } set(newLen) { this.len = newLen; } } I'm curious. Is it just a coincidence that how you've always thought happens to look a lot like C# properties? Or did you mean to say Ever since I saw how C# does properties I've thought? Nope. Never used C#, never seen it. I just think about language design a lot, and this is what I came up with. From that newsgroup thread, it seems that they are still quite different from C# properties. In any event I think a problem with this is that for D's simple grammar to remain simple and context free, get and set would both have to be made keywords in the language. I don't think so. They can just be identifiers with special meaning. If you look a bit further down the thread, I suggest adding the 'auto' keyword where the missing types are now. Perhaps that helps. In fact, in the design of my own language, those names have special meaning for all types: get(x) (or x.get()) returns x itself. set(x, v) (or x.get(v)) assigns v to x. If you specify them in a property, you're just overriding their meaning for the underlying type of the property, just like you can override other member-functions. Another upside is that you can always count on these functions existing for every type and you can pass them around as functions/delegates. -- Michiel Helvensteijn
Re: Reddit: why aren't people using D?
Michiel Helvensteijn wrote: set(x, v) (or x.get(v)) assigns v to x. Small correction: x.set(v) -- Michiel Helvensteijn
Re: Reddit: why aren't people using D?
Eldar Insafutdinov wrote: from your post: property int length { get() { return this.len; } set(newLen) { this.len = newLen; } void opIncrement() { this.len++; } } I don't think that's flexible to overload every operator to get the best performance. As Walter likes to say the best way should be the most obvious. Besides we forgot that D2 allows to return references, which eliminates the issue. If your property really just hides a private member variable, it was probably for encapsulation purposes or because you want redundant actions to be taken for every access. If you return a reference, you give unlimited and unrestricted access to that variable with only one call, and you might as well not have used a property at all. If your property is derived -- that is, if it doesn't directly mirror a variable --, there is no reference to return. Besides, in D, you can probably use mixins to copy the entire interface of a type into the property without code duplication. -- Michiel Helvensteijn
Re: Comma expressions must die [Was: Reddit: why aren't people using D?]
Adam D. Ruppe wrote: It might be my years of C bias, but the naked tuples just look wrong. There are ways -- elegant ways, I believe -- to make it work. Would you look at this page and give me your opinion? http://code.google.com/p/mist/wiki/Tuples I'm not sure if it can ever work for D, to be honest. There may be too many differences between the two languages. -- Michiel Helvensteijn
Re: Comma expressions must die [Was: Reddit: why aren't people using D?]
Adam D. Ruppe wrote: By keeping the tuple word there, it is no longer conflicting with my C expectations, but seems to be just as useful as your proposal. Hm. Then I believe you haven't read the whole thing. (That's ok, it does go on for a while.) Yes, much of the appeal is in the shorter syntax. But some of the features proposed even require that no 'tuple' keyword is used. Looking like C is not the be-all and end-all of programming languages. Mist tries to follow mathematical notation wherever possible. This has had other implications, like using - for assignment and = for equality. -- Michiel Helvensteijn
Re: (Non) Nesting block comments
yigal chripun wrote: IMHO, this is an ugly trick. it's less readable IMO and it just saves a cuple keystrokes. readability is more important than that. more over, this is completely unneeded (unless you program in notepad) since even the simplest of the (programmer) text editors has a shortcut to comment/uncomment a block of code. For instance, in Eclipse it's Ctrl+Shift+/ The point is not the amount of keystrokes. The point is that such a construction is automatic documentation of the fact that either the one or the other piece of code should be activated by the programmer (probably for debugging). Of course, you can pretty it up a little: //*/// A /* B //*/// But if you make this a convention in a project, every programmer will immediately understand. The fact that it takes only one keystroke to make the change is what gives the constructions its affordance. -- Michiel Helvensteijn
Re: Reddit: why aren't people using D?
Here's the opinion of an 'outsider'. I've experimented a bit with D in the past (years ago), but have lately just followed the newsgroup out of general interest. I respect the expertise and hard work of the D team, but I won't use D. And here's an incomplete list of my reasons. I imagine there are other programmers who share my views. Most of these issues, if not all, are well known here. But I'll mention them anyway. Please forgive (and correct) any factual mistakes. I'm sure there will be some. If you reply to any point in the list, I'll be glad to elaborate. D offers too many ways to do the same thing: * const, enum, immutable, invariant * structs, classes * functions, delegates, lazy parameter evaluation * garbage collection, manual D memory management, manual C memory management Even with so many ways to ensure const correctness, it is still possible to cast constness away, either making it impossible for the compiler to make any assumptions regarding constness, or making it very dangerous to do the cast. D offers some cool features, but leaves them very underpowered: * Contract programming (no contract inheritance, no compile-time static analysis, no loop invariants / ranking functions) * Class/Struct properties (no control over their use by class designer, no way to use +=, -=, no global properties, no parameterized properties) * Operator overloading (no fine control over comparison operators, fixed commutativity, confusing rule priority to determine translation, no overloading of !, , ||, =) * Tuples (no dedicated syntax, no parallel assignment, no non-flattening tuples without workarounds, no returning tuples) * Unit testing (not at compile time, not possible to categorize) There are two competing standard libraries for D. This has been discussed to death and I won't go further into it. But it's a bad thing. I maintain that D suffers greatly from its lack of a formal specification. It is silly for a language as old and relatively popular as D to use a compiler written by a small group of people (1 person?) as the official reference to the language. Not only does the D specification feel really unstable, it has a very low bus-factor. In other words: if, hypothetically, Walter were hit by a bus, would the D language survive? D just doesn't offer enough improvements over C++ to make it worthwhile switching over. Its design is not very adventurous, keeping simply too close to that of the C family, making it look like Yet Another C Language. I believe simply filling in the gaps of C++ wasn't enough to take over the world. There should have been a greater change. -- Michiel Helvensteijn
Re: (Non) Nesting block comments
Robert Jacques wrote: Well /* */ are excellent for toggling code sections. I tend to use constructs such as // */ or //* or /*/ which allows me to turn on of off blocks with often a single key stroke. Using /+ +/ means I have to Add /++/ and remove /++/ each time I want to activate or deactivate a code block. Why? I believe that /++/ works exactly like /**/ in that regard. Doesn't it? //+ code that can be turned off by removing the first / //+/ -- Michiel Helvensteijn
Re: (Non) Nesting block comments
Michel Fortin wrote: /* A /*/ B /**/ With this, you compile B while A is in a comment. Add / at the start of the first line and you compile code A while B is now in commented out. Aha. Interesting construction. I like it. No, you couldn't do that with nesting comments. I do wonder how often it comes up. -- Michiel Helvensteijn
Re: Casts and conversions done right
Lars T. Kyllingstad wrote: int i = to!int(pi);// The to function already exists in std.conv But what does the to function do, exactly? I'd prefer to use one of floor, round or ceil. Wouldn't you? I'm sure they are available as well. -- Michiel Helvensteijn
(Non) Nesting block comments
D has the old C style block comments that start with /* and end with the first possible */. But it also has nesting block comments, starting with /+ and ending with the *matching* +/. The nesting block comments were a great idea, since they can be used to 'comment out' any block of code, even if other block comments are already present. I was wondering, though. C++ compatibility aside, is there an actual use case for the C style block comments anymore? Has anyone here written some code lately where they thought: I really need a comment here containing /+ or +/ without the matching delimiter! Thank deity for C style comments! (Yes, this is bikeshed stuff, and I don't really care. I like programming language syntax discussions. Sometimes they are low barrier discussions.) -- Michiel Helvensteijn
Re: (Non) Nesting block comments
bearophile wrote: I was wondering, though. C++ compatibility aside, is there an actual use case for the C style block comments anymore? C compatibility is an important goal of D, so you can't put it aside. Of course. It was mostly theoretical. It may be generally interesting. (Time ago I have suggested the opposite, to make the /* */ nestable and remove /+ +/, but this idea was not appreciated by D devs.) I can understand that. It would break compatibility: /* /* */ (here be code in C, comment in D) -- Michiel Helvensteijn
Re: Random Suggestion: Swap Operator =?
Simen Kjaeraas wrote: I have a swap operator in my new programming language: x - y; It's syntactically consistent with the assignment operator: x - E; Clearly, this should be generalized to allow both right-to-left and left-to-right assignment. :p I thought about that. Of course it has a certain symmetry. But having two different syntaxes for standard assignment isn't right. And right-to-left has its advantages. You can see at a glance which variable is going to change value. -- Michiel Helvensteijn
Re: Random Suggestion: Swap Operator =?
Julian Salazar wrote: I'm wondering, who here would use a swap operator if it were available? I have a swap operator in my new programming language: x - y; It's syntactically consistent with the assignment operator: x - E; The swap operator is really syntactic sugar for the swap function, which can be overloaded and templated to your hearts desire (as long as each template type can be automatically deduced by the actual parameters). So yeah, I'd use it. -- Michiel Helvensteijn
Re: Random Suggestion: Swap Operator =?
Leandro Lucarella wrote: A more general solution is supporting tuples in the language, then you can do something like: a, b = b, a; That's a great feature. But even if it's available, I'd use swap, because: * I wouldn't have to mention each variable twice * It would use move-operations rather than copy operations Parallel assignment is still useful for other stuff, like traversing the fibonachi sequence with two variables :-) (a, b) - (b, a + b); -- Michiel Helvensteijn
Re: cast(public)
dsimcha wrote: Could we put a feature in the language that allows private member variables to be cast to public? The idea is that, if a class/struct designer makes something private, they're saying it's a bad idea to mess with it, and that you do so at your own risk. However, I think there needs to be a back door to cowboy this one In general don't believe this is a good idea. Calling private functions and accessing private variables may violate the class invariant. That's why it should only be done by member functions, which are bound to maintain that invariant. If there was such a back door, a class invariant would mean nothing. Neither the compiler nor the programmer could ever depend upon it. However, since D is a systems programming language, which can already cast away constness and such, it might fit. -- Michiel Helvensteijn
Re: modulus redux
Andrei Alexandrescu wrote: The multiplicative expressions are multiplication (\ccbox{a * b}), division (\ccbox{a / b}), and remainder (\ccbox{a \% b}). They operate on numeric types only. The result type of either of these operations is same as the type of \ccbox{true ? a : b} (see~\S~\ref{sec:conditional-operator}). either of means one of two or both of two. You're talking about three operations, so I'd leave out either of. Also, while the (true ? a : b) thing may be true, is this really the clearest way to explain? Perhaps you should define a term to mean common type of two operands and use that to explain both typeof(a mulop b) and typeof(true ? a : b). ... If such a number cannot be found, \ccbox{a \% b} yields the Not A Number (NaN) special value. When is this? If b == 0? If b == NaN? Perhaps it would be better to be precise. -- Michiel Helvensteijn
Re: Oh Dear
Walter Bright wrote: I agree with you that it should be better. I just don't agree with it being a showstopper. You know that the D Wikipedia article states: The official compiler by Walter Bright defines the language itself.? In other words, every bug in DMD is really a feature of the language. Until you fix it. That kind of permanent instability may be part of the reason people have been so negative around here lately. I invite you to contribute spec corrections to the examples you pointed out. I will file those corrections. However, the MulExpression thing was only an example. The first one I checked, too. The mentality behind compiler first, specification later just seems wrong to me. And that's not something I can report to bugzilla (or can I). By the way, what kind of integer division *does* D use? -- Michiel Helvensteijn
Re: Oh Dear
Walter Bright wrote: In other words, every bug in DMD is really a feature of the language. Until you fix it. That kind of permanent instability may be part of the reason people have been so negative around here lately. I don't agree with that characterization. Bugs get reported to bugzilla, and get fixed in a regular cycle. Sure they do. But if it's really true that the DMD implementation *is* the D language specification, any bug in DMD would also be part of that specification. And as the compiler changes, so does the spec. It's the danger of that approach. I will file those corrections. Thank you, I look forward to it. Issue 3165, Issue 3166. By the way, what kind of integer division *does* D use? To be frank, it is what the x86 DIV instruction does. After a quick Google search, it would seem DIV is the x86 unsigned divide instruction. Are you sure you aren't using IDIV (signed divide) for negative operands? If not, you'd actually be interpreting 2's complement signed ints as unsigned ints. (And surely such a thing would have been noticed before now?) But I agree that the modulus should be defined, regardless of whether that makes it less efficient on some machines. Good. Make sure that your divide operation and your modulo operation are consistent. The following identity should hold: if a / n = q and a % n = r a = q*n + r -- Michiel Helvensteijn
Re: Oh Dear
Rainer Deyke wrote: Actually I suspect that integer division with negative values is rare enough that a problem might escape notice for some time. Yep. It's possible. I suggest someone tests this. I don't have a D compiler installed, and I don't really have time for this. floor division, which is 99% of the time the type of division I want. Agreed. I'm using floored division in my new programming language. The quotient rounds towards negative infinity and the result of the mod operation has the same sign as the divisor. However, it seems D prides itself on its speed. And since truncated division is implemented by the hardware, D will probably use that. And that's acceptable, as long as it's guaranteed (predictable). -- Michiel Helvensteijn
Re: Oh Dear
Walter Bright wrote: I don't have a D compiler installed, and I don't really have time for this. Thanks to Ary, there's now a one click installer for Windows: http://ftp.digitalmars.com/dinstaller.exe That's nice. But I run Linux. Walter, surely this test shouldn't take more than a minute for you (or anyone else with a D compiler installed). Just see what DMD outputs for: 8 / 3 8 / (-3) (-8) / 3 (-8) / (-3) 8 % 3 8 % (-3) (-8) % 3 (-8) % (-3) If D uses DIV instead if IDIV, this should be immediately visible. In any case, we will see exactly what kind of division and modulo D uses. You can compare with the table on the bottom of page 3 of: http://www.cs.uu.nl/~daan/download/papers/divmodnote.pdf That's an informative article, by the way. -- Michiel Helvensteijn
Re: Oh Dear
Michiel Helvensteijn wrote: Walter, surely this test shouldn't take more than a minute for you (or anyone else with a D compiler installed). Ok, ok. I'll do it. Here's the results: -- import std.stdio; int main() { writefln(8/3); writefln(8/(-3)); writefln((-8)/3); writefln((-8)/(-3)); writefln(8%3); writefln(8%(-3)); writefln((-8)%3); writefln((-8)%(-3)); return 0; } -- outputs the following -- 2 -2 -2 2 2 2 -2 -2 -- So DMD uses truncated division. The quotient rounds towards zero and the remainder has the same sign as the dividend. I've updated issue 3165 with this information. Hope that helps. -- Michiel Helvensteijn
Re: Oh Dear
Andrei Alexandrescu wrote: Thanks, Michiel. Here's what I have in TDPL. Is it 100% in sync with you? === ... i...@b@ is zero in \ccbox{a / b} or \ccbox{a \% b}, a hardware exception is thrown. The sign\footnote{Sign, not signedness, i.e.,~the sign of the actual value.} of \ccbox{a \% b} is always the same as the sign o...@a@. That is, \ccbox{a \% b} is the closest number to zero of the same sign ...@a@ Now that I read it again (the last words there), this is not completely accurate. I know I made the same mistake myself just now, but the remainder has not necessarily the same sign as 'a', since it may be zero, which is signless. Of course, such a triviality won't hinder anyone's understanding, but you may as well be accurate, no? Some thing like same sign a...@a@ (or zero), perhaps? (Also note the word 'as' instead of 'of', which is not strictly grammatically correct.) that must be added t...@a@ to make it divisible b...@b@. For example, \ccbox{-5 \% 2} and \ccbox{-5 \% -2} both yield~\cc{-1}. The rest of the information is accurate, but you still neglect to mention the type of division. D uses truncated division. The quotient rounds towards zero. In other words, it cuts off the fractional part of the result. Good luck with your book. -- Michiel Helvensteijn
Re: Oh Dear
Andrei Alexandrescu wrote: \dee\ also defines modulus for floating-point numbers in the same way as the IEEE~754 standard. When at least one of @a@ and @b@ is a floating-point value in \cc{a \% b}, the result is the floating-point number @r@ satisfying the relation \cc{a = b * n + r}, where @n@ is an integer\footnote{``integer'' in the mathematical sense here} and @r@ is a positive number less than @b@'s absolute value. Oh, about this part. I left it out because it's not about integer division, but while I'm at it anyway. I believe you wanted the word non-negative there, instead of positive. However, I just ran the following test: writefln(5.0%2.0); writefln(5.0%(-2.0)); writefln((-5.0)%2.0); writefln((-5.0)%(-2.0)); it outputs: -- 1 1 -1 -1 -- So the remainder can still become negative, it seems. Same as with integer modulo. I would expect this consistency, but your paragraph there says something different. -- Michiel Helvensteijn
Re: Oh Dear
Walter Bright wrote: I'd like to emphasize that the code generator has been in use for 25 years for several hundred thousand users, and it is incredibly unlikely that nobody would notice if it is getting basic integer arithmetic wrong. I didn't think the compiler would be wrong. I was just replying to your statement that D does what x86 DIV does (you didn't mention IDIV; hence my initial confusion). If you'd like to write up a formal definition that can be inserted into the D specification, that would be great. I've given an unambiguous description of D division and modulus in another subthread here. I've also updated issue 3165 with the information. You can use that. -- Michiel Helvensteijn
Re: Oh Dear
Michiel Helvensteijn wrote: What does chopped to fit the integral type mean? What if it's a multiplication between two differently sized integral types? I'm sorry. I missed the first sentence of that section, which explains this part of it nicely: -- They undergo integral promotions, and then are brought to a common type using the usual arithmetic conversions. -- But the rest of my example stands. -- Michiel Helvensteijn