www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Reddit: why aren't people using D?

reply Walter Bright <newshound1 digitalmars.com> writes:
http://www.reddit.com/r/programming/comments/93jh5/ask_proggit_the_d_programming_language_looks/
Jul 22 2009
next sibling parent reply Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
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
Jul 22 2009
next sibling parent Ary Borenszweig <ary esperanto.org.ar> writes:
Michiel Helvensteijn escribiů:
 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

Agree.
 * structs, classes

Don't agree. It's nice to have this distinction when you care about performance. I just removed a class from a Java project and replaced it with a pair of parameters because too many instances of it were created. If I had structs in Java I woudln't have that problem. C# also has them and it's ok.
 * functions, delegates, lazy parameter evaluation
 * garbage collection, manual D memory management, manual C memory management

It's ok if you want to have finer control over the memory. Not everything is high-level.
 
 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:
 
 1. Contract programming (no contract inheritance, no compile-time static
 analysis, no loop invariants / ranking functions)
 2. Class/Struct properties (no control over their use by class designer, no
 way to use +=, -=, no global properties, no parameterized properties)
 3. Operator overloading (no fine control over comparison operators, fixed
 commutativity, confusing rule priority to determine translation, no
 overloading of !, &&, ||, <>=)
 4. Tuples (no dedicated syntax, no parallel assignment, no non-flattening
 tuples without workarounds, no returning tuples)
 5. Unit testing (not at compile time, not possible to categorize)
 
 6. 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.

It's amazing how many times 2, 5 and 6 were mentioned in this newsgroup. However nothing is done in this respect (maybe for 6 yes, but I think phobos should just dissapear).
 
 I maintain that D suffers greatly from its lack of a formal specification.

For me, it's not the lack of a formal specification, but it's hard to find how something works. Navigating the site is a PITA.
 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.
 

Jul 22 2009
prev sibling next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Michiel Helvensteijn wrote:
 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.

Thanks for taking the time to let us know your thoughts.
 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.

Ok.
 D offers too many ways to do the same thing:
 
 * const, enum, immutable, invariant

invariant is deprecated and completely replaced by immutable. So now we're down to three <g>. The uses are: immutable - data that cannot change or be changed (imagine it is stored in ROM) const - read only view of data, you cannot change it but others can enum - compile time constant, has no storage The only place these overlap is in the declaration of symbolic constants. C++ has all three, but in a way that is context dependent that very few people are aware of.
 * structs, classes

structs are value types, classes are reference types. That's a fundamental distinction, not two ways to do the same thing. A lot of confusing problems with C++ code stem from attempting to use a struct (or class!) both ways, or trying to give it characteristics of both.
 * functions, delegates, lazy parameter evaluation

Lazy parameter evaluation may turn out to be a bad idea, it doesn't seem to have found its "groove" anywhere. On the other hand, you can just ignore them like everyone else does, like everyone ignores exception specifications in C++. There's some undeniable extra complexity in having both function pointers and delegates. At some level, function pointers must be supported in order to support the C interface. Delegates are just too useful to give up (C++ has had awful problems trying to work around not having them - member function pointers anyone? Boost::bind? no thanks). It is technically possible to wrap delegates with a thunk so they are interchangeable with function pointers, but this thunk has to be created at runtime. It'll have a corresponding performance and memory consumption penalty. It's hard to know if it's an acceptable cost or not.
 * garbage collection,

Many programming paradigms are not practical without gc.
 manual D memory management,

It's possible to do this, but rather pointless. It's only there for people who insist they need it.
 manual C memory management

Necessary to support the C ABI. But D actually does not have C memory management - to do C memory management, you call the C functions malloc/free. Those are not reimplemented in D. D programs have complete access to C runtime libraries, and naturally this includes any C memory management functions.
 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.

Being a systems programming language, it must be possible to defeat the static type checking system for special cases. Yes, you can cast away constness, but (unlike in C++), if you use that power to change the value, you are in undefined territory. The compiler is allowed to assume that const-ness is respected. In C++, it is legal and defined behavior to cast away const (unless it is a top level const) *and* change the value. This makes const completely useless as a hint to the code generator.
 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)

True, but compile-time static analysis is a "quality of implementation" issue. Furthermore, I know of no language other than Eiffel that has all this, and nobody uses Eiffel.
 * Class/Struct properties (no control over their use by class designer, no
 way to use +=, -=, no global properties, no parameterized properties)

I don't understand what this means.
 * Operator overloading (no fine control over comparison operators,
 fixed commutativity,

This is deliberate. Operator overloading should be restricted to implementing arithmetic like operations on objects, not completely different things like what iostreams, Spirit and Boost::regex do.
 confusing rule priority to determine translation,

The alternative is "Koenig lookup", which I guarantee is far more confusing and has many weird problems.
 no overloading of !, &&, ||,

That's deliberate. For !, I wish to maintain the property of negation of the boolean result, as much of the semantics of transformation depend on it. For && and ||, they are "short circuit" operators, and how that would sensibly interact with operator overloading I have no idea. I know of no language that allows overloading && and ||.
  <>=)

I need to fix that.
 * 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.
 * Unit testing (not at compile time,

You can do testing at compile time with static asserts.
 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. 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.
 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.

There is one standard library, Phobos, and an alternative, Tango.
 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.
 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.

This is not true anymore. Several people are contributing substantial upgrades to it. I review everything before they get folded into the source tree, of course, but the quality of the submissions has been improving by leaps and bounds.
 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 how it's supposed to work, there's a reference implementation to resolve disputes, and weaknesses in the spec get fixed. D2 is a work in progress, and so the spec for it is, too.
 it has a very low bus-factor. In other words: if, hypothetically,
 Walter were hit by a bus, would the D language survive?

With the full release of the source code, and the growth of fully-capable third party D compilers, yes it will survive. I couldn't wreck the language if I tried <g>.
 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.

In my experience, D code is about 30% less source code than the equivalent C++. That's a third off of development time, not including the debugging time saved. That's a very big deal. Many valuable improvements of D, such as memory safety guarantees, protections against function hijacking, etc., are surely "yeah, yeah, so what" unless one has managed large projects and been submarined by these problems. 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.
Jul 22 2009
next sibling parent Trass3r <mrmocool gmx.de> writes:
Jarrett Billingsley schrieb:
 On Wed, Jul 22, 2009 at 6:30 PM, Walter
 Bright<newshound1 digitalmars.com> wrote:
 
 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.

This is EXACTLY the point I always try to make to newcomers. It's so significant that I think it should be on the front page of the language spec, in bold, 72 point, red letters.

Seconded. Even though the road is paved with obstacles I can't imagine going back to C++ or any other language. By obstacles I mean among others: - D1<->D2 and Phobos<->Tango problem - esp. when creating a library that shall be compilable with any combination the end user wants you have to use a lot of versions and aliases to accommodate that, like it is done in DFL. - dozens of more or less abandoned projects that aren't usable with latest compilers anymore, - furthermore many users tend to maintaining their own fork rather than contributing to the project, thus useful functionality is often spread and sometimes even unknown cause the fork isn't publicly available - lack of IDEs, Descent is pretty good (and the only one regularly updated), but still has a long way to go. It's only reasonably usable with dsss, but rebuild is horribly outdated and always gets trapped in an infinite loop when using D2 and sometimes also refuses to work with D1. xf.build is still in the early stages and using the compiler directly is out of question. The newly added -deps parameter is probably a step forward, but wouldn't it be possible to simply include that rebuild functionality in dmd? I mean if it is possible to scan the dependencies and write them to a file, it shouldn't be that hard to simply add those found modules to the "working queue", should it? Build tools could then concentrate on the stuff dsss actually does like project management, installing and so on (which it does in a brilliant way imho, I really like the dsss.conf style)
Jul 22 2009
prev sibling next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Bill Baxter wrote:
 Yeh, it's like what's the big diff between a Lamborghini and a Chevy
 Nova anyway?  They both have four tires.  They both run on gas.  So
 what's all the fuss about the Lamborghini?

It's like a car from the 60's vs a car today. It's hard to see what's really different, until you spend time driving one. There's just a boatload of little improvements in everything that add up to a lot. It's no surprise that most people who fix up those old cars also upgrade the systems with modern technology.
Jul 22 2009
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Walter Bright wrote:
 Bill Baxter wrote:
 Yeh, it's like what's the big diff between a Lamborghini and a Chevy
 Nova anyway?  They both have four tires.  They both run on gas.  So
 what's all the fuss about the Lamborghini?

It's like a car from the 60's vs a car today.

Or like driving an American car vs. a Japanese or European car. Andrei
Jul 22 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Jarrett Billingsley wrote:
 On Wed, Jul 22, 2009 at 10:00 PM, Andrei
 Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:
 Or like driving an American car vs. a Japanese or European car.

Yeah, what *is* the deal with that? In terms of little convenience features, American cars feel outright primitive compared to Japanese and European cars.. Sorry for the OT :P

Would you believe there is a guy in this newsgroup who'd manage to keep a straight face while saying that Ford is better designed than Mercedes? Andrei
Jul 22 2009
prev sibling parent Walter Bright <newshound1 digitalmars.com> writes:
Walter Bright wrote:
 It's no surprise that most people who fix up those old cars also upgrade 
 the systems with modern technology.

I was just over in one of the restoration forums, where they're talking about a company that makes exact reproductions of original wiring harnesses. Turns out they aren't exact reproductions, they're using much higher quality wire that is more resistant to heat.
Jul 23 2009
prev sibling next sibling parent Walter Bright <newshound1 digitalmars.com> writes:
Bill Baxter wrote:
 Even that does have a cumulative effect, though.  If you keep hearing
 "take my word for it" from different sources, eventually, if you have
 any curiousity at all, you'll want to check it out for yourself.

Right. Just keep making comments about D in public forums in appropriate contexts. It works. I give presentations on D frequently. I always start with: 1. Who has heard of D? 2. Who has written programs in D? Over time, the hands raised on (1) have gone from a few to essentially 100%. (2) is rising steadily.
Jul 22 2009
prev sibling parent reply Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
Walter Bright wrote:

 immutable - data that cannot change or be changed (imagine it is stored
 in ROM)
 
 const - read only view of data, you cannot change it but others can
 
 enum - compile time constant, has no storage
 
 The only place these overlap is in the declaration of symbolic
 constants. C++ has all three, but in a way that is context dependent
 that very few people are aware of.

Aren't immutable and enum the same thing? At least to the programmer?
 * structs, classes

structs are value types, classes are reference types. That's a fundamental distinction, not two ways to do the same thing. A lot of confusing problems with C++ code stem from attempting to use a struct (or class!) both ways, or trying to give it characteristics of both.

But in C++ you can put a class object on the stack with value semantics, just as you can put a struct object on the heap. No problem, really. Stack is default. For the heap, all you need is a pointer. Personally I hate Java style reference semantics (a.k.a. heap without pointers). Especially because they also offer a small set of value types, to confuse matters. Now here's D doing the same thing. 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.
 * functions, delegates, lazy parameter evaluation

Lazy parameter evaluation may turn out to be a bad idea, it doesn't seem to have found its "groove" anywhere. On the other hand, you can just ignore them like everyone else does, like everyone ignores exception specifications in C++.

Actually, lazy parameter evaluation has its purpose. I personally like languages in which there are little or no "special constructs" that only the compiler can provide. In this case, lazy parameter eval could be used to overload your own short-circuiting operator.
 There's some undeniable extra complexity in having both function
 pointers and delegates. At some level, function pointers must be
 supported in order to support the C interface. Delegates are just too
 useful to give up (C++ has had awful problems trying to work around not
 having them - member function pointers anyone? Boost::bind? no thanks).

I understand why you keep delegates around. I'd just call them function variables and remove the C(++) cruft. But D's goal is to keep some sort of backwards compatibility, so ok.
 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)

True, but compile-time static analysis is a "quality of implementation" issue.

Only when you're talking about optimization. There is great value in automatic proof of correctness. But I know this is a tall order.
 Furthermore, I know of no language other than Eiffel that has all 
 this, and nobody uses Eiffel.

That's a spurious argument. The reason people don't use Eiffel is not its advanced contract programming features. (It may be the syntax.) Plus, you ignored the other points. Contract inheritance, 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)

I don't understand what this means.

Properties. Your syntactic sugar: int i = c.p; // int i = c.p() p = i // c.p(i) They can't do these things: * No control over their use by class designer: ANY member function with one or zero parameters may be called using 'property syntax'. This is not a good thing. * No way to use +=, -=: I hope this one is clear. The operators that require both read and write access won't work on properties. * No global properties: If I'm not mistaken, global functions can't be properties. * No parameterized properties: c.f(5) = 6; // c.f(5, 6)
 * Operator overloading (no fine control over comparison operators,

This is deliberate. Operator overloading should be restricted to implementing arithmetic like operations on objects, not completely different things like what iostreams, Spirit and Boost::regex do.

Arithmetic like operations like matrix multiplication (which is not commutative)?
 confusing rule priority to determine translation,

The alternative is "Koenig lookup", which I guarantee is far more confusing and has many weird problems.

Perhaps you misunderstand. I was referring to the algorithm that first checks for a complete match, then tries the 'reverse overload', then tries the commutative call.
 no overloading of !, &&, ||,

That's deliberate. For !, I wish to maintain the property of negation of the boolean result, as much of the semantics of transformation depend on it.

I can perhaps understand this one. Though I'm sure there are programmers that'd rather have the ability to overload it.
 For && and ||, they are "short circuit" operators, and how that 
 would 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
Jul 23 2009
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Michiel Helvensteijn wrote:
 Walter Bright wrote:
 
 immutable - data that cannot change or be changed (imagine it is stored
 in ROM)

 const - read only view of data, you cannot change it but others can

 enum - compile time constant, has no storage

 The only place these overlap is in the declaration of symbolic
 constants. C++ has all three, but in a way that is context dependent
 that very few people are aware of.

Aren't immutable and enum the same thing? At least to the programmer?

Well you can build an immutable list.
 * structs, classes

fundamental distinction, not two ways to do the same thing. A lot of confusing problems with C++ code stem from attempting to use a struct (or class!) both ways, or trying to give it characteristics of both.

But in C++ you can put a class object on the stack with value semantics, just as you can put a struct object on the heap. No problem, really. Stack is default. For the heap, all you need is a pointer. Personally I hate Java style reference semantics (a.k.a. heap without pointers). Especially because they also offer a small set of value types, to confuse matters. Now here's D doing the same thing. 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. There's only one place when anyone would seriously want something to be a value and a reference simultaneously, and that's exception classes. And those are tricky. I've never seen any correctly designed exception hierarchy in C++, starting with the standard exceptions. The fact that D requires one more allocation to throw an exception is IMHO a very small compromise. Andrei
Jul 23 2009
parent reply Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
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
Jul 23 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Michiel Helvensteijn wrote:
 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.

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.

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. MEC++ discusses the problem of defining constructors and particularly copy constructors in hierarchies. Assignment and comparison are also problematic. Andrei
Jul 23 2009
next sibling parent Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
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
Jul 23 2009
prev sibling parent reply Rainer Deyke <rainerd eldwood.com> writes:
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. MEC++ discusses the problem of defining constructors and
 particularly copy constructors in hierarchies. Assignment and comparison
 are also problematic.

Yes, C++ has problems, but these problems can be fixed! The struct/class split, on the other hand, introduces many more problems that are harder to fix. -- Rainer Deyke - rainerd eldwood.com
Jul 23 2009
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Rainer Deyke wrote:
 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. MEC++ discusses the problem of defining constructors and
 particularly copy constructors in hierarchies. Assignment and comparison
 are also problematic.

Yes, C++ has problems, but these problems can be fixed!

How? Minding constantly a set of dangerous problems is not fixing it.
 The
 struct/class split, on the other hand, introduces many more problems
 that are harder to fix.

Again: what are those problems? Andrei
Jul 23 2009
parent reply Rainer Deyke <rainerd eldwood.com> writes:
Andrei Alexandrescu wrote:
 Rainer Deyke wrote:
 Yes, C++ has problems, but these problems can be fixed!

How? Minding constantly a set of dangerous problems is not fixing it.

Proposal 1: instances of polymorphic classes are stored on the heap but treated as value types. They are copied when the variable is copied (a full non-slicing copy), they are destroyed when the variable goes out of scope. In short, they are truly polymorphic value types, with some performance penalty. Proposal 2: Syntactically distinguish between polymorphic references (references to an instance of a class or any of its subclasses) and non-polymorphic references (references to an instance of a specific class and only that class), with the latter decaying to the former. Copy constructors would take a non-polymorphic reference as argument, thereby completely fixing the slicing problem.
 The
 struct/class split, on the other hand, introduces many more problems
 that are harder to fix.

Again: what are those problems?

Syntactic ambiguity. Confusion between an instance of a class and a reference to that instance. -- Rainer Deyke - rainerd eldwood.com
Jul 23 2009
parent reply Walter Bright <newshound1 digitalmars.com> writes:
Rainer Deyke wrote:
 The
 struct/class split, on the other hand, introduces many more problems
 that are harder to fix.


Syntactic ambiguity. Confusion between an instance of a class and a reference to that instance.

I was initially thrown by this when I started some Java programming. But it soon became clear this was an advantage, and I came to prefer it. So I think this is a case of one's perspective, not an actual problem.
Jul 23 2009
parent reply Rainer Deyke <rainerd eldwood.com> writes:
Walter Bright wrote:
 Rainer Deyke wrote:
 Syntactic ambiguity.  Confusion between an instance of a class and a
 reference to that instance.

I was initially thrown by this when I started some Java programming. But it soon became clear this was an advantage, and I came to prefer it.

I like it in Python, where all variables are references. Java is similar to Python in this regard, although the existence of primitive value types complicates the situation somewhat. I don't like it in D, where reference types and value types coexist. I especially don't like it in templates in D, where it may not be clear if you're dealing with a reference type or a value type until instantiation. -- Rainer Deyke - rainerd eldwood.com
Jul 23 2009
next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Rainer Deyke wrote:
 Walter Bright wrote:
 Rainer Deyke wrote:
 Syntactic ambiguity.  Confusion between an instance of a class and a
 reference to that instance.

it soon became clear this was an advantage, and I came to prefer it.

I like it in Python, where all variables are references. Java is similar to Python in this regard, although the existence of primitive value types complicates the situation somewhat. I don't like it in D, where reference types and value types coexist. I especially don't like it in templates in D, where it may not be clear if you're dealing with a reference type or a value type until instantiation.

Is C++ really better in that regard? Given a non-trivial struct or class declaration, I'd be hard pressed to determine if it was meant to be a value or reference type.
Jul 23 2009
parent reply Rainer Deyke <rainerd eldwood.com> writes:
Walter Bright wrote:
 Rainer Deyke wrote:
 I like it in Python, where all variables are references.  Java is
 similar to Python in this regard, although the existence of primitive
 value types complicates the situation somewhat.

 I don't like it in D, where reference types and value types coexist.  I
 especially don't like it in templates in D, where it may not be clear if
 you're dealing with a reference type or a value type until instantiation.

Is C++ really better in that regard? Given a non-trivial struct or class declaration, I'd be hard pressed to determine if it was meant to be a value or reference type.

Yes, it is. Mainly because C++ doesn't have reference types in same way that D does. In C++, values of *all* types (including primitive integral types and even pointer types) can be placed on the heap, and such values are *always* managed by (smart) pointers, with pointer syntax. In this sense, all types in C++ can be used as reference types. There are C++ classes that are meant to always be placed on the heap and managed by a pointer. They are the closest C++ has to D-style classes. They are exceedingly rare. They're also easy to identify: their constructors are protected, so the only way to instantiate them is by calling a factory function that returns a (smart) pointer. -- Rainer Deyke - rainerd eldwood.com
Jul 24 2009
parent Walter Bright <newshound1 digitalmars.com> writes:
Rainer Deyke wrote:
 Yes, it is.  Mainly because C++ doesn't have reference types in same way
 that D does.
 
 In C++, values of *all* types (including primitive integral types and
 even pointer types) can be placed on the heap, and such values are
 *always* managed by (smart) pointers, with pointer syntax.  In this
 sense, all types in C++ can be used as reference types.
 
 There are C++ classes that are meant to always be placed on the heap and
 managed by a pointer.  They are the closest C++ has to D-style classes.
  They are exceedingly rare.  They're also easy to identify: their
 constructors are protected, so the only way to instantiate them is by
 calling a factory function that returns a (smart) pointer.

A reference type isn't defined as one that only exists on the heap. Even in D, value types can be in the heap, and reference types can be on the stack. The value/reference dichotomy is how the object is referred to, not where it is.
Jul 24 2009
prev sibling parent reply Leandro Lucarella <llucax gmail.com> writes:
Rainer Deyke, el 23 de julio a las 19:49 me escribiste:
 Walter Bright wrote:
 Rainer Deyke wrote:
 Syntactic ambiguity.  Confusion between an instance of a class and a
 reference to that instance.

I was initially thrown by this when I started some Java programming. But it soon became clear this was an advantage, and I came to prefer it.

I like it in Python, where all variables are references. Java is similar to Python in this regard, although the existence of primitive value types complicates the situation somewhat. I don't like it in D, where reference types and value types coexist. I especially don't like it in templates in D, where it may not be clear if you're dealing with a reference type or a value type until instantiation.

!? It's true that in Python all are references, but there are inmutable objects in Python, like int, float, strings and tuples. From a practical POV it exactly the same as value types, if you do: def f(x, y): x = 5 y = (1, 3) a = 1 b = (5, 9) f(a, b) print a, b prints "1 (5, 9)", not "5 (1, 3)". So I can't see how you like Python's way and not D's way. -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- En la calle me cruc√© con un se√Īor muy correcto, que habitualmente anda en Falcon; iba corriendo con dos valijas en la mano y dijo: "Voy para Miami, tiene alg√ļn mensaje o ..." y le dije: "No, no, no..." -- Extra Tato (1983, Triunfo de Alfons√≠n)
Jul 24 2009
parent reply Rainer Deyke <rainerd eldwood.com> writes:
Leandro Lucarella wrote:
 !? It's true that in Python all are references, but there are inmutable
 objects in Python, like int, float, strings and tuples. From a practical
 POV it exactly the same as value types, if you do:

Immutable reference types are still reference types, and follow the same rules as other reference types. You just can't modify them. The assignment operator *always* rebinds a reference, regardless of the mutability or immutability of any objects involved. The one exception is that operators like '+=' will create a new object when applied to immutable types, but modify existing objects when applied to mutable objects. And, yes, this bothers me in Python. A lot. But that's still not half as bad as D, where something simple like 'a = b; a.x = 5;' can have two completely different meanings depending on whether 'a' is a reference type or a value type. -- Rainer Deyke - rainerd eldwood.com
Jul 24 2009
next sibling parent Walter Bright <newshound1 digitalmars.com> writes:
Rainer Deyke wrote:
 Leandro Lucarella wrote:
 !? It's true that in Python all are references, but there are inmutable
 objects in Python, like int, float, strings and tuples. From a practical
 POV it exactly the same as value types, if you do:

Immutable reference types are still reference types, and follow the same rules as other reference types. You just can't modify them. The assignment operator *always* rebinds a reference, regardless of the mutability or immutability of any objects involved.

From a user's point of view, an immutable reference is indistinguishable from a value.
 But that's still not half as bad as D, where something simple like 'a =
 b; a.x = 5;' can have two completely different meanings depending on
 whether 'a' is a reference type or a value type.

True. And in C++ with assignment overloads and copy constructors, one also has no clue what a.x=5 does without looking at the source to those functions. I don't think there's anyway we can pretend to know what semantics a type has in a language with user-definable types without at least looking at its declaration.
Jul 24 2009
prev sibling parent reply Leandro Lucarella <llucax gmail.com> writes:
Rainer Deyke, el 24 de julio a las 11:55 me escribiste:
 Leandro Lucarella wrote:
 !? It's true that in Python all are references, but there are inmutable
 objects in Python, like int, float, strings and tuples. From a practical
 POV it exactly the same as value types, if you do:

Immutable reference types are still reference types, and follow the same rules as other reference types. You just can't modify them. The assignment operator *always* rebinds a reference, regardless of the mutability or immutability of any objects involved.

That's true, conceptually, but when you use the variables, you use them as value types, with the same advantages and limitations.
 The one exception is that operators like '+=' will create a new object
 when applied to immutable types, but modify existing objects when
 applied to mutable objects.  And, yes, this bothers me in Python.  A lot.

How do you note that? Really. Python inmutables have value semantics.
 But that's still not half as bad as D, where something simple like 'a =
 b; a.x = 5;' can have two completely different meanings depending on
 whether 'a' is a reference type or a value type.

Yes, that's true, but this is a common problem. Think of operator overloading... Even in Python that could mean *anything* (__getattr__). -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- Y será el día en que la electricidad deje de ser rayo y sea depilador femenino. -- Ricardo Vaporeso
Jul 24 2009
parent Rainer Deyke <rainerd eldwood.com> writes:
Leandro Lucarella wrote:
 Yes, that's true, but this is a common problem. Think of operator
 overloading... Even in Python that could mean *anything* (__getattr__).

I want a programming language that enables me to write good code, not one that prevents me from writing bad code. Abusing operator overloading is bad code, and I try to avoid it. Using 'a = b; a.x = 5;' to mean two different things is also bad code, but it's not something I can avoid in D. -- Rainer Deyke - rainerd eldwood.com
Jul 24 2009
prev sibling next sibling parent Leandro Lucarella <llucax gmail.com> writes:
Jarrett Billingsley, el 23 de julio a las 14:06 me escribiste:
 On Thu, Jul 23, 2009 at 1:20 PM, Steven
 Schveighoffer<schveiguy yahoo.com> wrote:
 
 However, when I realized that with a custom allocator, I could tremendously
 increase performance, I had to switch to structs.

Um, did you? Because you can have custom allocators for classes too..

And that reason only seems to be a complain with the GC performance, not with the struct/class separation ;) -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- Que barbaridad, este país se va cada ves más pa' tras, más pa' tras... -- Sidharta Kiwi
Jul 23 2009
prev sibling parent reply Rainer Deyke <rainerd eldwood.com> writes:
Jarrett Billingsley wrote:
 Classes and structs are fundamentally different concepts.  You design
 your code from the start to use one or the other, because only one
 makes sense.

In my first (and to date only) D project, *all* my user-defined types started as structs, and *all* became classes when I found out that D1 structs don't support all of the features I need. (None of them used polymorphism. In C++, all would have been value types.) I expect the situation will be much better in D2. -- Rainer Deyke - rainerd eldwood.com
Jul 23 2009
parent Rainer Deyke <rainerd eldwood.com> writes:
Jarrett Billingsley wrote:
 On Thu, Jul 23, 2009 at 4:34 PM, Rainer Deyke<rainerd eldwood.com> wrote:
 In my first (and to date only) D project, *all* my user-defined types
 started as structs, and *all* became classes when I found out that D1
 structs don't support all of the features I need.  (None of them used
 polymorphism.  In C++, all would have been value types.)

And you don't think that has *anything* to do with trying to program C++ in D.

No, it was clearly a case of trying to program D2 in D1. In D2, all of these types should be structs. -- Rainer Deyke - rainerd eldwood.com
Jul 23 2009
prev sibling next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Michiel Helvensteijn wrote:
 Aren't immutable and enum the same thing? At least to the programmer?

Not at all. How would you declare a type that is "pointer to immutable int" using an enum? Anyhow, there was a looong thread about this a year back or so.
 * Contract programming (no contract inheritance, no compile-time static
 analysis, no loop invariants / ranking functions)

issue.

Only when you're talking about optimization. There is great value in automatic proof of correctness. But I know this is a tall order.
 Furthermore, I know of no language other than Eiffel that has all 
 this, and nobody uses Eiffel.

That's a spurious argument. The reason people don't use Eiffel is not its advanced contract programming features. (It may be the syntax.)

It may indeed be the syntax, but consider that no other language adopted those constructs. There was a proposal to add contracts to C++0x which died. I added them to Digital Mars C++ and nobody cared.
 Plus, you ignored the other points. Contract inheritance, loop invariants,
 ranking functions.

Contracts didn't hit paydirt, and so haven't gotten a lot of follow-on attention. Eiffel has contract inheritance, I think it has loop invariants, and I never heard of ranking functions.
 * Class/Struct properties (no control over their use by class designer,
 no way to use +=, -=, no global properties, no parameterized properties)


Properties. Your syntactic sugar: int i = c.p; // int i = c.p() p = i // c.p(i) They can't do these things: * No control over their use by class designer: ANY member function with one or zero parameters may be called using 'property syntax'. This is not a good thing.

Why not? Seriously, what is the semantic difference?
 * No way to use +=, -=: I hope this one is clear. The operators that require
 both read and write access won't work on properties.

Agreed that's a problem. Andrei has also been a strong advocate of fixing it.
 * No global properties: If I'm not mistaken, global functions can't be
 properties.

int foo() { return 3; } void main() { int x = foo; } works.
 * No parameterized properties: c.f(5) = 6; // c.f(5, 6)

Ok.
 * Operator overloading (no fine control over comparison operators,

This is deliberate. Operator overloading should be restricted to implementing arithmetic like operations on objects, not completely different things like what iostreams, Spirit and Boost::regex do.

Arithmetic like operations like matrix multiplication (which is not commutative)?

I believe this is completely controllable with D.
 confusing rule priority to determine translation,

confusing and has many weird problems.

Perhaps you misunderstand. I was referring to the algorithm that first checks for a complete match, then tries the 'reverse overload', then tries the commutative call.

I did understand it. The alternative is Koenig Lookup, and the reason for its existence. Reverse operator overloading is a bit awkward, but the awkwardness is restricted to the class in which it appears. ADL (Koenig Lookup) spreads awkwardness everywhere.
 no overloading of !, &&, ||,

the boolean result, as much of the semantics of transformation depend on it.

I can perhaps understand this one. Though I'm sure there are programmers that'd rather have the ability to overload it.

I'm sure there are, too. That doesn't mean it's a good idea! Features ought to have compelling use cases for them, not just it-would-be-nice-if.
 For && and ||, they are "short circuit" operators, and how that 
 would 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.

Oops, you're right. Here's an old thread about it: http://www.digitalmars.com/d/archives/digitalmars/D/18153.html I 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.
 * Tuples (no dedicated syntax, no parallel assignment, no non-flattening
 tuples without workarounds, no returning tuples)

library support.

You cannot get a dedicated syntax with library support.

Of course that's true, but why is a dedicated syntax better than Tuple!( ...) ?
 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.
 * Unit testing (not at compile time,


Not unit testing, surely.

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.
 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).

I replied more on unit testing in another response in this thread.
 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? And how about the C++ source character set and the behavior of "char"? It's a standardized specifying of a mess of implementation defined and undefined behavior. Sure, the D spec has gaps in it. But the C++ standard also has large gaps of uselessness in it.
Jul 23 2009
next sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
Walter Bright wrote:
 Michiel Helvensteijn wrote:
 Properties. Your syntactic sugar:

 int i = c.p; // int i = c.p()
 p = i // c.p(i)

 They can't do these things:

 * No control over their use by class designer: ANY member function 
 with one
 or zero parameters may be called using 'property syntax'. This is not a
 good thing.

Why not? Seriously, what is the semantic difference?

Semantic difference: a property doesn't have *visible* side effects. If you invoke it one hundred times, it should always return the same thing. And nothing else in your program should change. So it's kind of like pure functions. I say "visible" because you might want to implement a property lazily. But the logic remains inside your class and it's visible in the outside world.
Jul 23 2009
parent reply Walter Bright <newshound1 digitalmars.com> writes:
Ary Borenszweig wrote:
 Walter Bright wrote:
 Michiel Helvensteijn wrote:
 * No control over their use by class designer: ANY member function 
 with one
 or zero parameters may be called using 'property syntax'. This is not a
 good thing.

Why not? Seriously, what is the semantic difference?

Semantic difference: a property doesn't have *visible* side effects. If you invoke it one hundred times, it should always return the same thing. And nothing else in your program should change. So it's kind of like pure functions. I say "visible" because you might want to implement a property lazily. But the logic remains inside your class and it's visible in the outside world.

Ok, but not having visible side effects is just a convention, one which is apparently not enforced by languages with special property syntax. A pure function, however, can be statically guaranteed to have no side effects. So IDEs, etc., can regard as 'properties' any such methods which take no arguments.
Jul 23 2009
next sibling parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Walter Bright wrote:
 Ary Borenszweig wrote:
 Walter Bright wrote:
 Michiel Helvensteijn wrote:
 * No control over their use by class designer: ANY member function
 with one
 or zero parameters may be called using 'property syntax'. This is not a
 good thing.

Why not? Seriously, what is the semantic difference?

Semantic difference: a property doesn't have *visible* side effects. If you invoke it one hundred times, it should always return the same thing. And nothing else in your program should change. So it's kind of like pure functions. I say "visible" because you might want to implement a property lazily. But the logic remains inside your class and it's visible in the outside world.

Ok, but not having visible side effects is just a convention, one which is apparently not enforced by languages with special property syntax. A pure function, however, can be statically guaranteed to have no side effects. So IDEs, etc., can regard as 'properties' any such methods which take no arguments.

That's true, but you haven't addressed the other side of it: property setters. Let me give you an example of where I think a few people are trying to come from. In VB6, you could create custom ActiveX controls. In the code for it, you could declare properties with getters and setters. The nice thing was that because the IDE could tell the difference between functions and properties, it could display these properties automatically in the property sheet for each control. With D, you would need to explicitly state which methods are properties manually somehow; dunno how you would, though. Especially when you consider subclassing and mixins.
Jul 23 2009
next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Daniel Keep wrote:
 That's true, but you haven't addressed the other side of it: property
 setters.

Right. Consider the case where there's a pure function with no arguments, and an overload with the same name and one argument, and no other overloads. Wouldn't it be reasonable to take that as a property setter?
 With D, you would need to explicitly state which methods are properties
 manually somehow; dunno how you would, though.  Especially when you
 consider subclassing and mixins.

See my rule above - I think it'll work.
Jul 23 2009
next sibling parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Walter Bright wrote:
 Daniel Keep wrote:
 That's true, but you haven't addressed the other side of it: property
 setters.

Right. Consider the case where there's a pure function with no arguments, and an overload with the same name and one argument, and no other overloads. Wouldn't it be reasonable to take that as a property setter?
 With D, you would need to explicitly state which methods are properties
 manually somehow; dunno how you would, though.  Especially when you
 consider subclassing and mixins.

See my rule above - I think it'll work.

Actually, I've now come up with a counter-example for the idea of using pure at all: class Lazy(T) { private { T v; T delegate() dg; } this(T delegate() dg) { this.dg = dg; } T value() { if( dg !is null ) { v = dg(); dg = null; } return v; } } You can't make value pure, but it is supposed to be a property. One of the examples Nick gives in DIP4 is a property that accesses an SQL database; there's no way to make that pure!
Jul 24 2009
next sibling parent Ary Borenszweig <ary esperanto.org.ar> writes:
Daniel Keep escribió:
 
 Walter Bright wrote:
 Daniel Keep wrote:
 That's true, but you haven't addressed the other side of it: property
 setters.

arguments, and an overload with the same name and one argument, and no other overloads. Wouldn't it be reasonable to take that as a property setter?
 With D, you would need to explicitly state which methods are properties
 manually somehow; dunno how you would, though.  Especially when you
 consider subclassing and mixins.


Actually, I've now come up with a counter-example for the idea of using pure at all: class Lazy(T) { private { T v; T delegate() dg; } this(T delegate() dg) { this.dg = dg; } T value() { if( dg !is null ) { v = dg(); dg = null; } return v; } } You can't make value pure, but it is supposed to be a property. One of the examples Nick gives in DIP4 is a property that accesses an SQL database; there's no way to make that pure!

Exactly! That's why I said "kind of pure" (well, maybe I didn't say that :-P), but the idea is that properties don't modify anything visible from outside of the symbol they are contained in. But it's hard to define what that means...
Jul 24 2009
prev sibling next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Daniel Keep" <daniel.keep.lists gmail.com> wrote in message 
news:h4br9n$1rje$1 digitalmars.com...
 You can't make value pure, but it is supposed to be a property.  One of
 the examples Nick gives in DIP4 is a property that accesses an SQL
 database; there's no way to make that pure!

Speaking of that, has my top-level post about that (Subject: "DIP4: Properties") shown up for anyone? I first posted it about 12:30am (my time, 4.5 hours ago), than again between 1 and 2, and again just now, and none of them are showing up for me. I know there can be a delay, but I've never had more than a few seconds of delay on here before for a top-level or for a reply.
Jul 24 2009
next sibling parent "Nick Sabalausky" <a a.a> writes:
"Nick Sabalausky" <a a.a> wrote in message 
news:h4bt95$1uul$1 digitalmars.com...
 "Daniel Keep" <daniel.keep.lists gmail.com> wrote in message 
 news:h4br9n$1rje$1 digitalmars.com...
 You can't make value pure, but it is supposed to be a property.  One of
 the examples Nick gives in DIP4 is a property that accesses an SQL
 database; there's no way to make that pure!

Speaking of that, has my top-level post about that (Subject: "DIP4: Properties") shown up for anyone? I first posted it about 12:30am (my time, 4.5 hours ago), than again between 1 and 2, and again just now, and none of them are showing up for me. I know there can be a delay, but I've never had more than a few seconds of delay on here before for a top-level or for a reply.

My stuff seems to still be showing up fine in this thread...
Jul 24 2009
prev sibling parent reply "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
Nick Sabalausky wrote:
 "Daniel Keep" <daniel.keep.lists gmail.com> wrote in message 
 news:h4br9n$1rje$1 digitalmars.com...
 You can't make value pure, but it is supposed to be a property.  One of
 the examples Nick gives in DIP4 is a property that accesses an SQL
 database; there's no way to make that pure!

Speaking of that, has my top-level post about that (Subject: "DIP4: Properties") shown up for anyone? I first posted it about 12:30am (my time, 4.5 hours ago), than again between 1 and 2, and again just now, and none of them are showing up for me. I know there can be a delay, but I've never had more than a few seconds of delay on here before for a top-level or for a reply.

I can see three posts by you in the DIP4 thread. -Lars
Jul 24 2009
parent reply "Nick Sabalausky" <a a.a> writes:
"Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> wrote in message 
news:h4bua5$20bd$1 digitalmars.com...
 Nick Sabalausky wrote:
 "Daniel Keep" <daniel.keep.lists gmail.com> wrote in message 
 news:h4br9n$1rje$1 digitalmars.com...
 You can't make value pure, but it is supposed to be a property.  One of
 the examples Nick gives in DIP4 is a property that accesses an SQL
 database; there's no way to make that pure!

Speaking of that, has my top-level post about that (Subject: "DIP4: Properties") shown up for anyone? I first posted it about 12:30am (my time, 4.5 hours ago), than again between 1 and 2, and again just now, and none of them are showing up for me. I know there can be a delay, but I've never had more than a few seconds of delay on here before for a top-level or for a reply.

I can see three posts by you in the DIP4 thread.

Strange, I still can't see the thread at all, and I've never had trouble seeing my own posts (even in this thread). I'm at least relieved that it apperently isn't three separate DIP4 threads :) Is there a post by anyone other than me in that thread? If not, maybe that would get my reader to finally wake up.
Jul 24 2009
parent "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
Nick Sabalausky wrote:
 "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> wrote in message 
 news:h4bua5$20bd$1 digitalmars.com...
 Nick Sabalausky wrote:
 "Daniel Keep" <daniel.keep.lists gmail.com> wrote in message 
 news:h4br9n$1rje$1 digitalmars.com...
 You can't make value pure, but it is supposed to be a property.  One of
 the examples Nick gives in DIP4 is a property that accesses an SQL
 database; there's no way to make that pure!

Properties") shown up for anyone? I first posted it about 12:30am (my time, 4.5 hours ago), than again between 1 and 2, and again just now, and none of them are showing up for me. I know there can be a delay, but I've never had more than a few seconds of delay on here before for a top-level or for a reply.


Strange, I still can't see the thread at all, and I've never had trouble seeing my own posts (even in this thread). I'm at least relieved that it apperently isn't three separate DIP4 threads :)

Actually, on closer inspection, it turns out there are three separate DIP4 threads. Apparently, Thunderbird was smart enough to group them for me. :)
 Is there a post by anyone other than me in that thread? If not, maybe that 
 would get my reader to finally wake up. 

Yes, Daniel Keep has posted two replies. PS: Both his and your messages are visible in the web interface. -Lars
Jul 24 2009
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Daniel Keep wrote:
 Actually, I've now come up with a counter-example for the idea of using
 pure at all:

That's right, lazy evaluation can't be pure. So, the question is is this an important enough case to justify a whole new syntax?
Jul 24 2009
parent reply Walter Bright <newshound1 digitalmars.com> writes:
Steven Schveighoffer wrote:
 I don't think properties should be necessarily pure anyways.  How do you 
 have a pure setter?  It's more of a convention that a property getter 
 should not change the state of the containing entity, a pretty much 
 non-enforcable convention.

That's my problem with properties as a distinct syntax - they don't have distinct uses or behaviors.
Jul 24 2009
next sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
Steven Schveighoffer wrote:
 On Fri, 24 Jul 2009 14:10:59 -0400, Walter Bright 
 <newshound1 digitalmars.com> wrote:
 
 Steven Schveighoffer wrote:
 I don't think properties should be necessarily pure anyways.  How do 
 you have a pure setter?  It's more of a convention that a property 
 getter should not change the state of the containing entity, a pretty 
 much non-enforcable convention.

That's my problem with properties as a distinct syntax - they don't have distinct uses or behaviors.

If you delineate what can be called how, then you elminate syntax ambiguities from occurring, and eliminate bizarro cases of syntax. The difficulty is that the "human meaning" of a property is different than the human meaning of a function. To the compiler, they're all functions, so you as the compiler writer aren't seeing that they are different. I think we all agree that writefln = "hi"; makes absolutely no sense to a person. But it makes complete sense to the compiler, because it has no idea what the word "writefln" means to a person. It's the exact same reason + is not the concatenation operator. Semantically, making + concatenate two strings together would be completely unambiguous from adding two integers together because strings do not define addition, and integers do not define concatenation. From your own documentation, someone seeing "10" + 3 might think that he would get 13 or "103". Even if the compiler defines what "should" happen, and the rules are unambiguous, it looks incorrect to the user. But having ~ be the concatenation operator makes it completely unambiguous what the syntax means, regardless of what the types are. So the compiler and the user are talking the same language, and the user isn't freaked out by the "human meaning" of the syntax. -Steve

Maybe what scares Walter is a whole new syntax for properties. If at least you could say which functions are properties and which are not, that would be a small change and it'll make it possible for other things. Something like: int property foo(); // getter int property foo(int value); // setter So properties are marked with a modifier and that's it. The compiler could discard those modifiers or, much better, disallow doing things like: bar = 3; // ERROR: bar is not a property foo(); // ERROR: foo is a property and must be used as foo Now we need someone to think which of the current keywords could be used instead of "property". :-P
Jul 24 2009
next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Ary Borenszweig wrote:
 Maybe what scares Walter is a whole new syntax for properties.

It doesn't scare me. It's trivial to add more syntax. It's just that D is complex enough - there needs to be some very good reasons for adding more syntax that has apparently zero semantic information that would be different from the usual function syntax.
Jul 24 2009
next sibling parent Michel Fortin <michel.fortin michelf.com> writes:
On 2009-07-24 17:40:37 -0400, Walter Bright <newshound1 digitalmars.com> said:

 It's just that D is complex enough - there needs to be some very good 
 reasons for adding more syntax that has apparently zero semantic 
 information that would be different from the usual function syntax.

You know. I agree with you on that point. Earlier, in a thread no one replied to [1], demonstrated that we already have almost everyting we need to create properties using mixins. Here's an example: struct Z { int valueSquare; template Property() { int value; void opAssign(int v) { value = v; valueSquare = value * value; } void opAddAssign(int v) { value = v; valueSquare = value * value; } int get() { return value; } alias get this; } mixin Property property; } The only really missing part is that "alias get this" doesn't work ("Error: expression has no value" when fetching a value from z.property) so you have to explicitly call the "get" function. [1]: http://www.digitalmars.com/d/archives/digitalmars/D/properties_using_template_mixins_and_alias_this_87952.html -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jul 24 2009
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Bill Baxter wrote:
 On Mon, Jul 27, 2009 at 7:13 AM, Steven
 Schveighoffer<schveiguy yahoo.com> wrote:
 On Fri, 24 Jul 2009 17:40:37 -0400, Walter Bright
 <newshound1 digitalmars.com> wrote:

 Ary Borenszweig wrote:
 Maybe what scares Walter is a whole new syntax for properties.

It's just that D is complex enough - there needs to be some very good reasons for adding more syntax that has apparently zero semantic information that would be different from the usual function syntax.

What is *your* solution to forbidding abuses like this: writefln = "hi"; ???

I think his suggestion was the Java-style approach -- special naming convention for get/set functions: int opGet_foo() { return foo_; } void opSet_foo(int foo) { foo_ = foo; } private: int foo_; --bb

For one thing I like that I now get to define empty() for a range and then call it with r.empty. I'd think it would be a small step backward if I had to define get_empty() or something instead. Andrei
Jul 27 2009
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Steven Schveighoffer:
 property
 {
     int x() {}
     void x(int n) {}
     bool empty() {}
 }

An alternative: property(x) { ... // or getter and/or setter } Bye, bearophile
Jul 27 2009
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Steven Schveighoffer wrote:
 The "getter" notation that currently exists only has a few minor 
 problems.  The most major of those problems is if the return value is a 
 callable type, such as a delegate, you can't easily perform the call on 
 the returned value.

Thanks for a very lucid analysis! So let me give an example: class A { int delegate() wyda() { return delegate int() { return 5; }; } } void main(string[] args) { auto a = new A; auto b = a.wyda; writeln(typeof(b).stringof); auto c = a.wyda(); writeln(typeof(c).stringof); auto d = a.wyda()(); writeln(typeof(d).stringof); auto e = &a.wyda; writeln(typeof(e).stringof); } This program prints: int delegate() int delegate() int int delegate() delegate() I agree that that's an issue. One can't currently implement transparently a property that returns a delegate taking no arguments. There's an extra () needed.
  Being that it isn't very bad for the getter 
 property, would it make sense to leave that functionality?  That is:
 
 1. A setter must be defined in the opSet_X(int x) form
 2. A getter can be a function with no required arguments, but this 
 getter should not return callable types

... with zero arguments.
 3. A getter can be defined in the opGet_X() form, and then using X() 
 will be the eqivalent of opGet_X()().
 
 There are small implications to leaving the existing getter syntax.  
 Namely one can call a function not intended to be a getter in a 
 property-like syntax, resulting in less-than-obvious code.

This I don't agree with. I am very happy that I define popFront() as a method and then call it without parens.
  Also, this 
 distinction will be very hard to explain to newbies ("how come a getter 
 is defined as x(), but a setter has to be opSet_x(...)?).

I don't see that as a problem. You just explain that the trailing () is not necessary, and then you tell them to define opSet_x if they want to enable obj.x = y.
 The more I look at it, the more I like the keyword solution.  I do find 
 the C#-like syntax which groups properties together appealing, but I 
 think you only absolutely need that if you are going to have 
 context-keywords, which I DON'T think we need.  I do find the whole 
 construct of C# properties tedious to type.
 
 With a keyword attribute, you could even group your properties together 
 to save on typing/ugliness:
 
 property
 {
    int x() {}
    void x(int n) {}
    bool empty() {}
 }

Not a fan, but this would work. I just don't see why I need to go through with it. Andrei
Jul 27 2009
next sibling parent escalan <escalan gmail.com> writes:
Andrei Alexandrescu Wrote:

 Steven Schveighoffer wrote:
 The "getter" notation that currently exists only has a few minor 
 problems.  The most major of those problems is if the return value is a 
 callable type, such as a delegate, you can't easily perform the call on 
 the returned value.

Thanks for a very lucid analysis! So let me give an example: class A { int delegate() wyda() { return delegate int() { return 5; }; } } void main(string[] args) { auto a = new A; auto b = a.wyda; writeln(typeof(b).stringof); auto c = a.wyda(); writeln(typeof(c).stringof); auto d = a.wyda()(); writeln(typeof(d).stringof); auto e = &a.wyda; writeln(typeof(e).stringof); } This program prints: int delegate() int delegate() int int delegate() delegate() I agree that that's an issue. One can't currently implement transparently a property that returns a delegate taking no arguments. There's an extra () needed.
  Being that it isn't very bad for the getter 
 property, would it make sense to leave that functionality?  That is:
 
 1. A setter must be defined in the opSet_X(int x) form
 2. A getter can be a function with no required arguments, but this 
 getter should not return callable types

... with zero arguments.
 3. A getter can be defined in the opGet_X() form, and then using X() 
 will be the eqivalent of opGet_X()().
 
 There are small implications to leaving the existing getter syntax.  
 Namely one can call a function not intended to be a getter in a 
 property-like syntax, resulting in less-than-obvious code.

This I don't agree with. I am very happy that I define popFront() as a method and then call it without parens.
  Also, this 
 distinction will be very hard to explain to newbies ("how come a getter 
 is defined as x(), but a setter has to be opSet_x(...)?).

I don't see that as a problem. You just explain that the trailing () is not necessary, and then you tell them to define opSet_x if they want to enable obj.x = y.
 The more I look at it, the more I like the keyword solution.  I do find 
 the C#-like syntax which groups properties together appealing, but I 
 think you only absolutely need that if you are going to have 
 context-keywords, which I DON'T think we need.  I do find the whole 
 construct of C# properties tedious to type.
 
 With a keyword attribute, you could even group your properties together 
 to save on typing/ugliness:
 
 property
 {
    int x() {}
    void x(int n) {}
    bool empty() {}
 }

Not a fan, but this would work. I just don't see why I need to go through with it. Andrei

Hi, I'm new here. A simple idea I've had is to simply use aliases for defining properties. If you allow writing aliases as expressions, you have get properties. Then a simple extension to the syntax would also allow for writing set properties. alias (a) property; alias (a = n) property(n); foo(property); // Get property = 32; // Set This virtually eliminates any problems with properties, and it doesn't require any new keywords. It won't break existing aliases either.
Jul 27 2009
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Steven Schveighoffer wrote:
 On Mon, 27 Jul 2009 18:37:01 -0400, Andrei Alexandrescu 
 ... with zero arguments.

No, callable types period. Note that this does not compile: class A { int delegate(int foo) wyda() { return delegate int(int foo) { return foo;}; } } int main(string[] args) { auto a = new A; auto b = a.wyda(5); // line 14 auto c = a.wyda()(5); return 1; } [steves steveslaptop files]$ dmd testme.d testme.d(14): Error: function testme.A.wyda () does not match parameter types (int) testme.d(14): Error: expected 0 arguments, not 1 commenting out line 14 compiles.

Ok, thanks.
 3. A getter can be defined in the opGet_X() form, and then using X() 
 will be the eqivalent of opGet_X()().
  There are small implications to leaving the existing getter syntax.  
 Namely one can call a function not intended to be a getter in a 
 property-like syntax, resulting in less-than-obvious code.

This I don't agree with. I am very happy that I define popFront() as a method and then call it without parens.

Knowing that you can call functions without parens, seeing code like: r.popFront; it's obvious that popFront is a function, not a property. But, do you agree that this code looks less-than-obvious? auto x = flush; is flush a flag saying flushing should occur? is it a function that flushes something, and returns the success? I agree that the bizarre factor is not as bad as with setters, but it's still not as self-explanatory as if you know that something without parens must be a property for the compiler to accept it.

I think inferring meaning from the presence or absence of "()" is rather dicey.
 Let's separate this problem into two sections:
 
 1. do we have to hint to the compiler that a function is a property or not?
 
 I think we do, otherwise, we have the strange setter anomalies, and the 
 inability to return delegates from getters.

Well I don't think so. To repeat what I wrote elsethread: foo = bar is rewritten into foo(bar) if and only if auto __x = foo, __x = bar works. This means, a setter only works if there's a corresponding getter. (Write-only properties be damned.) Andrei
Jul 28 2009
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Steven Schveighoffer wrote:
 On Tue, 28 Jul 2009 10:16:16 -0400, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 
 I think inferring meaning from the presence or absence of "()" is 
 rather dicey.

Really? Then why name your functions things like empty, why not ex245, to make them look it up, making *sure* they know what the meaning is before they use it.

I didn't say not to infer meaning from the name.
 As one other person stated, they thought empty() 
 emptied a range.

Well it doesn't.
 Being able to read code and understand what it means without resorting 
 to documentation is the sign of a good choice of symbol names.

Sure.
 The 
 presence or absence of parens is a hard-coded accepted meaning of field 
 vs. function.

I understand how some people want to derive meaning from obj.foo() versus obj.foo. I think they shouldn't in D. I mean D has had for years the behavior that you could drop the trailing empty parentheses.
 Properties build on this notion by making a virtual field 
 that actually resolves to a function (but behaves like a field, and this 
 is an important accepted meaning).

Not quite. C# has allocated a language feature for properties. Yet they allow you to write write-only properties, which do NOT behave at all like fields, and also read-only properties, which also don't behave like fields. Guess what - they both behave like functions. So their properties are an elaborate mechanism that is actually thoroughly unchecked, thus going back to what you could do by calling functions. So why the hell did they define the feature in the first place? Oh, for allowing people to write a.foo() instead of a.foo. You know what, that's a bit disappointing for an entire language feature.
 However, D does not allow intuitive 
 names to be paired with the intuitive meaning of the presense or absence 
 of parens, because you can't enforce it!  Remember my example with 
 TimeSpans?  People will infer meaning from the presense or absense of 
 parens whether you think it's a good idea or not.  You will never get 
 away from it.
 
 Let's separate this problem into two sections:
  1. do we have to hint to the compiler that a function is a property 
 or not?
  I think we do, otherwise, we have the strange setter anomalies, and 
 the inability to return delegates from getters.

Well I don't think so. To repeat what I wrote elsethread: foo = bar is rewritten into foo(bar) if and only if auto __x = foo, __x = bar works. This means, a setter only works if there's a corresponding getter. (Write-only properties be damned.)

This is a band-aid fix, easily broken. int select(int timeoutMS = -1); // method on a socket, for example Hell, even my TimeSpan problem would still fail.

Well maybe you could change TimeSpan.
 Also you are forgoing the ability to have overloaded setters, which 
 could be useful.  Not to mention getters for delegates.

Wait, overloaded setters do NOT make the thing behave like a field, but you were stating how nice that is a few paragraphs ago! So what is it that you think is good? Andrei
Jul 28 2009
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Steven Schveighoffer wrote:
 On Tue, 28 Jul 2009 11:11:09 -0400, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 
 Steven Schveighoffer wrote:
 On Tue, 28 Jul 2009 10:16:16 -0400, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:

 I think inferring meaning from the presence or absence of "()" is 
 rather dicey.

ex245, to make them look it up, making *sure* they know what the meaning is before they use it.

I didn't say not to infer meaning from the name.

No, you're saying inferring meaning from parentheses is not a good idea. I think it's the same thing as saying that inferring the meaning from a function/field name is not a good idea (just in a more sarcastic way...). When you see parentheses, you infer function. When you don't you infer field/property. Note that I'm not just pulling this out of a hat, it's the way people already think, you should acknowledge that.

I acknowledge that in C, C++, and Java, you must add () to call an argument-less function. I also acknowledge that in C# a.b could mean either a field access or execution of arbitrary code.
 As one other person stated, they thought empty() emptied a range.

Well it doesn't.

Exactly, so why do you think he thought that? Let's take someone who's used a language that uses () do denote a function, and no parens to denote a field (there are a few of them out there). Would that person ever think that x.empty; means "empty the contents of x"? The answer is no, not ever. Whether you like it or not or think it's dicey or not PEOPLE WILL INFER MEANING FROM PARENTHESES. I even do it, even though I *know* that it's dicey. I hate having to look up usages of things that make no sense because I have no idea what the code is doing. It's so much better when the meaning is clear from the code itself.

I acknowledge that some people infer meaning from parentheses. I mean, there's at least one :o).
 Being able to read code and understand what it means without 
 resorting to documentation is the sign of a good choice of symbol names.

Sure.
 The presence or absence of parens is a hard-coded accepted meaning of 
 field vs. function.

I understand how some people want to derive meaning from obj.foo() versus obj.foo. I think they shouldn't in D. I mean D has had for years the behavior that you could drop the trailing empty parentheses.

And for years, there have been complaints about it. This will continuously be a thorn in the side of D adoption until it is resolved.

Again, most complaints have been directed towards writeln = 5. I think that's the major problem to be resolved.
 Properties build on this notion by making a virtual field that 
 actually resolves to a function (but behaves like a field, and this 
 is an important accepted meaning).

Not quite. C# has allocated a language feature for properties. Yet they allow you to write write-only properties, which do NOT behave at all like fields

I'll give you that one, but that's an uncommon "because we can" case.

I acknowledge that you give me that one.
 and also read-only properties, which also don't behave like fields.

Ever heard of readonly fields? Yes, they exist in C#. Besides, that's one of the benefits of properties, you can do things that you can't do with fields, otherwise why have them?

So now C# has two ways of providing a readonly field. Doesn't quite look like an example to follow.
 Guess what - they both behave like functions. So their properties are 
 an elaborate mechanism that is actually thoroughly unchecked, thus 
 going back to what you could do by calling functions. So why the hell 
 did they define the feature in the first place? Oh, for allowing 
 people to write a.foo() instead of a.foo. You know what, that's a bit 
 disappointing for an entire language feature.

No, they did it to *force* you to write a.foo instead of a.foo(), to make it more defined that foo is a field-like entity.

Which is not, because it can execute arbitrary code that is not restricted in any way. How good a design is that? Back to semantics by convention? That's what I'm saying: if it could do anything, at least don't pretend it's anything special. It's a function!
 There's a subtle, 
 yet very important difference.  They saw the implementation of 
 properties in Java as a good thing, but Java relied on a social standard 
 that a method that begins with get is a getter, a method that begins 
 with set is a setter, and a method that begins with is is a boolean.  C# 
 provides a better way to convey that contract via properties.

Why is C#'s way better?
 D's implementation looks to me like a quick hack so D can say "look, we 
 have properties!"  They don't provide any of the interface benefits that 
 true properties do.

What are the interface benefits that "true" properties do? What is a "true" property? Something that could do anything. Surprise, that was already the charter of functions. Well thank you very much.
 Might as well go back to Java style, where you have 
 to name your properties getX, setX or isX.  But now, normal functions 
 are corrupted with the ability to use them as properties.

Yum.
 Well I don't think so. To repeat what I wrote elsethread: foo = bar 
 is rewritten into foo(bar) if and only if auto __x = foo, __x = bar 
 works. This means, a setter only works if there's a corresponding 
 getter. (Write-only properties be damned.)

int select(int timeoutMS = -1); // method on a socket, for example Hell, even my TimeSpan problem would still fail.

Well maybe you could change TimeSpan.

Lovely. Force the developer to rename his functions because D is too weak to allow defining a correct interface.

Or maybe because her use of name was too ambiguous.
 You didn't even address the 
 select example, I think that's a very compelling example of something 
 that breaks your rule.

I agree that that example reveals a problem. I also think that that problem could be solved, but I doubt that you'll be pleased.
 My point is that your rule only works if you write code in a certain 
 way,

Your rule also works if you write code in a certain way.
 and I don't think that should be a determination of whether 
 something is a property or not by the compiler, because the naming of 
 functions is supposed to be up to the developer, not the spec.

opXxx are up to the spec.
 It's 
 like a prejudice against certain coding styles without any good reason.

I don't see that. I more see a prejudice against dropping "()" when calling a function.
 Also you are forgoing the ability to have overloaded setters, which 
 could be useful.  Not to mention getters for delegates.

Wait, overloaded setters do NOT make the thing behave like a field, but you were stating how nice that is a few paragraphs ago! So what is it that you think is good?

Yes they do. It makes them behave like a variant field.

Then write a function that takes a variant instead of overloading.
 e.g.
 
 x.timeout = 5.5; // set timeout to 5.5 seconds
 x.timeout = TimeSpan.seconds(5); // set timeout to 5 seconds exactly
 
 And what about getters for delegates?  That problem is still unresolved 
 by your rule.

I believe it's a minor problem that does not impede people from getting work done. Andrei
Jul 28 2009
next sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
Andrei Alexandrescu wrote:
 Steven Schveighoffer wrote:
 On Tue, 28 Jul 2009 11:11:09 -0400, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 Guess what - they both behave like functions. So their properties are 
 an elaborate mechanism that is actually thoroughly unchecked, thus 
 going back to what you could do by calling functions. So why the hell 
 did they define the feature in the first place? Oh, for allowing 
 people to write a.foo() instead of a.foo. You know what, that's a bit 
 disappointing for an entire language feature.

No, they did it to *force* you to write a.foo instead of a.foo(), to make it more defined that foo is a field-like entity.

Which is not, because it can execute arbitrary code that is not restricted in any way. How good a design is that? Back to semantics by convention?

Back to semantics by convention? Whenever you write *anything*, there's always semantic by convention. writefln("Foo"); That writefln could just do antyhing with it's argument, maybe return it twice. So how do you enforce writefln to actually write something? Aaaah... D sucks because it can't enforce that.
Jul 28 2009
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Ary Borenszweig wrote:
 Andrei Alexandrescu wrote:
 Steven Schveighoffer wrote:
 On Tue, 28 Jul 2009 11:11:09 -0400, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 Guess what - they both behave like functions. So their properties 
 are an elaborate mechanism that is actually thoroughly unchecked, 
 thus going back to what you could do by calling functions. So why 
 the hell did they define the feature in the first place? Oh, for 
 allowing people to write a.foo() instead of a.foo. You know what, 
 that's a bit disappointing for an entire language feature.

No, they did it to *force* you to write a.foo instead of a.foo(), to make it more defined that foo is a field-like entity.

Which is not, because it can execute arbitrary code that is not restricted in any way. How good a design is that? Back to semantics by convention?

Back to semantics by convention? Whenever you write *anything*, there's always semantic by convention. writefln("Foo"); That writefln could just do antyhing with it's argument, maybe return it twice. So how do you enforce writefln to actually write something? Aaaah... D sucks because it can't enforce that.

I was replying to the expectation that a.foo() does an action and a.foo allegedly does not. Andrei
Jul 28 2009
prev sibling parent Rainer Deyke <rainerd eldwood.com> writes:
I C++, I write a lot of functions with names in the form of get_foo,
set_foo, or is_foo.  The get/set/is isn't just clutter, it serves an
important function in describing the semantics of the function.  A
function named 'empty' has different semantics than a function named
'is_empty'.  A function named 'get_color' has different semantics than a
function named 'color'.

To me, 'y = x;' makes a lot of sense as syntax sugar for 'y = get_x();',
but makes no sense as syntax sugar for 'y = x();'.  Writing 'y = get_x;'
instead of 'y = get_x();' is barely an improvement, and nowhere near as
nice as 'y = x;'.

Likewise, 'x = y;' makes sense as syntax sugar for 'set_x(y);', but not
as syntax sugar for 'x(y);'.  I don't want to have to write 'set_x = y;'.

So, yes, properties are just functions.  However, they are /different/
functions from the functions with the same name as the property, with
different semantics.  Its use as a property is logically part of the
name of a function.


-- 
Rainer Deyke - rainerd eldwood.com
Jul 28 2009
prev sibling next sibling parent Ary Borenszweig <ary esperanto.org.ar> writes:
Andrei Alexandrescu wrote:
 Steven Schveighoffer wrote:
 On Tue, 28 Jul 2009 11:11:09 -0400, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 D's implementation looks to me like a quick hack so D can say "look, 
 we have properties!"  They don't provide any of the interface benefits 
 that true properties do.

What are the interface benefits that "true" properties do? What is a "true" property? Something that could do anything. Surprise, that was already the charter of functions. Well thank you very much.

Just because it could do anything doesn't mean it *has* to do anything. Again, D ranges suck because the compiler can't enforce you that empty, pop, etc., actually do what their name says.
Jul 28 2009
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Bill Baxter wrote:
 On Tue, Jul 28, 2009 at 10:20 AM, Steven
 Schveighoffer<schveiguy yahoo.com> wrote:
 On Tue, 28 Jul 2009 12:30:00 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 Steven Schveighoffer wrote:


 What if the compiler allowed you to call functions as long as what you
 typed was an unambiguous prefix of the function name
 why don't we have a
 wonderful time-saving feature like this?  Because it would be a nightmare to
 read.

 So now C# has two ways of providing a readonly field. Doesn't quite look
 like an example to follow.

Yes, that's right. readonly is analogous to const.

 That's what I'm saying: if it could do anything, at least don't pretend
 it's anything special. It's a function!

So would you argue that C# or D with operator overloading isn't better because operators are just functions, why call them something else?

Bravo! Fine, rational arguments, Steve.

I don't think it's a good argument. Operators are functions with a specific syntax, is all. D is not even pretending any different: it simply rewrites the usual syntax into function calls. We should do the same with properties. Andrei
Jul 28 2009
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Steven Schveighoffer wrote:
 However, when I see:
 
 x.empty;
 
 I can't tell what is implied here.

You can. In either C# or D language it could execute arbitrary code that you better know what it's supposed to do. D simply doesn't make it "bad style" as C# stupidly does. Andrei
Jul 28 2009
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Steven Schveighoffer wrote:
 On Tue, 28 Jul 2009 16:08:58 -0400, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 
 Steven Schveighoffer wrote:
 However, when I see:
  x.empty;
  I can't tell what is implied here.

You can. In either C# or D language it could execute arbitrary code that you better know what it's supposed to do. D simply doesn't make it "bad style" as C# stupidly does.

still not getting it, are you... Just forget it, I think this is a lost cause, I keep making the same points over and over again, and you keep not reading them.

I do read them and understand them. I mean, it's not rocket surgery. At the end of the day you say "x = a.b;" looks more like sheer access because that's what happens for fields already. Then you say "a.b()" in any context looks more like an action because it's clear that there's a function call involved. But your arguments are not convincing to me, and in turn I explained why. What would you do if you were me? Andrei
Jul 28 2009
next sibling parent reply aarti_pl <aarti interia.pl> writes:
Andrei Alexandrescu pisze:
 Steven Schveighoffer wrote:
 On Tue, 28 Jul 2009 16:08:58 -0400, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:

 Steven Schveighoffer wrote:
 However, when I see:
  x.empty;
  I can't tell what is implied here.

You can. In either C# or D language it could execute arbitrary code that you better know what it's supposed to do. D simply doesn't make it "bad style" as C# stupidly does.

still not getting it, are you... Just forget it, I think this is a lost cause, I keep making the same points over and over again, and you keep not reading them.

I do read them and understand them. I mean, it's not rocket surgery. At the end of the day you say "x = a.b;" looks more like sheer access because that's what happens for fields already. Then you say "a.b()" in any context looks more like an action because it's clear that there's a function call involved. But your arguments are not convincing to me, and in turn I explained why. What would you do if you were me? Andrei

You should just accept what others want *although* you don't agree... Steve's arguments are very good and convincing, and unfortunately somehow you don't get them. And I don't see your arguments being superior at all. Sorry for thread hijacking, but such discussions make me want not to use D any more... I am writing because I still have some hope... Maybe community should decide in poll who's arguments are better? BR Marcin Kuszczak
Jul 28 2009
next sibling parent Ary Borenszweig <ary esperanto.org.ar> writes:
aarti_pl wrote:
 Andrei Alexandrescu pisze:
 Steven Schveighoffer wrote:
 On Tue, 28 Jul 2009 16:08:58 -0400, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:

 Steven Schveighoffer wrote:
 However, when I see:
  x.empty;
  I can't tell what is implied here.

You can. In either C# or D language it could execute arbitrary code that you better know what it's supposed to do. D simply doesn't make it "bad style" as C# stupidly does.

still not getting it, are you... Just forget it, I think this is a lost cause, I keep making the same points over and over again, and you keep not reading them.

I do read them and understand them. I mean, it's not rocket surgery. At the end of the day you say "x = a.b;" looks more like sheer access because that's what happens for fields already. Then you say "a.b()" in any context looks more like an action because it's clear that there's a function call involved. But your arguments are not convincing to me, and in turn I explained why. What would you do if you were me? Andrei

You should just accept what others want *although* you don't agree... Steve's arguments are very good and convincing, and unfortunately somehow you don't get them. And I don't see your arguments being superior at all. Sorry for thread hijacking, but such discussions make me want not to use D any more... I am writing because I still have some hope... Maybe community should decide in poll who's arguments are better?

I'd like to see a poll about this. I think just a few want the ability to remove the () from an argument-less function call, and all of us others want the opposite.
Jul 28 2009
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
aarti_pl wrote:
 Andrei Alexandrescu pisze:
 Steven Schveighoffer wrote:
 On Tue, 28 Jul 2009 16:08:58 -0400, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:

 Steven Schveighoffer wrote:
 However, when I see:
  x.empty;
  I can't tell what is implied here.

You can. In either C# or D language it could execute arbitrary code that you better know what it's supposed to do. D simply doesn't make it "bad style" as C# stupidly does.

still not getting it, are you... Just forget it, I think this is a lost cause, I keep making the same points over and over again, and you keep not reading them.

I do read them and understand them. I mean, it's not rocket surgery. At the end of the day you say "x = a.b;" looks more like sheer access because that's what happens for fields already. Then you say "a.b()" in any context looks more like an action because it's clear that there's a function call involved. But your arguments are not convincing to me, and in turn I explained why. What would you do if you were me? Andrei

You should just accept what others want *although* you don't agree... Steve's arguments are very good and convincing, and unfortunately somehow you don't get them. And I don't see your arguments being superior at all.

I do get his arguments. Not being convinced does not mean I don't understand them. You seem to assume that as soon as I understood his arguments I'd automatically agree, so somehow I don't understand them.
 Sorry for thread hijacking, but such discussions make me want not to use 
 D any more... I am writing because I still have some hope...

D has great features, and probably less warts than most other languages. I understand how you feel, but I'd also hope that realistically your use of the language hinges on a little more than this one issue.
 Maybe community should decide in poll who's arguments are better?

That would be helpful. Andrei
Jul 28 2009
parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:
 Maybe community should decide in poll who's arguments are better?

That would be helpful.

Designing a language with polls is an obvious idea, but I have not suggested it in the past because it has some drawbacks too (there's a risk of losing the coherence of the language and to use "political" solutions that are mostly good to close the muzzle of the majority of people). On the other hand it has some advantages too (example: despite you are intelligent, some names and function/templates signatures you have added to Phobos may be not good because you aren't equal to the average person, everyone has some personal quirks. So designing by poll helps remove such quirks). So this time, as an experiment, we may try to see what happens using a poll :-) Language design polls must be not anonymous, each vote must have a name beside it. I think that a poll done in the past may have lead to different outcomes (for example in two recent changes to the "switch", one by you and one by Walter). Bye, bearophile
Jul 28 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
bearophile wrote:
 Andrei Alexandrescu:
 Maybe community should decide in poll who's arguments are better?


Designing a language with polls is an obvious idea, but I have not suggested it in the past because it has some drawbacks too (there's a risk of losing the coherence of the language and to use "political" solutions that are mostly good to close the muzzle of the majority of people). On the other hand it has some advantages too (example: despite you are intelligent, some names and function/templates signatures you have added to Phobos may be not good because you aren't equal to the average person, everyone has some personal quirks. So designing by poll helps remove such quirks). So this time, as an experiment, we may try to see what happens using a poll :-) Language design polls must be not anonymous, each vote must have a name beside it. I think that a poll done in the past may have lead to different outcomes (for example in two recent changes to the "switch", one by you and one by Walter).

Great thoughts. One thing that maybe is not clear is that I afford to argue in these debates exactly because I don't get to decide. Walter never implements something that is not convinced of. It happens often that I suggest an improvement that he doesn't approve for one reason or another. Last time I suggested that switch should work with all types that support comparison (it's just weird that it only works with ints and strings), but he refused to consider it at least for the time being. So, polls would be very useful to gauge what people want. That's very solid information. Andrei
Jul 28 2009
parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:
 So, polls would be very useful to gauge what people want. That's very 
 solid information.

I want to add two small things: 1) Votes must follow a period of discussions, and possibly even a summary that lists the most common ideas. Otherwise lot of people will base their vote on an insufficient level of knowledge of the topic :-) 2) Votes (or proposals) may be all equal, with always a "weight" of 1. OR they may have a variable weight, that for example comes from the estimated experience (or importance) of a person on a topic. For example once I have seen Guido V. Rossum vote for something with with a weight of 1000 (it essentially meant that his decision was the final one). It means that for example I can accept that a vote by Bartoz regarding some concurrency topic is much more heavy (important) than mine, because I know very little about that topic compared to him. In practice to keep things practical most people have a weight of 1, with few known exceptions (for example if you define the API of regex you may have a weight of 4 or 5). Bye, bearophile
Jul 28 2009
next sibling parent Ary Borenszweig <ary esperanto.org.ar> writes:
bearophile escribiů:
 Andrei Alexandrescu:
 So, polls would be very useful to gauge what people want. That's very 
 solid information.

I want to add two small things: 1) Votes must follow a period of discussions, and possibly even a summary that lists the most common ideas. Otherwise lot of people will base their vote on an insufficient level of knowledge of the topic :-) 2) Votes (or proposals) may be all equal, with always a "weight" of 1. OR they may have a variable weight, that for example comes from the estimated experience (or importance) of a person on a topic. For example once I have seen Guido V. Rossum vote for something with with a weight of 1000 (it essentially meant that his decision was the final one). It means that for example I can accept that a vote by Bartoz regarding some concurrency topic is much more heavy (important) than mine, because I know very little about that topic compared to him. In practice to keep things practical most people have a weight of 1, with few known exceptions (for example if you define the API of regex you may have a weight of 4 or 5).

Do you know such a poll system that's free? I just created a poll, but forgot about these points...
Jul 28 2009
prev sibling parent bearophile <bearophileHUGS lycos.com> writes:
bearophile:
(for example if you define the API of regex you may have a weight of 4 or 5).<

Just to be sure of what I mean: it mans you can express a vote in the closed interval [-5 .. +5], you aren't forced to vote just -5 and +5 :-) Bye, bearophile
Jul 28 2009
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Bill Baxter wrote:
 On Tue, Jul 28, 2009 at 1:49 PM, Andrei
 Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:
 aarti_pl wrote:
 What would you do if you were me?

 Andrei

Steve's arguments are very good and convincing, and unfortunately somehow you don't get them. And I don't see your arguments being superior at all.

them. You seem to assume that as soon as I understood his arguments I'd automatically agree, so somehow I don't understand them

I think the expectation is more that you would address or respond to his argument rather than making your own argument again. Or say something like this: The fundamental difference in our viewpoints is that you believe that expressing extra semantic information to people who read the code is more valuable that saving some typing. I believe the opposite. (feel free to rewrite as you wish) Then it is clear that you have understood his argument and have some idea how and where the difference in opinion really comes from. Simply repeating your argument makes it look as though you have not read his.

Well we both repeated our arguments several times :o). And don't forget: I don't get to decide. So such a discussion between Steve and me could as well be a discussion between any two participants. I do have accountability for Phobos, and there haven't been huge debates about it that I vetoed against, have there?
 Sorry for thread hijacking, but such discussions make me want not to use D
 any more... I am writing because I still have some hope...

understand how you feel, but I'd also hope that realistically your use of the language hinges on a little more than this one issue.

I don't think it's this one issue he's talking about. I think the issue is an occasionally repeated history of questionable changes in D made in the face of strong community opposition. Like foreach_reverse. Such choices may be perfectly valid, but if you find yourself repeatedly not seeing eye-to-eye with the designers of a language, you have to wonder if you're in the right language community.

I understand. On the other hand, a lot of good things have been done in relative silence, which are likely to positively impact code writing experience a great deal. They just need some more riping. For example, I consider the recently-introduced value range propagation an excellent feature and a well-balanced engineering tradeoff. Such a thing *would* be the kind of feature that would make me cast an interested eye over a language. Finally, a step forward in the always-muddy world of fixed-size integer arithmetic. Then probably I'd try value range propagation and see the compiler essentially fail for all cases (Walter, Walter... I wonder if you had *any* test case for the thing) and then give up in frustration. Andrei
Jul 28 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Bill Baxter wrote:
 On Tue, Jul 28, 2009 at 2:35 PM, Andrei
 Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Tue, Jul 28, 2009 at 1:49 PM, Andrei
 Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:
 I think the expectation is more that you would address or respond to
 his argument rather than making your own argument again.

 Or say something like this:
 The fundamental difference in our viewpoints is that you believe that
 expressing extra semantic information to people who read the code is
 more valuable that saving some typing.  I believe the opposite.

 (feel free to rewrite as you wish)  Then it is clear that you have
 understood his argument and have some idea how and where the
 difference in opinion really comes from.   Simply repeating your
 argument makes it look as though you have not read his.

don't get to decide. So such a discussion between Steve and me could as well be a discussion between any two participants.

That's not quite true. You do talk to Walter more than Steve does. And I think everyone can guess that if you don't get convinced there's no way Walter will be. Convincing you isn't sufficient, but it is necessary.

Oh yeah? How about "lazy"? Andrei
Jul 28 2009
prev sibling parent Benji Smith <dlanguage benjismith.net> writes:
Andrei Alexandrescu wrote:
 Steven Schveighoffer wrote:
 On Tue, 28 Jul 2009 16:08:58 -0400, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:

 Steven Schveighoffer wrote:
 However, when I see:
  x.empty;
  I can't tell what is implied here.

You can. In either C# or D language it could execute arbitrary code that you better know what it's supposed to do. D simply doesn't make it "bad style" as C# stupidly does.

still not getting it, are you... Just forget it, I think this is a lost cause, I keep making the same points over and over again, and you keep not reading them.

I do read them and understand them. I mean, it's not rocket surgery. At the end of the day you say "x = a.b;" looks more like sheer access because that's what happens for fields already. Then you say "a.b()" in any context looks more like an action because it's clear that there's a function call involved. But your arguments are not convincing to me, and in turn I explained why. What would you do if you were me? Andrei

I totally agree with Steven's arguments (and have enjoyed reading the discussion). I think the reason he says you're "not getting it" is because your examples tend to be "a.b" whereas his examples tend to be "a.empty". In your examples, you've stripped away the distinct function/field names and presented the argument from the compiler's perspective: in terms of arbitrary symbols that might either perform a pointer dereference or a function invocation. Steve's arguments, on the other hand, are all from the perspective of the programmer. The parentheses following the identifier act as *punctuation* that clarify intent. Good? Good. --benji
Jul 30 2009
prev sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Tue, Jul 28, 2009 at 4:45 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Tue, Jul 28, 2009 at 2:35 PM, Andrei
 Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Tue, Jul 28, 2009 at 1:49 PM, Andrei
 Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:
 I think the expectation is more that you would address or respond to
 his argument rather than making your own argument again.

 Or say something like this:
 The fundamental difference in our viewpoints is that you believe that
 expressing extra semantic information to people who read the code is
 more valuable that saving some typing. =A0I believe the opposite.

 (feel free to rewrite as you wish) =A0Then it is clear that you have
 understood his argument and have some idea how and where the
 difference in opinion really comes from. =A0 Simply repeating your
 argument makes it look as though you have not read his.

Well we both repeated our arguments several times :o). And don't forget=



 don't get to decide. So such a discussion between Steve and me could as=



 be a discussion between any two participants.

That's not quite true. =A0You do talk to Walter more than Steve does. And I think everyone can guess that if you don't get convinced there's no way Walter will be. =A0Convincing you isn't sufficient, but it is necessary.

Oh yeah? How about "lazy"?

I mean in this case, since Walter seems happy to leave things as-is. His expressed desire is to change things as little as possible here. So if you say a new keyword isn't necessary the chance of a new keyword is basically zero. --bb
Jul 28 2009
prev sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Tue, Jul 28, 2009 at 2:35 PM, Andrei
Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Tue, Jul 28, 2009 at 1:49 PM, Andrei
 Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:

his argument rather than making your own argument again. Or say something like this: The fundamental difference in our viewpoints is that you believe that expressing extra semantic information to people who read the code is more valuable that saving some typing. =A0I believe the opposite. (feel free to rewrite as you wish) =A0Then it is clear that you have understood his argument and have some idea how and where the difference in opinion really comes from. =A0 Simply repeating your argument makes it look as though you have not read his.

Well we both repeated our arguments several times :o). And don't forget: =

 don't get to decide. So such a discussion between Steve and me could as w=

 be a discussion between any two participants.

That's not quite true. You do talk to Walter more than Steve does. And I think everyone can guess that if you don't get convinced there's no way Walter will be. Convincing you isn't sufficient, but it is necessary.
 I do have accountability for Phobos, and there haven't been huge debates
 about it that I vetoed against, have there?

You have indeed made a good effort there. It was iffy for a while with the head/toe thing, but you did come around. :-)
 I don't think it's this one issue he's talking about. =A0I think the
 issue is an occasionally repeated history of questionable changes in D
 made in the face of strong community opposition. =A0Like
 foreach_reverse. =A0Such choices may be perfectly valid, but if you find
 yourself repeatedly not seeing eye-to-eye with the designers of a
 language, you have to wonder if you're in the right language
 community.

I understand. On the other hand, a lot of good things have been done in relative silence, which are likely to positively impact code writing experience a great deal. They just need some more riping. For example, I consider the recently-introduced value range propagation an excellent feature and a well-balanced engineering tradeoff. Such a thing *would* be the kind of feature that would make me cast an interested eye over a language. Finally, a step forward in the always-muddy world of fixed-size integer arithmetic. Then probably I'd try value range propagation and see the compiler essentially fail for all cases (Walter, Walter... I wonder i=

 you had *any* test case for the thing) and then give up in frustration.

There's probably a connection there with human nature's way of remembering affronts much more clearly and dearly than compliments. --bb
Jul 28 2009
prev sibling next sibling parent Sergey Gromov <snake.scaly gmail.com> writes:
Tue, 28 Jul 2009 11:30:00 -0500, Andrei Alexandrescu wrote:

 The presence or absence of parens is a hard-coded accepted meaning of 
 field vs. function.

I understand how some people want to derive meaning from obj.foo() versus obj.foo. I think they shouldn't in D. I mean D has had for years the behavior that you could drop the trailing empty parentheses.

And for years, there have been complaints about it. This will continuously be a thorn in the side of D adoption until it is resolved.

Again, most complaints have been directed towards writeln = 5. I think that's the major problem to be resolved.

I think it is mentioned more often because you tend to agree with it. There are many more as valid arguments which you discard or ignore, mainly maintainability.
Jul 28 2009
prev sibling parent Sergey Gromov <snake.scaly gmail.com> writes:
Tue, 28 Jul 2009 13:20:30 -0400, Steven Schveighoffer wrote:

 Let me come at another angle.  You can't view properties as some sort of  
 enforcement by the compiler.  The compiler is not guaranteeing that if you  
 call something without parentheses, it doesn't execute arbitrary code, it  
 has nothing to do with what the compiler guarantees.  But the *meaning*  
 that the author of the function wishes to convey is available via the  
 requirement of parentheses or lack thereof.  The author of the code is  
 saying "I wrote this function as if it were a field."

I think the reason is purely syntactical. Specifically to distinguish nouns from verbs. Many English words can be used as both. "Empty" may mean "contains nothing" or "to throw everything away" and both meanings are equally valid. You need context to derive the correct meaning of a word. You always have such context in human language because of its nature. Programming languages are much more formalized which robs you of context. Parentheses make a perfect syntactic convention for anybody familiar with C family languages: verbs have parens, nouns (adjectives, adverbs) don't. Because functions do things but variables do not. So when I define "empty" as a property in C# I don't promise pure behavior or O(1) complexity. I simply state: "This *word* is not a verb. Read it accordingly." And it's immediately clear to me that "empty" is "nothing inside" while "empty()" is "do cleanup".
Jul 28 2009
prev sibling parent reply =?UTF-8?B?IkrDqXLDtG1lIE0uIEJlcmdlciI=?= <jeberger free.fr> writes:
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable

Andrei Alexandrescu wrote:
 Steven Schveighoffer wrote:
 The presence or absence of parens is a hard-coded accepted meaning of =


 field vs. function.

I understand how some people want to derive meaning from obj.foo()=20 versus obj.foo. I think they shouldn't in D. I mean D has had for years=

 the behavior that you could drop the trailing empty parentheses.
=20

And of course, D has such a huge number of users already that=20 anyone who comes from another language can just go to hell as far as=20 we're concerned... </sarcasm> Jerome --=20 mailto:jeberger free.fr http://jeberger.free.fr Jabber: jeberger jabber.fr
Jul 28 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
J√©r√īme M. Berger wrote:
 Andrei Alexandrescu wrote:
 Steven Schveighoffer wrote:
 The presence or absence of parens is a hard-coded accepted meaning of 
 field vs. function.

I understand how some people want to derive meaning from obj.foo() versus obj.foo. I think they shouldn't in D. I mean D has had for years the behavior that you could drop the trailing empty parentheses.

And of course, D has such a huge number of users already that anyone who comes from another language can just go to hell as far as we're concerned... </sarcasm>

But then they'd expect a number of improvements wouldn't they. To me, the space-wasting and uncomfortable-to-type parens have always been unpleasant noise. I like some of the values of the old village I grew up in, but please pave the darn road, I could do without the mud. Andrei
Jul 28 2009
prev sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2009-07-28 10:16:16 -0400, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 Well I don't think so. To repeat what I wrote elsethread: foo = bar is 
 rewritten into foo(bar) if and only if auto __x = foo, __x = bar works. 
 This means, a setter only works if there's a corresponding getter. 
 (Write-only properties be damned.)

This may lead to strange issues if both the setter and the getter don't have the same protection attribute, or purity, or constness of arguments. For instance: protected void foo(Object o); public pure const const(Object) foo(); Here, you can assign to foo using the property syntax only from a non-pure functions of this class or a derived classes and when the value you're assinging is a const(Object). Elsewhere, you can only assign using the function syntax. Anything else would break "auto __x = foo, __x = bar". -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jul 28 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Michel Fortin wrote:
 On 2009-07-28 10:16:16 -0400, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> said:
 
 Well I don't think so. To repeat what I wrote elsethread: foo = bar is 
 rewritten into foo(bar) if and only if auto __x = foo, __x = bar 
 works. This means, a setter only works if there's a corresponding 
 getter. (Write-only properties be damned.)

This may lead to strange issues if both the setter and the getter don't have the same protection attribute, or purity, or constness of arguments. For instance: protected void foo(Object o); public pure const const(Object) foo(); Here, you can assign to foo using the property syntax only from a non-pure functions of this class or a derived classes and when the value you're assinging is a const(Object). Elsewhere, you can only assign using the function syntax. Anything else would break "auto __x = foo, __x = bar".

Well I chose the rule that makes bar look and feel as much as an assignable value as possible. The rule could be relaxed (e.g. by dropping qualifiers), but that means we're departing from assignable value lookalike. Andrei
Jul 28 2009
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2009-07-28 11:37:05 -0400, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 Michel Fortin wrote:
 On 2009-07-28 10:16:16 -0400, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> said:
 
 Well I don't think so. To repeat what I wrote elsethread: foo = bar is 
 rewritten into foo(bar) if and only if auto __x = foo, __x = bar works. 
 This means, a setter only works if there's a corresponding getter. 
 (Write-only properties be damned.)

This may lead to strange issues if both the setter and the getter don't have the same protection attribute, or purity, or constness of arguments. For instance: protected void foo(Object o); public pure const const(Object) foo(); Here, you can assign to foo using the property syntax only from a non-pure functions of this class or a derived classes and when the value you're assinging is a const(Object). Elsewhere, you can only assign using the function syntax. Anything else would break "auto __x = foo, __x = bar".

Well I chose the rule that makes bar look and feel as much as an assignable value as possible. The rule could be relaxed (e.g. by dropping qualifiers), but that means we're departing from assignable value lookalike.

Also, what if a derived class implements a getter while the base class only has a setter. Does that mean that only the derived class can use the property syntax on the base class' setter? What I don't like about that proposal is that that how to call a setter is bound to the existence of another function in the same scope using pretty non-obvious rules. Also, it doesn't solve the problem of the getter that returns a delegate since you can continue using the function notation with properties and you can continue to call functions with no parenthesis. While I like too being able to call functions with no argument by skipping the tailing parenthesis, I'd easily give up on that if it means I can get a language with less ambiguities. I also happen to agree with Walter and you that it wouldn't be so great to just decorate functions with a keyword to give them a different syntax. I've propsed earlier a namespace-like syntax where you can have functions like "foo.opAssign" inside a class (or anywhere really) that you can call with "foo = x", unifying properties with operator overloading. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jul 28 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Michel Fortin wrote:
 On 2009-07-28 11:37:05 -0400, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> said:
 
 Michel Fortin wrote:
 On 2009-07-28 10:16:16 -0400, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> said:

 Well I don't think so. To repeat what I wrote elsethread: foo = bar 
 is rewritten into foo(bar) if and only if auto __x = foo, __x = bar 
 works. This means, a setter only works if there's a corresponding 
 getter. (Write-only properties be damned.)

This may lead to strange issues if both the setter and the getter don't have the same protection attribute, or purity, or constness of arguments. For instance: protected void foo(Object o); public pure const const(Object) foo(); Here, you can assign to foo using the property syntax only from a non-pure functions of this class or a derived classes and when the value you're assinging is a const(Object). Elsewhere, you can only assign using the function syntax. Anything else would break "auto __x = foo, __x = bar".

Well I chose the rule that makes bar look and feel as much as an assignable value as possible. The rule could be relaxed (e.g. by dropping qualifiers), but that means we're departing from assignable value lookalike.

Also, what if a derived class implements a getter while the base class only has a setter. Does that mean that only the derived class can use the property syntax on the base class' setter?

It all follows normal language rules. That's what I like about rewrites (lowerings): they allow you to reason about a new mini-feature (that in this case is absolutely nothing beyond a minor syntactic convenience) in terms of the rest of the language.
 What I don't like about that proposal is that that how to call a setter 
 is bound to the existence of another function in the same scope using 
 pretty non-obvious rules.

I think the rules are very obvious.
 Also, it doesn't solve the problem of the 
 getter that returns a delegate since you can continue using the function 
 notation with properties and you can continue to call functions with no 
 parenthesis.

It doesn't solve the problem with a getter that returns a delegate. People who want to return delegates must use an extra pair of parens.
 While I like too being able to call functions with no argument by 
 skipping the tailing parenthesis, I'd easily give up on that if it means 
 I can get a language with less ambiguities.

I wouldn't want to hurt the majority of my code for an obscure case. I do agree I'd rather not have an obscure case in the first place.
 I also happen to agree with Walter and you that it wouldn't be so great 
 to just decorate functions with a keyword to give them a different 
 syntax. I've propsed earlier a namespace-like syntax where you can have 
 functions like "foo.opAssign" inside a class (or anywhere really) that 
 you can call with "foo = x", unifying properties with operator overloading.

That would work. Many things would work. Andrei
Jul 28 2009
prev sibling next sibling parent reply Rainer Deyke <rainerd eldwood.com> writes:
Ary Borenszweig wrote:
 Maybe what scares Walter is a whole new syntax for properties. If at
 least you could say which functions are properties and which are not,
 that would be a small change and it'll make it possible for other
 things. Something like:
 
 int property foo(); // getter
 int property foo(int value); // setter

My proposal requires no new keywords and no new syntax: int getfoo(); // getter int setfoo(int); // setter -- Rainer Deyke - rainerd eldwood.com
Jul 24 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Rainer Deyke wrote:
 Ary Borenszweig wrote:
 Maybe what scares Walter is a whole new syntax for properties. If at
 least you could say which functions are properties and which are not,
 that would be a small change and it'll make it possible for other
 things. Something like:

 int property foo(); // getter
 int property foo(int value); // setter

My proposal requires no new keywords and no new syntax: int getfoo(); // getter int setfoo(int); // setter

This is pretty clean, and in keep with the opXxx approach. Actually how about defining property foo by defining opGet_foo and opSet_foo. Andrei
Jul 24 2009
next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2009-07-24 22:58:33 -0400, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 This is pretty clean, and in keep with the opXxx approach. Actually how 
 about defining property foo by defining opGet_foo and opSet_foo.

The problem with this is that it's ugly. What about this int foo.opGet(); // getter void foo.opAssign(int); // setter with some support from the compiler. It could even be exteded to support more: int foo.opIndex(int); // foo[1]; void foo.opAddAssign(int); / foo += 1; void foo.invert(); // special function attached to property -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jul 24 2009
parent Lutger <lutger.blijdestijn gmail.com> writes:
Michel Fortin wrote:

 On 2009-07-24 22:58:33 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> said:
 
 This is pretty clean, and in keep with the opXxx approach. Actually how
 about defining property foo by defining opGet_foo and opSet_foo.

The problem with this is that it's ugly. What about this int foo.opGet(); // getter void foo.opAssign(int); // setter with some support from the compiler. It could even be exteded to support more: int foo.opIndex(int); // foo[1]; void foo.opAddAssign(int); / foo += 1; void foo.invert(); // special function attached to property

There is a thread discussing the proposal which is also linked to by the wiki. Posting there would be useful, for future reference too.
Jul 24 2009
prev sibling parent Daniel Keep <daniel.keep.lists gmail.com> writes:
Andrei Alexandrescu wrote:
 Rainer Deyke wrote:
 Ary Borenszweig wrote:
 Maybe what scares Walter is a whole new syntax for properties. If at
 least you could say which functions are properties and which are not,
 that would be a small change and it'll make it possible for other
 things. Something like:

 int property foo(); // getter
 int property foo(int value); // setter

My proposal requires no new keywords and no new syntax: int getfoo(); // getter int setfoo(int); // setter

This is pretty clean, and in keep with the opXxx approach. Actually how about defining property foo by defining opGet_foo and opSet_foo. Andrei

Actually, if this became the "official" way of doing properties, that would solve the IDE and debugger issues and (hopefully) the parens thing. Which leaves only one issue: that writing properties violates DRY. So I wrote a basic Property generator. Full source is here: http://gist.github.com/154755 I know people hate mixins, but this approach would give us discoverability and a slightly terser syntax, without having to actually introduce new language syntax. And maybe if D ends up with enough of these mixins being used as standard, it'll spur Walter into adding macros. :D Examples from the code: struct S { mixin ( // Default accessor property with automatic private storage. Property!(int, "bar") // Public read-only w/ auto storage ~Property!(int, "baz", null, "private") // Public read-only with default ~Property!(int, "bop = 42", null, "private") // Read-only ~Property!(int, "qux", null, "-") // Fully custom; no auto storage created ~Property!(int, "zyz", q{ return 7; }, q{ // Note "magic" value argument writefln("Set zyz to: %s", value); }) // Fully custom with private setter and auto storage ~Property!(int, "gfh", q{ // Public here is optional public { return storage/100; } }, q{ private { storage = value*100; } }) ); }
Jul 25 2009
prev sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Mon, Jul 27, 2009 at 7:49 PM, Jarrett
Billingsley<jarrett.billingsley gmail.com> wrote:
 On Mon, Jul 27, 2009 at 7:33 PM, escalan<escalan gmail.com> wrote:
 Hi, I'm new here. A simple idea I've had is to simply use aliases for defining
properties.

 If you allow writing aliases as expressions, you have get properties. Then a
simple extension to the syntax would also allow for writing set properties.

 alias (a) property;
 alias (a = n) property(n);

 foo(property); // Get
 property = 32; // Set

 This virtually eliminates any problems with properties, and it doesn't require
any new keywords. It won't break existing aliases either.

Except if you want to do anything more complex in your setter/getter than a simple expression.

Also, if your suggestion really did just replace any accesses to the property with the aliased expression, there would be no way to override it in subclasses, it would be invisible to the debugger, etc.
Jul 27 2009
prev sibling next sibling parent reply Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
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
Jul 24 2009
next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Michiel Helvensteijn 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?
Jul 24 2009
next sibling parent Lutger <lutger.blijdestijn gmail.com> writes:
Walter Bright wrote:

 Michiel Helvensteijn 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?

A property contains information describing some object, which may or may not be mutable.
 2. How is that different from, say, a pure function?

A pure function is a computation without side effects: - does not have to relate to any one object - a mutable counterpart may not make any sense - it cannot have any side effects while that may make sense even for a getter (lazy load for example) - it does not have to *describe* an object in the sense that a property does The mechanism may be exactly the same, but a property gives a big hint to the programmer (and tools) as to what kind of thing you are dealing with. Extremely dumb example, all very much the same going from less to more nice: color(corvette, Color.Red); assert(color(corvette) == Color.Red); corvette.color(Color.Red); assert(corvette.color() == Color.Red) corvette.color = Color.Red; assert(corvette.color == Color.Red);
Jul 24 2009
prev sibling next sibling parent Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
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
Jul 24 2009
prev sibling parent Daniel Keep <daniel.keep.lists gmail.com> writes:
Walter Bright wrote:
 Michiel Helvensteijn 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?

A piece of state referred to by some name; state which is usually part of some object. Semantically the same as a field, except it may be more complex then just an address in memory. I'm going to fudge your next question a little... We've already established that pure functions won't cut it since they prevent you from doing lazy loads, or anything involving mutation (like tracking access counts). So let's pretend the question was:
 2. How is that different from, say, a function?

Which has a more interesting answer. :) In terms of machine code, nothing. This isn't a question about functionality, in the end, it's a question of intent. To reiterate: something like Qt depends pretty heavily on properties being distinct from functions. For example: T foo(); T foo(T); Is foo a property or a function? It's impossible to tell. It could be a function with two overloads, one of which requires an argument, or it could be a getter/setter pair. This causes a few problems. The first of which, and the one that I think is the most important, is it cripples IDEs and other graphical tools. Another example: I'm in the planning stages for a graphical editor that snaps together components. I'd love to be able to just introspect an object at runtime and grab all the properties, but I can't. I cannot determine, for certain, which methods are properties and which are REALLY methods, so I'll probably end up doing something like this: class Blah : Component { mixin(properties("a", "b", "c")); } To identify them. Of course, this isn't much use for a general IDE, unless this sort of thing becomes a standard in the language, and even then it's pretty hideous. Another problem is the issue with leaving off parens. The canonical example being: struct Foo { int delegate() bar(); } You have to put in *two* sets of parens to call the result from bar, not one as might be assumed. There's also the argument for debuggers being able to automatically display properties; I think this one is fairly borderline since if I was writing a debugger, it would only *automatically* display the result of pure functions, property or not. Finally, there's a speculative argument in that the current arrangement limits properties to having a getter and/or a setter. Andrei made a comment a while back about needing three primitives for them to work properly; in the current system. --- So basically, the issues are not *really* technical; they all boil down to ambiguity in terms of interpretation, or clumsy corner cases. To speak of the technical implementation of properties, my comments on DIP4 basically recommends to implement "new style" properties almost EXACTLY THE SAME as current ones; the difference is that "new style" properties have slightly more information available about them. I hope all that helps, although I suspect I'm just rambling at this point. :)
Jul 24 2009
prev sibling parent Walter Bright <newshound1 digitalmars.com> writes:
Steven Schveighoffer wrote:
 It's a good strategy for someone who's word is almost law when it comes 
 to D.  You have to be careful what you say, flip-flopping around only 
 leads to knee-jerk feature additions, more bikeshed discussions, and 
 more people clammoring for feature additions (hey, you added this, why 
 not that!).  I have great respect for the balance he has to deal with 
 between adding interesting features and keeping a sane spec.

I spent literally all day in this thread yesterday. Each reply I make spawns several replies from others. It's exponential. At some point, I have to just stop <g>.
Jul 24 2009
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Steven Schveighoffer wrote:
 On Fri, 24 Jul 2009 14:10:59 -0400, Walter Bright 
 <newshound1 digitalmars.com> wrote:
 That's my problem with properties as a distinct syntax - they don't 
 have distinct uses or behaviors.

If you delineate what can be called how, then you elminate syntax ambiguities from occurring, and eliminate bizarro cases of syntax. The difficulty is that the "human meaning" of a property is different than the human meaning of a function. To the compiler, they're all functions, so you as the compiler writer aren't seeing that they are different. I think we all agree that writefln = "hi"; makes absolutely no sense to a person. But it makes complete sense to the compiler, because it has no idea what the word "writefln" means to a person.

But when I suggest a restriction on properties, I get complaints that someone might want to have them do what functions do. So I fail to see what rule distinguishes them from functions, even for people.
 It's the exact same reason + is not the concatenation operator.  
 Semantically, making + concatenate two strings together would be 
 completely unambiguous from adding two integers together because strings 
 do not define addition, and integers do not define concatenation.  From 
 your own documentation, someone seeing "10" + 3 might think that he 
 would get 13 or "103".  Even if the compiler defines what "should" 
 happen, and the rules are unambiguous, it looks incorrect to the user.

Using + for concatenation is syntactically ambiguous with vector addition.
Jul 24 2009
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Walter Bright" <newshound1 digitalmars.com> wrote in message 
news:h4d9jt$1hq5$1 digitalmars.com...
 Steven Schveighoffer wrote:
 On Fri, 24 Jul 2009 14:10:59 -0400, Walter Bright 
 <newshound1 digitalmars.com> wrote:
 That's my problem with properties as a distinct syntax - they don't have 
 distinct uses or behaviors.

If you delineate what can be called how, then you elminate syntax ambiguities from occurring, and eliminate bizarro cases of syntax. The difficulty is that the "human meaning" of a property is different than the human meaning of a function. To the compiler, they're all functions, so you as the compiler writer aren't seeing that they are different. I think we all agree that writefln = "hi"; makes absolutely no sense to a person. But it makes complete sense to the compiler, because it has no idea what the word "writefln" means to a person.

But when I suggest a restriction on properties, I get complaints that someone might want to have them do what functions do. So I fail to see what rule distinguishes them from functions, even for people.

I'm not sure what restriction you're talking about, but here's the difference: Function: Abstracted to a Verb ("write" "sort" "play" "decompress") Property: Abstracted to a Noun/Adjective ("position" "width" "color" "turret" "ball") Variable: *Special case of Property*, where the *underlying storage* is never lazy at all and is always exactly the same as what's presented to the class's user. Here's another (psuedocode) way to describe the difference: Thing2D ball1, ball2; ball1.moveTo( [10, 7] ); // Function ball1.position = [10, 7]; // Property ball1.moveTo = [10, 7]; // Meaningless bullshit ball1.position( [10, 7] ); // Meaningless bullshit ball1.moveTo(ball2.position); // Sensible ball1.position = ball2.position; // Sensible ball1.moveTo(ball2.moveTo); // Meaningless bullshit ball1.position = ball2.moveTo; // Meaningless bullshit
 It's the exact same reason + is not the concatenation operator. 
 Semantically, making + concatenate two strings together would be 
 completely unambiguous from adding two integers together because strings 
 do not define addition, and integers do not define concatenation.  From 
 your own documentation, someone seeing "10" + 3 might think that he would 
 get 13 or "103".  Even if the compiler defines what "should" happen, and 
 the rules are unambiguous, it looks incorrect to the user.

Using + for concatenation is syntactically ambiguous with vector addition.

Are you saying that were it not for vector operations you would have used + for concatenation? If not, then you're dodging the point Steven is making.
Jul 25 2009
parent "Nick Sabalausky" <a a.a> writes:
"Nick Sabalausky" <a a.a> wrote in message 
news:h4eg2c$sn8$1 digitalmars.com...
 "Walter Bright" <newshound1 digitalmars.com> wrote in message 
 news:h4d9jt$1hq5$1 digitalmars.com...
 Steven Schveighoffer wrote:
 On Fri, 24 Jul 2009 14:10:59 -0400, Walter Bright 
 <newshound1 digitalmars.com> wrote:
 That's my problem with properties as a distinct syntax - they don't 
 have distinct uses or behaviors.

If you delineate what can be called how, then you elminate syntax ambiguities from occurring, and eliminate bizarro cases of syntax. The difficulty is that the "human meaning" of a property is different than the human meaning of a function. To the compiler, they're all functions, so you as the compiler writer aren't seeing that they are different. I think we all agree that writefln = "hi"; makes absolutely no sense to a person. But it makes complete sense to the compiler, because it has no idea what the word "writefln" means to a person.

But when I suggest a restriction on properties, I get complaints that someone might want to have them do what functions do. So I fail to see what rule distinguishes them from functions, even for people.

I'm not sure what restriction you're talking about, but here's the difference: Function: Abstracted to a Verb ("write" "sort" "play" "decompress") Property: Abstracted to a Noun/Adjective ("position" "width" "color" "turret" "ball") Variable: *Special case of Property*, where the *underlying storage* is never lazy at all and is always exactly the same as what's presented to the class's user. Here's another (psuedocode) way to describe the difference: Thing2D ball1, ball2; ball1.moveTo( [10, 7] ); // Function ball1.position = [10, 7]; // Property ball1.moveTo = [10, 7]; // Meaningless bullshit ball1.position( [10, 7] ); // Meaningless bullshit ball1.moveTo(ball2.position); // Sensible ball1.position = ball2.position; // Sensible ball1.moveTo(ball2.moveTo); // Meaningless bullshit ball1.position = ball2.moveTo; // Meaningless bullshit

With that ball/moveTo/position stuff, I should also clarify that for most of the code/languages across my programming career (save for the occasional cases of deliberate obfuscation and blatanty bad coding standards...oh, and asm of course ;) ) up until D, things have pretty much always worked like this: IDENTIFIER PARENS: Verb IDENTIFIER: Noun/Adjective And especially now, that's becoming more and more the standard convention. (And yea, I'm sure there's a bunch of languages from the 80's and before that were completely different...)
Jul 25 2009
prev sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
Walter Bright Wrote:

 Steven Schveighoffer wrote:
 On Fri, 24 Jul 2009 14:10:59 -0400, Walter Bright 
 <newshound1 digitalmars.com> wrote:
 That's my problem with properties as a distinct syntax - they don't 
 have distinct uses or behaviors.

If you delineate what can be called how, then you elminate syntax ambiguities from occurring, and eliminate bizarro cases of syntax. The difficulty is that the "human meaning" of a property is different than the human meaning of a function. To the compiler, they're all functions, so you as the compiler writer aren't seeing that they are different. I think we all agree that writefln = "hi"; makes absolutely no sense to a person. But it makes complete sense to the compiler, because it has no idea what the word "writefln" means to a person.

But when I suggest a restriction on properties, I get complaints that someone might want to have them do what functions do. So I fail to see what rule distinguishes them from functions, even for people.

The only thing that properties can't do that functions can is be called with parentheses. The only thing that functions cannot do that properties can is be called without parentheses (assuming properties are separated from functions) I fail to see any issues there. Where are these complaints you speak of? I've not seen any.
 It's the exact same reason + is not the concatenation operator.  
 Semantically, making + concatenate two strings together would be 
 completely unambiguous from adding two integers together because strings 
 do not define addition, and integers do not define concatenation.  From 
 your own documentation, someone seeing "10" + 3 might think that he 
 would get 13 or "103".  Even if the compiler defines what "should" 
 happen, and the rules are unambiguous, it looks incorrect to the user.

Using + for concatenation is syntactically ambiguous with vector addition.

OK, but assuming you didn't have vector addition (which you didn't have up until a few months ago), then how is this a different scenario than the property issue? Isn't it also ambiguous when you want to call a delegate/function returned from a property? Besides this, I like what another poster brought up better -- array indexing is the same as functions too, they take a single parameter, and return a value. So why do we have two different syntaxes for arrays and functions? Why do we have a special syntax for opIndex but no special syntax for properties? They're all functions, right? -Steve
Jul 25 2009
prev sibling next sibling parent reply Bill Baxter <wbaxter gmail.com> writes:
On Mon, Jul 27, 2009 at 7:13 AM, Steven
Schveighoffer<schveiguy yahoo.com> wrote:
 On Fri, 24 Jul 2009 17:40:37 -0400, Walter Bright
 <newshound1 digitalmars.com> wrote:

 Ary Borenszweig wrote:
 Maybe what scares Walter is a whole new syntax for properties.

It doesn't scare me. It's trivial to add more syntax. It's just that D is complex enough - there needs to be some very good reasons for adding more syntax that has apparently zero semantic information that would be different from the usual function syntax.

OK, so you don't like the idea of adding dedicated properties. What is *your* solution to forbidding abuses like this: writefln = "hi"; ???

I think his suggestion was the Java-style approach -- special naming convention for get/set functions: int opGet_foo() { return foo_; } void opSet_foo(int foo) { foo_ = foo; } private: int foo_; --bb
Jul 27 2009
parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Tue, Jul 28, 2009 at 03:07:34PM -0500, Andrei Alexandrescu wrote:
 To me, 
 the space-wasting and uncomfortable-to-type parens have always been 
 unpleasant noise.

For what it's worth, I agree with this. -- Adam D. Ruppe http://arsdnet.net
Jul 28 2009
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 27 Jul 2009 13:23:42 -0400, Bill Baxter <wbaxter gmail.com> wrote:

 On Mon, Jul 27, 2009 at 7:13 AM, Steven
 Schveighoffer<schveiguy yahoo.com> wrote:
 On Fri, 24 Jul 2009 17:40:37 -0400, Walter Bright
 <newshound1 digitalmars.com> wrote:

 Ary Borenszweig wrote:
 Maybe what scares Walter is a whole new syntax for properties.

It doesn't scare me. It's trivial to add more syntax. It's just that D is complex enough - there needs to be some very good reasons for adding more syntax that has apparently zero semantic information that would be different from the usual function syntax.

OK, so you don't like the idea of adding dedicated properties. What is *your* solution to forbidding abuses like this: writefln = "hi"; ???

I think his suggestion was the Java-style approach -- special naming convention for get/set functions: int opGet_foo() { return foo_; } void opSet_foo(int foo) { foo_ = foo; } private: int foo_;

Really? I got the impression that he does not think properties warrant any kind of special syntax. If that's the solution it's ok with me, the only issue is name collision (as others have mentioned): int opGet_foo() int foo; must be forbidden. This is different from other opX operators since the true names of those operators cannot be symbols, and therefore could never have collisions. -Steve
Jul 27 2009
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 27 Jul 2009 13:59:53 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Bill Baxter wrote:
 On Mon, Jul 27, 2009 at 7:13 AM, Steven
 Schveighoffer<schveiguy yahoo.com> wrote:
 On Fri, 24 Jul 2009 17:40:37 -0400, Walter Bright
 <newshound1 digitalmars.com> wrote:

 Ary Borenszweig wrote:
 Maybe what scares Walter is a whole new syntax for properties.

It's just that D is complex enough - there needs to be some very good reasons for adding more syntax that has apparently zero semantic information that would be different from the usual function syntax.

What is *your* solution to forbidding abuses like this: writefln = "hi"; ???

convention for get/set functions: int opGet_foo() { return foo_; } void opSet_foo(int foo) { foo_ = foo; } private: int foo_; --bb

For one thing I like that I now get to define empty() for a range and then call it with r.empty. I'd think it would be a small step backward if I had to define get_empty() or something instead.

The "getter" notation that currently exists only has a few minor problems. The most major of those problems is if the return value is a callable type, such as a delegate, you can't easily perform the call on the returned value. Being that it isn't very bad for the getter property, would it make sense to leave that functionality? That is: 1. A setter must be defined in the opSet_X(int x) form 2. A getter can be a function with no required arguments, but this getter should not return callable types 3. A getter can be defined in the opGet_X() form, and then using X() will be the eqivalent of opGet_X()(). There are small implications to leaving the existing getter syntax. Namely one can call a function not intended to be a getter in a property-like syntax, resulting in less-than-obvious code. Also, this distinction will be very hard to explain to newbies ("how come a getter is defined as x(), but a setter has to be opSet_x(...)?). The more I look at it, the more I like the keyword solution. I do find the C#-like syntax which groups properties together appealing, but I think you only absolutely need that if you are going to have context-keywords, which I DON'T think we need. I do find the whole construct of C# properties tedious to type. With a keyword attribute, you could even group your properties together to save on typing/ugliness: property { int x() {} void x(int n) {} bool empty() {} } -Steve
Jul 27 2009
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 27 Jul 2009 15:30:17 -0400, bearophile <bearophileHUGS lycos.com>  
wrote:

 Steven Schveighoffer:
 property
 {
     int x() {}
     void x(int n) {}
     bool empty() {}
 }

An alternative: property(x) { ... // or getter and/or setter }

No, that is a different proposal. All I was saying is if property is an attribute, then like other attributes (const, etc), code like this: property int x() {} property void x(int n) {} property bool empty() {} can be rewritten as above. -Steve
Jul 27 2009
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 27 Jul 2009 18:37:01 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Steven Schveighoffer wrote:
 The "getter" notation that currently exists only has a few minor  
 problems.  The most major of those problems is if the return value is a  
 callable type, such as a delegate, you can't easily perform the call on  
 the returned value.

Thanks for a very lucid analysis!

You're welcome :)
  Being that it isn't very bad for the getter property, would it make  
 sense to leave that functionality?  That is:
  1. A setter must be defined in the opSet_X(int x) form
 2. A getter can be a function with no required arguments, but this  
 getter should not return callable types

... with zero arguments.

No, callable types period. Note that this does not compile: class A { int delegate(int foo) wyda() { return delegate int(int foo) { return foo;}; } } int main(string[] args) { auto a = new A; auto b = a.wyda(5); // line 14 auto c = a.wyda()(5); return 1; } [steves steveslaptop files]$ dmd testme.d testme.d(14): Error: function testme.A.wyda () does not match parameter types (int) testme.d(14): Error: expected 0 arguments, not 1 commenting out line 14 compiles.
 3. A getter can be defined in the opGet_X() form, and then using X()  
 will be the eqivalent of opGet_X()().
  There are small implications to leaving the existing getter syntax.   
 Namely one can call a function not intended to be a getter in a  
 property-like syntax, resulting in less-than-obvious code.

This I don't agree with. I am very happy that I define popFront() as a method and then call it without parens.

Knowing that you can call functions without parens, seeing code like: r.popFront; it's obvious that popFront is a function, not a property. But, do you agree that this code looks less-than-obvious? auto x = flush; is flush a flag saying flushing should occur? is it a function that flushes something, and returns the success? I agree that the bizarre factor is not as bad as with setters, but it's still not as self-explanatory as if you know that something without parens must be a property for the compiler to accept it. Also, without a dedicated property syntax for setters, you have the problem mentioned above with callable types. At the very least you need the alternate syntax, the automagic properties for zero-arg functions are optional.
  Also, this distinction will be very hard to explain to newbies ("how  
 come a getter is defined as x(), but a setter has to be opSet_x(...)?).

I don't see that as a problem. You just explain that the trailing () is not necessary, and then you tell them to define opSet_x if they want to enable obj.x = y.

Perhaps. I admit that I don't have any real evidence to support my claim, but I don't think you do either ;)
 The more I look at it, the more I like the keyword solution.  I do find  
 the C#-like syntax which groups properties together appealing, but I  
 think you only absolutely need that if you are going to have  
 context-keywords, which I DON'T think we need.  I do find the whole  
 construct of C# properties tedious to type.
  With a keyword attribute, you could even group your properties  
 together to save on typing/ugliness:
  property
 {
    int x() {}
    void x(int n) {}
    bool empty() {}
 }

Not a fan, but this would work. I just don't see why I need to go through with it.

Let's separate this problem into two sections: 1. do we have to hint to the compiler that a function is a property or not? I think we do, otherwise, we have the strange setter anomalies, and the inability to return delegates from getters. If you think this is not the case, state your arguments and solutions to those problems. I don't think the compiler can tell if something is meant to be a property or not by looking at it. 2. Assuming #1 is true for either getters and/or setters, what should the hints be? This is more of a bikeshed issue, but there are some technical issues to consider (- = negative, + = positive): For an opSet style syntax (e.g. int opSet_foo()): - There is a possible conflict between opSet_foo and foo. Since it would be the only operator function where the calling syntax is also valid symbol. i.e. opAddAssign is called via +=, which can't be a valid symbol. The compiler absolutely has to forbid this, which might be tough to implement. - The meaning is a bit cryptic, kind of like opApply. I understand that it follows in line with other operators, so you might realize it is special, but it's not obvious that something is a property (this is really a bikeshed issue). + Because the function is of a different form than the property call, you can use it as a function easily. For example, easy to get a delegate to it, just &opSet_foo. + no changes to parser! No new keywords (some people value this, but I'm not really one of them) For a new keyword-style syntax (e.g. property int foo()): + Much easier for the compiler to resolve a conflict, since you are directly declaring the called symbol. + Easier to understand that foo is a property than with opSet_foo, and easier to know how to call it. - If you wanted to use the property as a function (for example, get a delegate to the property), it might be more difficult. For example, if a property is "property ref int foo()", &foo might give you the address of the returned value. I don't really know a great solution to this problem, maybe a cast? Maybe you forgo the ability to take the address of the return value, and just have it always be a delegate? - new keyword (some people might not like this, I don't really have a problem with it). + Easy to annotate groups of properties by enclosing them in an attribute block. ------ One more point. From my point of view, the readability of the code, and obvious meaning of the code to a user of the code is more important than the ease of development. I've always been a fan of verbose function names and variables which describe what the function/variable is rather than short easy to type names. For instance I loathe the module structure of phobos, simply because the module names are too terse. For me to try and find something, it's not obvious. So to that point, I think it's more important to make the readability and self-explanatory nature of properties better than to make them easier to declare. Remember, you only define them once, but you use them over and over. Where is it better to save time, on reading the docs or on writing the declaration? -Steve
Jul 28 2009
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 28 Jul 2009 10:16:16 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 I think inferring meaning from the presence or absence of "()" is rather  
 dicey.

Really? Then why name your functions things like empty, why not ex245, to make them look it up, making *sure* they know what the meaning is before they use it. As one other person stated, they thought empty() emptied a range. Being able to read code and understand what it means without resorting to documentation is the sign of a good choice of symbol names. The presence or absence of parens is a hard-coded accepted meaning of field vs. function. Properties build on this notion by making a virtual field that actually resolves to a function (but behaves like a field, and this is an important accepted meaning). However, D does not allow intuitive names to be paired with the intuitive meaning of the presense or absence of parens, because you can't enforce it! Remember my example with TimeSpans? People will infer meaning from the presense or absense of parens whether you think it's a good idea or not. You will never get away from it.
 Let's separate this problem into two sections:
  1. do we have to hint to the compiler that a function is a property or  
 not?
  I think we do, otherwise, we have the strange setter anomalies, and  
 the inability to return delegates from getters.

Well I don't think so. To repeat what I wrote elsethread: foo = bar is rewritten into foo(bar) if and only if auto __x = foo, __x = bar works. This means, a setter only works if there's a corresponding getter. (Write-only properties be damned.)

This is a band-aid fix, easily broken. int select(int timeoutMS = -1); // method on a socket, for example Hell, even my TimeSpan problem would still fail. Also you are forgoing the ability to have overloaded setters, which could be useful. Not to mention getters for delegates. -Steve
Jul 28 2009
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 28 Jul 2009 11:11:09 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Steven Schveighoffer wrote:
 On Tue, 28 Jul 2009 10:16:16 -0400, Andrei Alexandrescu  
 <SeeWebsiteForEmail erdani.org> wrote:

 I think inferring meaning from the presence or absence of "()" is  
 rather dicey.

ex245, to make them look it up, making *sure* they know what the meaning is before they use it.

I didn't say not to infer meaning from the name.

No, you're saying inferring meaning from parentheses is not a good idea. I think it's the same thing as saying that inferring the meaning from a function/field name is not a good idea (just in a more sarcastic way...). When you see parentheses, you infer function. When you don't you infer field/property. Note that I'm not just pulling this out of a hat, it's the way people already think, you should acknowledge that.
 As one other person stated, they thought empty() emptied a range.

Well it doesn't.

Exactly, so why do you think he thought that? Let's take someone who's used a language that uses () do denote a function, and no parens to denote a field (there are a few of them out there). Would that person ever think that x.empty; means "empty the contents of x"? The answer is no, not ever. Whether you like it or not or think it's dicey or not PEOPLE WILL INFER MEANING FROM PARENTHESES. I even do it, even though I *know* that it's dicey. I hate having to look up usages of things that make no sense because I have no idea what the code is doing. It's so much better when the meaning is clear from the code itself.
 Being able to read code and understand what it means without resorting  
 to documentation is the sign of a good choice of symbol names.

Sure.
 The presence or absence of parens is a hard-coded accepted meaning of  
 field vs. function.

I understand how some people want to derive meaning from obj.foo() versus obj.foo. I think they shouldn't in D. I mean D has had for years the behavior that you could drop the trailing empty parentheses.

And for years, there have been complaints about it. This will continuously be a thorn in the side of D adoption until it is resolved.
 Properties build on this notion by making a virtual field that actually  
 resolves to a function (but behaves like a field, and this is an  
 important accepted meaning).

Not quite. C# has allocated a language feature for properties. Yet they allow you to write write-only properties, which do NOT behave at all like fields

I'll give you that one, but that's an uncommon "because we can" case.
 and also read-only properties, which also don't behave like fields.

Ever heard of readonly fields? Yes, they exist in C#. Besides, that's one of the benefits of properties, you can do things that you can't do with fields, otherwise why have them?
 Guess what - they both behave like functions. So their properties are an  
 elaborate mechanism that is actually thoroughly unchecked, thus going  
 back to what you could do by calling functions. So why the hell did they  
 define the feature in the first place? Oh, for allowing people to write  
 a.foo() instead of a.foo. You know what, that's a bit disappointing for  
 an entire language feature.

No, they did it to *force* you to write a.foo instead of a.foo(), to make it more defined that foo is a field-like entity. There's a subtle, yet very important difference. They saw the implementation of properties in Java as a good thing, but Java relied on a social standard that a method that begins with get is a getter, a method that begins with set is a setter, and a method that begins with is is a boolean. C# provides a better way to convey that contract via properties. D's implementation looks to me like a quick hack so D can say "look, we have properties!" They don't provide any of the interface benefits that true properties do. Might as well go back to Java style, where you have to name your properties getX, setX or isX. But now, normal functions are corrupted with the ability to use them as properties.
 Well I don't think so. To repeat what I wrote elsethread: foo = bar is  
 rewritten into foo(bar) if and only if auto __x = foo, __x = bar  
 works. This means, a setter only works if there's a corresponding  
 getter. (Write-only properties be damned.)

int select(int timeoutMS = -1); // method on a socket, for example Hell, even my TimeSpan problem would still fail.

Well maybe you could change TimeSpan.

Lovely. Force the developer to rename his functions because D is too weak to allow defining a correct interface. You didn't even address the select example, I think that's a very compelling example of something that breaks your rule. My point is that your rule only works if you write code in a certain way, and I don't think that should be a determination of whether something is a property or not by the compiler, because the naming of functions is supposed to be up to the developer, not the spec. It's like a prejudice against certain coding styles without any good reason.
 Also you are forgoing the ability to have overloaded setters, which  
 could be useful.  Not to mention getters for delegates.

Wait, overloaded setters do NOT make the thing behave like a field, but you were stating how nice that is a few paragraphs ago! So what is it that you think is good?

Yes they do. It makes them behave like a variant field. e.g. x.timeout = 5.5; // set timeout to 5.5 seconds x.timeout = TimeSpan.seconds(5); // set timeout to 5 seconds exactly And what about getters for delegates? That problem is still unresolved by your rule. -Steve
Jul 28 2009
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 28 Jul 2009 12:30:00 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Steven Schveighoffer wrote:
  And for years, there have been complaints about it.  This will  
 continuously be a thorn in the side of D adoption until it is resolved.

Again, most complaints have been directed towards writeln = 5. I think that's the major problem to be resolved.

Yes, I agree. But there is also a subtle problem we can solve at the same time. You keep missing the point. Let me come at another angle. You can't view properties as some sort of enforcement by the compiler. The compiler is not guaranteeing that if you call something without parentheses, it doesn't execute arbitrary code, it has nothing to do with what the compiler guarantees. But the *meaning* that the author of the function wishes to convey is available via the requirement of parentheses or lack thereof. The author of the code is saying "I wrote this function as if it were a field." It's the same thing as function names. The compiler allows you to name your functions how you wish, and enforces that foo is different than bar. Why is this important? Because foo does something different than bar. And to a user, that's obvious, because in english foo means something different than bar. What if the compiler allowed you to call functions as long as what you typed was an unambiguous prefix of the function name. For example: struct S { int foo(); int flu(); int bar(); } This is valid code: S s; s.fl(); s.b(); // s.f(); // doesn't compile because its not unambiguous Why is this advantageous? Well, it saves you from having to type the whole function name. It's unambiguous, so there is no problems as far as the compiler is concerned, so its easily implemented. But why don't we have a wonderful time-saving feature like this? Because it would be a nightmare to read. You can change the implied english meaning of the function by just using its prefix. But the compiler doesn't care, because it has no idea what the english meaning of the words are, and it's satisfied that you made an unambiguous decision. Back to our problem at hand, by allowing one to call functions with or without parentheses you are not only changing the implied meaning of the function, but you have removed the ability of the author to convey that meaning with simply the requirement of parentheses. He has to explain "this is a property" through by making the function name reflect that fact, or be an ass and say "well you shouldn't assume things based on parentheses, look it up dummy!" Yes, if we solve the problem of setters, we have killed a huge wart on D, but why ignore the other warts?
 and also read-only properties, which also don't behave like fields.

that's one of the benefits of properties, you can do things that you can't do with fields, otherwise why have them?

So now C# has two ways of providing a readonly field. Doesn't quite look like an example to follow.

Just like D! struct S { const int readonlyfield; int readonlyproperty(); } Yes, that's right. readonly is analogous to const.
 Guess what - they both behave like functions. So their properties are  
 an elaborate mechanism that is actually thoroughly unchecked, thus  
 going back to what you could do by calling functions. So why the hell  
 did they define the feature in the first place? Oh, for allowing  
 people to write a.foo() instead of a.foo. You know what, that's a bit  
 disappointing for an entire language feature.

make it more defined that foo is a field-like entity.

Which is not, because it can execute arbitrary code that is not restricted in any way. How good a design is that? Back to semantics by convention? That's what I'm saying: if it could do anything, at least don't pretend it's anything special. It's a function!

I explained this above. I'll reiterate: The enforcement of "field-like" by the compiler is not the point of properties, the ability given to the author to document that fact is the point.
 There's a subtle, yet very important difference.  They saw the  
 implementation of properties in Java as a good thing, but Java relied  
 on a social standard that a method that begins with get is a getter, a  
 method that begins with set is a setter, and a method that begins with  
 is is a boolean.  C# provides a better way to convey that contract via  
 properties.

Why is C#'s way better?

It's less verbose, makes the code read better, allows you to avoid using functions to do everything. As another example, Java doesn't have operator overloading, so BigInteger is horrific to use, calling functions for each operation. So would you argue that C# or D with operator overloading isn't better because operators are just functions, why call them something else?
 D's implementation looks to me like a quick hack so D can say "look, we  
 have properties!"  They don't provide any of the interface benefits  
 that true properties do.

What are the interface benefits that "true" properties do? What is a "true" property? Something that could do anything. Surprise, that was already the charter of functions. Well thank you very much.

No. The interface benefits are explained above.
 Well maybe you could change TimeSpan.

weak to allow defining a correct interface.

Or maybe because her use of name was too ambiguous.

I want to use the parentheses or lack thereof as part of the human meaning for the function/property. Making them optional means I can't do that.
 You didn't even address the select example, I think that's a very  
 compelling example of something that breaks your rule.

I agree that that example reveals a problem. I also think that that problem could be solved, but I doubt that you'll be pleased.

I would be pleased, how can it be solved?
 My point is that your rule only works if you write code in a certain  
 way,

Your rule also works if you write code in a certain way.

But my way is orthogonal to writing normal functions. Your rule mistakenly identifies normal functions as properties.
 and I don't think that should be a determination of whether something  
 is a property or not by the compiler, because the naming of functions  
 is supposed to be up to the developer, not the spec.

opXxx are up to the spec.

Yes, and it is well established that opXxx shouldn't be used for arbitrary function names. But you are expanding that rule to basically any function name, which means all functions are subject to being misinterpreted by the compiler, no matter what you name them.
 It's like a prejudice against certain coding styles without any good  
 reason.

I don't see that. I more see a prejudice against dropping "()" when calling a function.

It's a sacrifice in the name of clarity.
 Also you are forgoing the ability to have overloaded setters, which  
 could be useful.  Not to mention getters for delegates.

Wait, overloaded setters do NOT make the thing behave like a field, but you were stating how nice that is a few paragraphs ago! So what is it that you think is good?


Then write a function that takes a variant instead of overloading.

I can live without overloading setters, I don't think it's a requirement, but it would be possible with my method. That's the only point I was trying to make. -Steve
Jul 28 2009
prev sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Fri, Jul 24, 2009 at 12:21 PM, Steven
Schveighoffer<schveiguy yahoo.com> wrote:
 On Fri, 24 Jul 2009 15:12:10 -0400, Ary Borenszweig <ary esperanto.org.ar=

 wrote:

 Maybe what scares Walter is a whole new syntax for properties. If at lea=


 you could say which functions are properties and which are not, that wou=


 be a small change and it'll make it possible for other things. Something
 like:

His point is that there are no benefits to the semantic meaning of the co=

 by declaring something a property. =A0It's still a function, still gets
 implemented by a function.

 It's like if you say functions can now be called like this:

 foo^arg

 But he's not getting that the compiler isn't the only one reading the cod=

 and D isn't the only language being used. =A0You are also using a person'=

 knowledge of math (x =3D y) and a person's native language. =A0At least t=

 native language, the compiler knows and cares nothing about, but the
 developer and user care greatly (and want the conventions enforced).

Another example: arrays are just functions too. So there's no real need for a distinct a[i] syntax. a(i) would work just fine (and is exactly what's used in Fortran and Matlab for array indexing). But we kind of like being able to see right away that something is intended to be indexing. It give the reader of the code a hint about the intended semantics. But of course the compiler can't enforce that every opIndex overload conforms to that. You could write an opIndex overload that prints to stdout. But generally people don't do that because that would be sending the wrong signal. Generally the opIndex overloads offer index-ing like behavior. --bb
Jul 24 2009
prev sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Fri, Jul 24, 2009 at 2:44 PM, Walter
Bright<newshound1 digitalmars.com> wrote:
 Michiel Helvensteijn 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?

""" Properties are members that provide a flexible mechanism to read, write, or compute the values of private fields. Properties can be used as though they are public data members, but they are actually special methods called accessors. This enables data to be accessed easily while still providing the safety and flexibility of methods. """ -- thanks MSDN
 2. How is that different from, say, a pure function?

Properties behave semantically like fields, but are implemented like functions enabling them to do arbitrary calculation on the side when the field is read from or written to. Pure functions are totally different. First, half of the property syntax is about mutating a state. That's obviously not pure. And on the get() side its returning the value of a mutable state, so again, not pure. --bb
Jul 24 2009
prev sibling next sibling parent reply Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
Walter Bright wrote:

 Aren't immutable and enum the same thing? At least to the programmer?

Not at all. How would you declare a type that is "pointer to immutable int" using an enum? Anyhow, there was a looong thread about this a year back or so.

Then perhaps you can get rid of enum and have only immutable. Well, I'm sure you have valid reasons to keep it (like actual enumeration). But it would just seem worthwhile to try to unify them.
 Contracts didn't hit paydirt, and so haven't gotten a lot of follow-on
 attention.

This is too bad. It was one of the features that I liked most about D when I first started using it.
 and I never heard of ranking functions. 

Yeah, they're called something different everywhere. I've seen them called loop variants or binding functions. It's the expression that strictly decreases each iteration and always remains non-negative. The existence of such an expression proves the eventual termination of the loop.
 * No control over their use by class designer: ANY member function with
 one or zero parameters may be called using 'property syntax'. This is not
 a good thing.

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.
 * No global properties: If I'm not mistaken, global functions can't be
 properties.

int foo() { return 3; } void main() { int x = foo; } works.

Aha. Then you may want to fix the documentation. http://d.puremagic.com/issues/show_bug.cgi?id=3204
 * Operator overloading (no fine control over comparison operators,

This is deliberate. Operator overloading should be restricted to implementing arithmetic like operations on objects, not completely different things like what iostreams, Spirit and Boost::regex do.

Arithmetic like operations like matrix multiplication (which is not commutative)?

I believe this is completely controllable with D.

Not if commutativity of the * operator is fixed. The documentation states that * is commutative, which in fact for integers it is. So if I overload * for matrices, for all the guarantees the docs give me, a D compiler might choose to swap the operands around (perhaps to get some memory alignment advantage), and the returned matrix would be incorrect.
 Perhaps you misunderstand. I was referring to the algorithm that first
 checks for a complete match, then tries the 'reverse overload', then
 tries the commutative call.

I did understand it. The alternative is Koenig Lookup, and the reason for its existence. Reverse operator overloading is a bit awkward, but the awkwardness is restricted to the class in which it appears. ADL (Koenig Lookup) spreads awkwardness everywhere.

Well, I suggest that there be NO reverse overloads, that an overload should be possible in the global scope with the class giving it access to its private members (C++ uses 'friend', but there must be more elegant ways), lifting the 'this' restriction that prompted reverse overloads. I don't know exactly what Koenig Lookup is, but from what I read on Wikipedia, it involves arbitrary access to other namespaces, which seems unnecessary. Otherwise it sounds like regular function overloading based on its parameter types, which D supports, of course. Though I haven't read it through in detail.
 For && and ||, they are "short circuit" operators, and how that
 would 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.

Oops, you're right. Here's an old thread about it: http://www.digitalmars.com/d/archives/digitalmars/D/18153.html I 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
Jul 23 2009
parent Don <nospam nospam.com> writes:
Michiel Helvensteijn wrote:
 * Operator overloading (no fine control over comparison operators,

This is deliberate. Operator overloading should be restricted to implementing arithmetic like operations on objects, not completely different things like what iostreams, Spirit and Boost::regex do.

commutative)?


Not if commutativity of the * operator is fixed. The documentation states that * is commutative, which in fact for integers it is. So if I overload * for matrices, for all the guarantees the docs give me, a D compiler might choose to swap the operands around (perhaps to get some memory alignment advantage), and the returned matrix would be incorrect.

That's not what the documentation means. * is only 'default commutative'. If a.opMul(b) is defined, by default you get b * a == a*b. To prevent this behaviour, you just need to define a.opMul_r(b), or b.opMul(a). (The documenation could be a bit clearer on this).
Jul 24 2009
prev sibling next sibling parent Lutger <lutger.blijdestijn gmail.com> writes:
Walter Bright wrote:

 Michiel Helvensteijn wrote:

 * No control over their use by class designer: ANY member function with
 one or zero parameters may be called using 'property syntax'. This is not
 a good thing.

Why not? Seriously, what is the semantic difference?

The major point about properties is imo not a semantic issue at all, it's about signalling the intention (much like the debug version statement is). This is also key to integration with tools like IDE and it's usefulness in gui programming.
Jul 23 2009
prev sibling next sibling parent reply Leandro Lucarella <llucax gmail.com> writes:
Walter Bright, el 23 de julio a las 12:11 me escribiste:
* Tuples (no dedicated syntax, no parallel assignment, no non-flattening
tuples without workarounds, no returning tuples)

library support.


Of course that's true, but why is a dedicated syntax better than Tuple!( ...) ?

When I see this, I think about this: for (std::vector<int>::const_iterator i = v.begin(); i != v.end(); ++i) { int x = *i; ... } Why is foreach (x; v) ... better than the former? The problem is, if is hard to write, or ugly to read, people won't use it, or will use it less. In Python tuples are easy to read and write, so people use them everywhere and they are really useful (especially for FP-style programming, where is more common to return multple values). I think that library tuple *implementation* is a great idea (like library dynamic and associative arrays implementations), but not having support in the language for tuples is bad (like it will be not to have dynamic and associative arrays). I think the 3 are very fundamental types and deserves language support. -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- <original> [Penis Uptime: 2days 13hrs 59mins 35secs] <Yapa> viagra? :) <original> yea, 20 pills
Jul 23 2009
parent reply Walter Bright <newshound1 digitalmars.com> writes:
Leandro Lucarella wrote:
 The problem is, if is hard to write, or ugly to read, people won't use it,
 or will use it less. In Python tuples are easy to read and write, so
 people use them everywhere and they are really useful (especially for
 FP-style programming, where is more common to return multple values).

That is a good point. I won't say I'm convinced for the tuple case <g>, but it is a good argument.
Jul 23 2009
parent Leandro Lucarella <llucax gmail.com> writes:
Walter Bright, el 23 de julio a las 17:42 me escribiste:
 Leandro Lucarella wrote:
The problem is, if is hard to write, or ugly to read, people won't use it,
or will use it less. In Python tuples are easy to read and write, so
people use them everywhere and they are really useful (especially for
FP-style programming, where is more common to return multple values).

That is a good point. I won't say I'm convinced for the tuple case <g>, but it is a good argument.

I can't believe it, I actually made Walter think something twice! =P -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- CAMPA√ĎA POR LA PAZ: APLASTARON JUGUETES B√ČLICOS -- Cr√≥nica TV
Jul 24 2009
prev sibling next sibling parent reply Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
Walter Bright wrote:
 Of course that's true, but why is a dedicated syntax better than Tuple!( 
 ...) ?

Why is dedicated syntax for comma expressions better than commaExpr(...) ? I take it most folks on this NG would prefer to have shorter syntax for tuples instead the virtually never used comma expressions. Other than that, you need Tuple!(...) for type tuples, some sorta STuple!(...) for struct-tuples (so they can be nested and passed around properly) and makeTuple(...) for struct-tuple instances. Comma expressions don't even have to be first-class members of the language: ---- import tango.io.Stdout; T[$-1] commaExpr(T ...)(lazy T t) { foreach (x; t[0..$-1]) { auto y = x; } return t[$-1]; } T[0] revCommaExpr(T ...)(lazy T t) { foreach_reverse (x; t[1..$]) { auto y = x; } return t[0]; } void main() { { int x; int y = revCommaExpr(x += 123, x *= 2, Stdout.formatln("{}", x), Stdout("omg").newline); assert (y == 123); } { int x; commaExpr(x += 123, x *= 2, Stdout.formatln("{}", x), Stdout("omg")).newline; } } ---- Output: omg 0 246 omg ---- -- Tomasz Stachowiak http://h3.team0xf.com/ h3/h3r3tic on #D freenode
Jul 23 2009
next sibling parent reply Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
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
Jul 23 2009
next sibling parent Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
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
Jul 23 2009
prev sibling next sibling parent reply Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
Adam D. Ruppe wrote:
 On Fri, Jul 24, 2009 at 12:03:37AM +0200, Michiel Helvensteijn wrote:
 Would you look at this page and give me your opinion?

Looking at it quickly, the big difference seems to be you leave the tuple word off, and use them in more places. Is Tuple!(int, bool) A = tuple(a, b) really that much worse than: (int, bool) A = (a, b) ? Better yet, of course is: auto A = tuple(a, b);

It's not much worse, but it's not everything that's to tuples. Here's one more example:
 int a, b;

----
 a, b = 2, 3;

Can't do it with tuple(a, b) = tuple(2, 3); One would have to create yet another helper function, e.g.
 ptuple(&a, &b) = tuple(2, 3);

Or perhaps something with 'ref' instead of pointers, but I remember it being buggy with tuples, and might be too dangerous, since you wouldn't see that you're passing pointers around -- Tomasz Stachowiak http://h3.team0xf.com/ h3/h3r3tic on #D freenode
Jul 23 2009
next sibling parent Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
Adam D. Ruppe wrote:
 (...) It is two brief lines longer to copy them to a local x and y if you want
to.

Remember delegate literals? They were just a few more tokens, but it wasn't until the shorthand syntax was introduced that everyone started using them. I mean, how hard is it to type the extra 'delegate' and perhaps a return type after it... -- Tomasz Stachowiak http://h3.team0xf.com/ h3/h3r3tic on #D freenode
Jul 23 2009
prev sibling parent reply Leandro Lucarella <llucax gmail.com> writes:
Adam D. Ruppe, el 23 de julio a las 22:56 me escribiste:
 On Fri, Jul 24, 2009 at 01:38:30AM +0000, Jesse Phillips wrote:
 Thanks for the tutorial, expect to see it on Wiki4D within a year :D

This actually doesn't /quite/ work, since the tuple returned by tuple() has unnamed fields, which is a different type than the one with named fields. Gah. This works though: auto getPoint() { return Tuple!(int, "x", int, "y")(5, 2); } That's getting a wee bit ugly even for my likes, but is the best way for correctness and ease of use on the calling end. Or Tuple!(int, int) getPoint() { return tuple(5,2); } That works, but then you have to address the return value as: auto p = getPoint(); p.field[0] == 5 p.field[1] == 2 Still, easy enough to say: auto x = p.field[0]; auto y = p.field[1]; x == 5 y == 2

And you still think that's not remarkably worse than something like: (int, int) getPoint() { return (5, 2); } auto (x, y) = getPoint(); I really think that's the difference between happily using tuples or curse them for the rest of your life :) I don't think comma expressions should be used for tuples (I don't care much either), but you can add support to the language without breaking them using something like (1, 2, 3) or ![ 1, 2, 3 ] or whatever. But you should support multple assignment, for example. If you don't, you don't have real tuple support, just a toy tuple emulation. -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- We're rotten fruit We're damaged goods What the hell, we've got nothing more to lose One gust and we will probably crumble We're backdrifters
Jul 24 2009
parent reply Leandro Lucarella <llucax gmail.com> writes:
Jesse Phillips, el 25 de julio a las 03:38 me escribiste:
 But you should support multple assignment, for example. If you don't,
 you don't have real tuple support, just a toy tuple emulation.

Tuples have nothing to do with multiple assignment, it is just something languages tend to provide.

It has, providing tuples without that generally doesn't need language support, like D or C++ tuples. When you have multiple assignment, you can fully use the power of tuples, if not, it's just syntax sugar for structs, or some kind of limited list. Tuples are much more useful when are a *language construct*. -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- Dale tu mano al mono, pero no el codo, dado que un mono confianzudo es irreversible. -- Ricardo Vaporeso. La Reja, Agosto de 1912.
Jul 25 2009
parent reply Rainer Deyke <rainerd eldwood.com> writes:
Leandro Lucarella wrote:
 It has, providing tuples without that generally doesn't need language
 support, like D or C++ tuples. When you have multiple assignment, you can
 fully use the power of tuples, if not, it's just syntax sugar for structs,
 or some kind of limited list.

From the Boost.Tuple documentation: int i; char c; double d; tie(i, c, d) = make_tuple(1,'a', 5.5); std::cout << i << " " << c << " " << d; So C++ tuples *do* support multiple assignment, even without language support. Still not as nice as the Python syntax, though. -- Rainer Deyke - rainerd eldwood.com
Jul 25 2009
parent Leandro Lucarella <llucax gmail.com> writes:
Rainer Deyke, el 25 de julio a las 13:20 me escribiste:
 Leandro Lucarella wrote:
 It has, providing tuples without that generally doesn't need language
 support, like D or C++ tuples. When you have multiple assignment, you can
 fully use the power of tuples, if not, it's just syntax sugar for structs,
 or some kind of limited list.

From the Boost.Tuple documentation: int i; char c; double d; tie(i, c, d) = make_tuple(1,'a', 5.5); std::cout << i << " " << c << " " << d; So C++ tuples *do* support multiple assignment, even without language support. Still not as nice as the Python syntax, though.

But you have to split declaration from initialization. That's not nice. -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- Yo soy Peperino Mártir Sanito, yo soy aquel, que come los flanes serenito. -- Peperino Pómoro
Jul 25 2009
prev sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Sat, Jul 25, 2009 at 01:20:33PM -0600, Rainer Deyke wrote:
From the Boost.Tuple documentation:

int i; char c; double d; tie(i, c, d) = make_tuple(1,'a', 5.5); std::cout << i << " " << c << " " << d; So C++ tuples *do* support multiple assignment, even without language support. Still not as nice as the Python syntax, though.

I think I like that. -- Adam D. Ruppe http://arsdnet.net
Jul 25 2009
prev sibling parent bearophile <bearophileHUGS lycos.com> writes:
Adam D. Ruppe:

 Why is dedicated syntax for comma expressions better than commaExpr(...)?
What do you propose we do about the commas in loops? Breaking them would be a
pretty big change to the C folks.<

Disallowing bad usages of commas is a starting point. for() can become a special case. Handy syntax for tuple unpacking is useful in many situations, look at Python code. Bye, bearophile (Late answer, sorry, I was away)
Jul 27 2009
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
 no overloading of !, &&, ||,

What bothers me about overloading && and || is they are control flow constructs, not really "operators". For example, ?: is also a control flow operator, and it sensibly isn't overloadable in C++. What if you could overload if..else.. statements? I'm sure someone somewhere could find a use for that, but it's still not a good idea.
Jul 23 2009
parent Daniel Keep <daniel.keep.lists gmail.com> writes:
Walter Bright wrote:
 
 no overloading of !, &&, ||,

What bothers me about overloading && and || is they are control flow constructs, not really "operators". For example, ?: is also a control flow operator, and it sensibly isn't overloadable in C++. What if you could overload if..else.. statements? I'm sure someone somewhere could find a use for that, but it's still not a good idea.

Ask downs about that one :3
Jul 24 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Thu, Jul 23, 2009 at 3:13 PM, Steven
Schveighoffer<schveiguy yahoo.com> wrote:
 Can you do that with classes, I don't know. =A0I thought it was impossibl=

 allocate several classes in one block. =A0It was pretty easy to do the cu=

 allocator with structs...

Ah, that's a good point. It is in fact possible; you can use typeid(Class).classinfo.init.length to get the size of an instance at runtime, or with D2, __traits(classInstanceSize, Class) will get you the same thing, at compile time. Though your other reasons are certainly more than enough justification to move to structs (which, like you said, they probably should have been in the first place) :)
Jul 23 2009
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Fri, Jul 24, 2009 at 01:38:30AM +0000, Jesse Phillips wrote:
 Thanks for the tutorial, expect to see it on Wiki4D within a year :D

This actually doesn't /quite/ work, since the tuple returned by tuple() has unnamed fields, which is a different type than the one with named fields. Gah. This works though: auto getPoint() { return Tuple!(int, "x", int, "y")(5, 2); } That's getting a wee bit ugly even for my likes, but is the best way for correctness and ease of use on the calling end. Or Tuple!(int, int) getPoint() { return tuple(5,2); } That works, but then you have to address the return value as: auto p = getPoint(); p.field[0] == 5 p.field[1] == 2 Still, easy enough to say: auto x = p.field[0]; auto y = p.field[1]; x == 5 y == 2 -- Adam D. Ruppe http://arsdnet.net
Jul 23 2009
prev sibling next sibling parent Jesse Phillips <jessekphillips gmail.com> writes:
On Thu, 23 Jul 2009 22:56:44 -0400, Adam D. Ruppe wrote:

 On Fri, Jul 24, 2009 at 01:38:30AM +0000, Jesse Phillips wrote:
 Thanks for the tutorial, expect to see it on Wiki4D within a year :D

This actually doesn't /quite/ work, since the tuple returned by tuple() has unnamed fields, which is a different type than the one with named fields. Gah. This works though: auto getPoint() { return Tuple!(int, "x", int, "y")(5, 2); } That's getting a wee bit ugly even for my likes, but is the best way for correctness and ease of use on the calling end. Or Tuple!(int, int) getPoint() { return tuple(5,2); } That works, but then you have to address the return value as: auto p = getPoint(); p.field[0] == 5 p.field[1] == 2 Still, easy enough to say: auto x = p.field[0]; auto y = p.field[1]; x == 5 y == 2

Thanks, truth be told I don't know why that first one works. But the second looks completely reasonable.
Jul 23 2009
prev sibling parent Jesse Phillips <jessekphillips gmail.com> writes:
On Fri, 24 Jul 2009 12:30:23 -0300, Leandro Lucarella wrote:

 Adam D. Ruppe, el 23 de julio a las 22:56 me escribiste:

 Tuple!(int, int) getPoint() { return tuple(5,2); }
 
 That works, but then you have to address the return value as:
 
 auto p = getPoint();
 p.field[0] == 5
 p.field[1] == 2
 
 
 Still, easy enough to say:
 
 auto x = p.field[0]; auto y = p.field[1]; x == 5
 y == 2

And you still think that's not remarkably worse than something like: (int, int) getPoint() { return (5, 2); } auto (x, y) = getPoint();

I would say it isn't remarkably worse. The other one though, that was quite a mess.
 I really think that's the difference between happily using tuples or
 curse them for the rest of your life :)
 
 I don't think comma expressions should be used for tuples (I don't care
 much either), but you can add support to the language without breaking
 them using something like  (1, 2, 3) or ![ 1, 2, 3 ] or whatever.
 
 But you should support multple assignment, for example. If you don't,
 you don't have real tuple support, just a toy tuple emulation.

Tuples have nothing to do with multiple assignment, it is just something languages tend to provide.
Jul 24 2009
prev sibling next sibling parent reply Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Wed, Jul 22, 2009 at 5:10 PM, Michiel
Helvensteijn<m.helvensteijn.remove gmail.com> wrote:

 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.

Ha. Had D differed *too* much from C++, then we'd run the risk of scaring off the C++ snobs simply because it wasn't familiar enough to them. You can never please C++ users with another language. Let's not get hung up on attracting them.
Jul 22 2009
parent Walter Bright <newshound1 digitalmars.com> writes:
Jarrett Billingsley wrote:
 Ha.  Had D differed *too* much from C++, then we'd run the risk of
 scaring off the C++ snobs simply because it wasn't familiar enough to
 them.

It's a good point. Radically different languages tend to fail simply because few are willing to expend the effort to learn it. This is why Haskell will never catch on.
 You can never please C++ users with another language.  Let's not get
 hung up on attracting them.

C++ will be around and will be used as long as any of us are alive, no matter what. It's just a fact of life.
Jul 22 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Wed, Jul 22, 2009 at 6:30 PM, Walter
Bright<newshound1 digitalmars.com> wrote:

 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.

This is EXACTLY the point I always try to make to newcomers. It's so significant that I think it should be on the front page of the language spec, in bold, 72 point, red letters.
Jul 22 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Wed, Jul 22, 2009 at 3:59 PM, Jarrett
Billingsley<jarrett.billingsley gmail.com> wrote:
 On Wed, Jul 22, 2009 at 6:30 PM, Walter
 Bright<newshound1 digitalmars.com> wrote:

 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=


 back to another language.

This is EXACTLY the point I always try to make to newcomers. =A0It's so significant that I think it should be on the front page of the language spec, in bold, 72 point, red letters.

Yeh, it's like what's the big diff between a Lamborghini and a Chevy Nova anyway? They both have four tires. They both run on gas. So what's all the fuss about the Lamborghini? --bb
Jul 22 2009
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wed, Jul 22, 2009 at 06:59:45PM -0400, Jarrett Billingsley wrote:
 On Wed, Jul 22, 2009 at 6:30 PM, Walter
 Bright<newshound1 digitalmars.com> wrote:
 
 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.

This is EXACTLY the point I always try to make to newcomers.

Agreed. This is the big benefit, but the hard part is that it takes some experience to really realize it. How can we sell that to someone who doesn't have that experience using it? "Just take my word for it" doesn't mean much when coming from strangers on the Internet, or from the site's homepage. -- Adam D. Ruppe http://arsdnet.net
Jul 22 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Wed, Jul 22, 2009 at 4:19 PM, Adam D. Ruppe<destructionator gmail.com> wrote:
 On Wed, Jul 22, 2009 at 06:59:45PM -0400, Jarrett Billingsley wrote:
 On Wed, Jul 22, 2009 at 6:30 PM, Walter
 Bright<newshound1 digitalmars.com> wrote:

 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.

This is EXACTLY the point I always try to make to newcomers.

Agreed. This is the big benefit, but the hard part is that it takes some experience to really realize it. How can we sell that to someone who doesn't have that experience using it? "Just take my word for it" doesn't mean much when coming from strangers on the Internet, or from the site's homepage.

Even that does have a cumulative effect, though. If you keep hearing "take my word for it" from different sources, eventually, if you have any curiousity at all, you'll want to check it out for yourself. --bb
Jul 22 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Wed, Jul 22, 2009 at 10:00 PM, Andrei
Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:
 Or like driving an American car vs. a Japanese or European car.

Yeah, what *is* the deal with that? In terms of little convenience features, American cars feel outright primitive compared to Japanese and European cars.. Sorry for the OT :P
Jul 22 2009
prev sibling next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Michiel Helvensteijn" <m.helvensteijn.remove gmail.com> wrote in message 
news:h47v8p$131i$1 digitalmars.com...
 D just doesn't offer enough improvements over C++ to make it worthwhile
 switching over.

Even as a former die-hard C/C++ user, I've never really understood this argument. But, I'm not in the "you have to try it / sum of it's parts" camp either... Better is just plain better. If you've got two things available, and one is better, it just doesn't make any sense to stick with the worse one if the only reason to do so is inertia. That would be plain laziness. All of the following *individually* (ie, not just as a lump sum) are things for which I've always considered well worth leaving C/C++ in the history books where it belongs: - No separate header/implementation files. (IMO, the king of all language anachronisms.) - Non-null-terminated, slicable strings. - Strong typing (Unless things have changed since I last looked, I refuse to accept C/C++ as *truly* strong-typed. Hell, most modern dynamic languages have more right to be called strongly-typed than C/C++.) - True delegates and function literals. - A sensible foreach instead of that horrid stl iterator mess. (And this opinion of mine was formed long before Andrei's ranges.) - Metaprogramming that isn't a kludge (I'm looking at both the C preprocessor and the use of C++'s templates for anything beyond mere generics). - The availability of build tools that make manual dependency-tracking (not to mention those god-awful "*make" programs) obsolete. - "finally" (Or does C++ have this now too?) which fixes a fatal flaw in old-style exception handling (not to mention scope guards which even make "finally" look primitive, at least where applicable). If you have any of these available, why *not* use them? Sure, D has it's well-known issues, but they're nothing compared to any of the above problems with C/C++. Hell, the last few times I used C/C++, the *only* reason was because it was the only viable systems language I was aware of.
Jul 22 2009
next sibling parent Rainer Deyke <rainerd eldwood.com> writes:
Nick Sabalausky wrote:
 All of the following *individually* (ie, not just as a lump sum) are things 
 for which I've always considered well worth leaving C/C++ in the history 
 books where it belongs:

And if D had just one of these features, plus all of the useful features of C++, then I would be using D instead of C++. But every time I find that a useful C++ idiom has no equivalent in D (and every time D introduces a new wart on top of the ones it inherits from C++), I am knocked back into C++ land. -- Rainer Deyke - rainerd eldwood.com
Jul 22 2009
prev sibling next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Nick Sabalausky wrote:
 Better is just plain better. If you've got two things available, and one is 
 better, it just doesn't make any sense to stick with the worse one if the 
 only reason to do so is inertia. That would be plain laziness.

It does take time and effort to learn a new tool, and that effort needs to be less than the expected gain.
 All of the following *individually* (ie, not just as a lump sum) are things 
 for which I've always considered well worth leaving C/C++ in the history 
 books where it belongs:
 
 - No separate header/implementation files. (IMO, the king of all language 
 anachronisms.)
 
 - Non-null-terminated, slicable strings.
 
 - Strong typing (Unless things have changed since I last looked, I refuse to 
 accept C/C++ as *truly* strong-typed. Hell, most modern dynamic languages 
 have more right to be called strongly-typed than C/C++.)
 
 - True delegates and function literals.
 
 - A sensible foreach instead of that horrid stl iterator mess. (And this 
 opinion of mine was formed long before Andrei's ranges.)
 
 - Metaprogramming that isn't a kludge (I'm looking at both the C 
 preprocessor and the use of C++'s templates for anything beyond mere 
 generics).
 
 - The availability of build tools that make manual dependency-tracking (not 
 to mention those god-awful "*make" programs) obsolete.
 
 - "finally" (Or does C++ have this now too?) which fixes a fatal flaw in 
 old-style exception handling (not to mention scope guards which even make 
 "finally" look primitive, at least where applicable).

My experience with C++ people sticking with it is they are so used to the problems they no longer see them. To me it's like the mess in one's house. One doesn't notice it until going on a vacation (i.e. learning a another language), having one's hotel room cleaned every day, then coming home and suddenly seeing how untidy it is <g>.
 If you have any of these available, why *not* use them? Sure, D has it's 
 well-known issues, but they're nothing compared to any of the above problems 
 with C/C++. Hell, the last few times I used C/C++, the *only* reason was 
 because it was the only viable systems language I was aware of.

The bizarre arguments I've seen are along the lines of "I don't want to use D because although it has X and Y which I love, it doesn't have Z and I really need Z", so they use C++ (or Java or C# or Python) which doesn't have X, Y, or Z.
Jul 22 2009
next sibling parent reply Rainer Deyke <rainerd eldwood.com> writes:
Walter Bright wrote:
 My experience with C++ people sticking with it is they are so used to
 the problems they no longer see them. To me it's like the mess in one's
 house. One doesn't notice it until going on a vacation (i.e. learning a
 another language), having one's hotel room cleaned every day, then
 coming home and suddenly seeing how untidy it is <g>.

I want to throw these words back at you, because my first impression of D was "the bastard child of C++ and Java, with a random assortment of new features thrown in without rhyme or reason". D is many things, but a simple and elegant language it is not. (This is not a major problem to me, really. I can live with messy languages. I can live with C++. But to think that D is a massive improvement in this area requires a special sort of perspective.) The reason I have stuck with C++ despite its (massive, obvious) flaws is that it has a couple of really nice and useful features that very few other languages have even attempted to match. D is the only language I know that even tries, although it still falls short in many areas. -- Rainer Deyke - rainerd eldwood.com
Jul 22 2009
next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Rainer Deyke wrote:
 I want to throw these words back at you, because my first impression of
 D was "the bastard child of C++ and Java, with a random assortment of
 new features thrown in without rhyme or reason".  D is many things, but
 a simple and elegant language it is not.  (This is not a major problem
 to me, really.  I can live with messy languages.  I can live with C++.
 But to think that D is a massive improvement in this area requires a
 special sort of perspective.)

One measure of messy language semantics is the messiness of the compiler code needed to deal with it. D is a pretty clean language in comparison. <g> Another way is measuring the change in source code size. I get about a 30% reduction when translating C++ code more or less directly to D. Yes, I think it is a massive improvement over C++ in simplicity and elegance. But if you try to write C++ code in D, you won't see as much of that as you would after being more used to the D way of doing things. For example, my early C code looked an awful lot like Fortran! It took a while before I used the language in a style that was natural for C. My first years of C++ code also looked a lot like just plain old C (in fact, it arguably still does).
 The reason I have stuck with C++ despite its (massive, obvious) flaws is
 that it has a couple of really nice and useful features that very few
 other languages have even attempted to match.  D is the only language I
 know that even tries, although it still falls short in many areas.

Fair enough. What are those two features?
Jul 23 2009
parent reply Rainer Deyke <rainerd eldwood.com> writes:
Walter Bright wrote:
 Rainer Deyke wrote:
 The reason I have stuck with C++ despite its (massive, obvious) flaws is
 that it has a couple of really nice and useful features that very few
 other languages have even attempted to match.  D is the only language I
 know that even tries, although it still falls short in many areas.

Fair enough. What are those two features?

1. C++'s object model, complete with polymorphic value types, deterministic destructors, arbitrary copy constructors, and optional lack of default constructor. D's structs come close, but I think the class/struct split hurts D more than it helps. And, yes, C++ has a lot of room for improvement here. 2. Templates. And this is one area that D improves in a major way. I love static if. -- Rainer Deyke - rainerd eldwood.com
Jul 23 2009
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Rainer Deyke wrote:
 Walter Bright wrote:
 Rainer Deyke wrote:
 The reason I have stuck with C++ despite its (massive, obvious) flaws is
 that it has a couple of really nice and useful features that very few
 other languages have even attempted to match.  D is the only language I
 know that even tries, although it still falls short in many areas.


1. C++'s object model, complete with polymorphic value types,

What designs make good use of polymorphic value types?
 deterministic destructors,  arbitrary copy constructors, and optional
 lack of default constructor.

Struct have that except for default constructor. In D, currently default constructors cannot execute code. This is a limitation that we might need to address, although it has some advantages.
 D's structs come close, but I think the
 class/struct split hurts D more than it helps.  And, yes, C++ has a lot
 of room for improvement here.

How does the class/struct split? I think it's an enormous source of confusion for C++. C++ lore clarifies that you must decide in day one whether a class is meant to be polymorphic or monomorphic. Unfortunately that can't be expressed in the language, hence the weird cases with deriving from std::vector or getting polymorphic values unceremoniously sliced. Avoiding such mistakes are important things that C++ users must learn because there's nothing in the language stopping them from doing such nonsensical things; D very elegantly breaks that pattern by defining the language to only allow meaningful constructs. Who says the class/struct situation is worse off in D than in C++ either doesn't know C++ or knows C++ too well. Andrei
Jul 23 2009
parent reply Rainer Deyke <rainerd eldwood.com> writes:
Andrei Alexandrescu wrote:
 Rainer Deyke wrote:
 1. C++'s object model, complete with polymorphic value types,

What designs make good use of polymorphic value types?

In a way, that's a loaded question, since C++ classes don't stay polymorphic when passed around by value. Actual polymorphic value types that stay polymorphic when copied would be much more useful. However, even the limited polymorphic value types of C++ are useful. Let's see: - Implementation inheritance of value types, even without actual polymorphism, is useful. See, for example, the curiously recurring template pattern (and all of its uses). And, yes, you can achieve similar results in D by using template mixins, but this is a specialized mechanism where C++ manages to do with the same generalized mechanism used for polymorphism and interface inheritance. I use inheritance of value types all the time. - Polymorphic references to value types are often useful. D has references to value types (in the form of 'ref' parameters and pointers) but these are not polymorphic. As an example, I would name the standard C++ iostream. They're value types (non-copyable for the most part, but stored directly instead of as pointers, with RAII), but they're often passed around as polymorphic references. I use polymorphic references to value types occasionally. - C++ makes a clear distinction between a reference and the thing being referenced. Even if value types and polymorphism were mutually exclusive, this distinction would be useful. All types are consistently treated as value types, even those types that reference another object. I *like* having to write 'gc_ptr<Object> p;' instead of 'Object p;'. I *like* having to write 'p->f();' instead of 'p.f();'. It keeps my code clearly and more explicit. - C++ does not have separate rules for value types and reference types. All types are implicitly value types; values of all types can be placed on the heap. This simplifies the language by having just one set of rules instead of separate rules for classes and structs. Again, this unification would be useful even if it was an error to declare a variable of a polymorphic type as a direct variable.
 deterministic destructors,  arbitrary copy constructors, and optional
 lack of default constructor.

Struct have that except for default constructor. In D, currently default constructors cannot execute code. This is a limitation that we might need to address, although it has some advantages.

There are things that copy constructors can do that the post-blit operator can't do. Also, unless I am mistaken, D can move value types around in memory at will, which also invalidates designs that are useful in C++.
 How does the class/struct split? I think it's an enormous source of
 confusion for C++. C++ lore clarifies that you must decide in day one
 whether a class is meant to be polymorphic or monomorphic. Unfortunately
 that can't be expressed in the language, hence the weird cases with
 deriving from std::vector or getting polymorphic values unceremoniously
 sliced. Avoiding such mistakes are important things that C++ users must
 learn because there's nothing in the language stopping them from doing
 such nonsensical things; D very elegantly breaks that pattern by
 defining the language to only allow meaningful constructs.

On the contrary, the default in C++ is that a class can be used both as a value type and through a pointer as a reference type. Even in D, value types can be turned into value types Yes, when you copy class instances, it might be a bad idea to use the class as a base class. And conversely, if you use the class as a base class, it might be a bad idea to pass around instances of the class by value. It would be easy to forbid both of these at the language level, and almost as easy to fix them by creating non-slicing polymorphic value types. But the class/struct split in D goes much deeper than that. -- Rainer Deyke - rainerd eldwood.com
Jul 23 2009
next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Rainer Deyke wrote:
   - Implementation inheritance of value types, even without actual
 polymorphism, is useful.  See, for example, the curiously recurring
 template pattern (and all of its uses).

You can do this with 'alias this'.
     And, yes, you can achieve similar results in D by using template
 mixins, but this is a specialized mechanism where C++ manages to do with
 the same generalized mechanism used for polymorphism and interface
 inheritance.

It should be a different mechanism to show that it is a very different thing. Value types aren't polymorphic and shouldn't look like they are.
     I use inheritance of value types all the time.
 
   - Polymorphic references to value types are often useful.  D has
 references to value types (in the form of 'ref' parameters and pointers)
 but these are not polymorphic.  As an example, I would name the standard
 C++ iostream.

iostream isn't a good example of design <g>.
     They're value types (non-copyable for the most part, but stored
 directly instead of as pointers, with RAII), but they're often passed
 around as polymorphic references.

I.e. they're a mess. You just confused the heck out of me.
     I use polymorphic references to value types occasionally.
 
   - C++ makes a clear distinction between a reference and the thing
 being referenced.  Even if value types and polymorphism were mutually
 exclusive, this distinction would be useful.  All types are consistently
 treated as value types, even those types that reference another object.
 
   I *like* having to write 'gc_ptr<Object> p;' instead of 'Object p;'.
 I *like* having to write 'p->f();' instead of 'p.f();'.  It keeps my
 code clearly and more explicit.
 
   - C++ does not have separate rules for value types and reference
 types.  All types are implicitly value types; values of all types can be
 placed on the heap.  This simplifies the language by having just one set
 of rules instead of separate rules for classes and structs.  Again, this
 unification would be useful even if it was an error to declare a
 variable of a polymorphic type as a direct variable.

That philosophy conflicts with using . for values and -> for references.
 deterministic destructors,  arbitrary copy constructors, and optional
 lack of default constructor.

constructors cannot execute code. This is a limitation that we might need to address, although it has some advantages.

There are things that copy constructors can do that the post-blit operator can't do. Also, unless I am mistaken, D can move value types around in memory at will, which also invalidates designs that are useful in C++.

The capability of being able to move value types is deliberately designed in. It's there for the obvious reason of being able to create a moving garbage collector, and for the more subtle reason of being able to optimize away many more cases of copy-construction and destruction.
Jul 23 2009
parent reply Rainer Deyke <rainerd eldwood.com> writes:
Walter Bright wrote:
 Rainer Deyke wrote:
   - Implementation inheritance of value types, even without actual
 polymorphism, is useful.  See, for example, the curiously recurring
 template pattern (and all of its uses).

You can do this with 'alias this'.

Composition instead of inheritance? Doesn't work if I need virtual functions.
   - Polymorphic references to value types are often useful.  D has
 references to value types (in the form of 'ref' parameters and pointers)
 but these are not polymorphic.  As an example, I would name the standard
 C++ iostream.

iostream isn't a good example of design <g>.

I fully agree, but /this particular aspect/ of iostreams isn't an example of bad design either. How would you do this in D? Turning iostreams into reference types isn't the answer, especially if this means losing RAII. Non-polymorphics iostreams is also no-go. I suppose you could create a polymorphic reference-type wrapper around a pointer to the actual iostream struct, but that's a lot of extra work that isn't necessary in C++.
     They're value types (non-copyable for the most part, but stored
 directly instead of as pointers, with RAII), but they're often passed
 around as polymorphic references.

I.e. they're a mess. You just confused the heck out of me.

I don't see what's confusing about this. Most iostreams are non-copyable, i.e. the following just plain doesn't compile: stream_type a; stream_type b = a; Iostreams are not reference types, at all. It's not possible for one iostream to (accidentally or intentionally) alias another iostream. There are not idiomatically allocated with 'new'. Therefore they avoid the problems of having reference types in the language. Long distance bugs with iostreams are highly unlikely. Iostreams are passed as references - real references, with the 'T&' syntax, equivalent to 'ref T' in D - because that's the only way to pass them around. The callee always knows they are receiving a reference, because the '&' is an explicit part of the function signature.
   - C++ makes a clear distinction between a reference and the thing
 being referenced.  Even if value types and polymorphism were mutually
 exclusive, this distinction would be useful.  All types are consistently
 treated as value types, even those types that reference another object.

   I *like* having to write 'gc_ptr<Object> p;' instead of 'Object p;'.
 I *like* having to write 'p->f();' instead of 'p.f();'.  It keeps my
 code clearly and more explicit.

   - C++ does not have separate rules for value types and reference
 types.  All types are implicitly value types; values of all types can be
 placed on the heap.  This simplifies the language by having just one set
 of rules instead of separate rules for classes and structs.  Again, this
 unification would be useful even if it was an error to declare a
 variable of a polymorphic type as a direct variable.

That philosophy conflicts with using . for values and -> for references.

Are you deliberately trying to misunderstand me? In C++, for any type T, there is a type T* (and shared_ptr<T> and inclusive_ptr<T> and so on). T is a value type, always. T* is a pointer to a value of type T, but T* itself is still a value type. Given 'T* p;', 'p.x' accesses a member of 'p', while 'p->x' or '(*p).x' accesses a member of the value referenced by 'p'. Always, consistently, whether 'T' itself is a primitive type, a class, or even itself a pointer type.
 The capability of being able to move value types is deliberately
 designed in. It's there for the obvious reason of being able to create a
 moving garbage collector, and for the more subtle reason of being able
 to optimize away many more cases of copy-construction and destruction.

I know. Still, it invalidates valid C++ idioms. If there was some way to say "this struct cannot be moved", or even a hook function that is called before/after/during each move, then those idioms might still be valid. -- Rainer Deyke - rainerd eldwood.com
Jul 23 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Rainer Deyke wrote:
 Walter Bright wrote:
 Rainer Deyke wrote:
   - Implementation inheritance of value types, even without actual
 polymorphism, is useful.  See, for example, the curiously recurring
 template pattern (and all of its uses).


Composition instead of inheritance? Doesn't work if I need virtual functions.

This is going in circles. You started from "implementation inheritance of value types, even without actual polymorphism". Andrei
Jul 24 2009
parent Rainer Deyke <rainerd eldwood.com> writes:
Andrei Alexandrescu wrote:
 Rainer Deyke wrote:
 Composition instead of inheritance?  Doesn't work if I need virtual
 functions.

This is going in circles. You started from "implementation inheritance of value types, even without actual polymorphism".

Yes, but implementation inheritance may involve customization points. Virtual functions are one of of providing this customization. The curiously recurring template pattern provides another way. Either way, the class looks like a non-polymorphic value type from the outside. Simple composition does *not* work here, unless the inner component has a pointer to the outer aggregate. -- Rainer Deyke - rainerd eldwood.com
Jul 24 2009
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Rainer Deyke wrote:
 Andrei Alexandrescu wrote:
 Rainer Deyke wrote:
 1. C++'s object model, complete with polymorphic value types,


In a way, that's a loaded question, since C++ classes don't stay polymorphic when passed around by value. Actual polymorphic value types that stay polymorphic when copied would be much more useful. However, even the limited polymorphic value types of C++ are useful.

I'll try to briefly reply to this (I've been offline since yesterday's storm when a thunder fried the cable modem).
 Let's see:
 
   - Implementation inheritance of value types, even without actual
 polymorphism, is useful.  See, for example, the curiously recurring
 template pattern (and all of its uses).
 
     And, yes, you can achieve similar results in D by using template
 mixins, but this is a specialized mechanism where C++ manages to do with
 the same generalized mechanism used for polymorphism and interface
 inheritance.
 
     I use inheritance of value types all the time.

Well I use it sometimes too, but it's so fraught with peril that virtually all coding standards I've ever seen, all books and magazine articles on the topic, all pundits, say one thing: don't. Better use composition.
   - Polymorphic references to value types are often useful.  D has
 references to value types (in the form of 'ref' parameters and pointers)
 but these are not polymorphic.  As an example, I would name the standard
 C++ iostream.
 
     They're value types (non-copyable for the most part, but stored
 directly instead of as pointers, with RAII), but they're often passed
 around as polymorphic references.
 
     I use polymorphic references to value types occasionally.

I don't know what polymorphic references to value types mean, and I don't think iostreams are representative for the matter, or a good design in general.
   - C++ makes a clear distinction between a reference and the thing
 being referenced.  Even if value types and polymorphism were mutually
 exclusive, this distinction would be useful.  All types are consistently
 treated as value types, even those types that reference another object.

This is incorrect. C++ references are not value types. The design of references in C++ is particularly poor.
   I *like* having to write 'gc_ptr<Object> p;' instead of 'Object p;'.
 I *like* having to write 'p->f();' instead of 'p.f();'.  It keeps my
 code clearly and more explicit.

I understand, but that's a judgment call (e.g. explicit calls instead of operator overloading). Other people prefer the opposite.
   - C++ does not have separate rules for value types and reference
 types.  All types are implicitly value types; values of all types can be
 placed on the heap.  This simplifies the language by having just one set
 of rules instead of separate rules for classes and structs.  Again, this
 unification would be useful even if it was an error to declare a
 variable of a polymorphic type as a direct variable.

Again, C++ has references which kind of introduce separate and very different rules.
 deterministic destructors,  arbitrary copy constructors, and optional
 lack of default constructor.

constructors cannot execute code. This is a limitation that we might need to address, although it has some advantages.

There are things that copy constructors can do that the post-blit operator can't do.

Yes, mostly wrong things. I think it would be a huge loss if D copied C++'s model.
 Also, unless I am mistaken, D can move value types
 around in memory at will, which also invalidates designs that are useful
 in C++.

C++ copy+destroy sequence has been an absolute pest for years. Rvalue references fix that by adding another layer of complexity. I'm very happy D didn't inherit that. Andrei
Jul 24 2009
next sibling parent reply Rainer Deyke <rainerd eldwood.com> writes:
Andrei Alexandrescu wrote:
 Well I use it sometimes too, but it's so fraught with peril that
 virtually all coding standards I've ever seen, all books and magazine
 articles on the topic, all pundits, say one thing: don't. Better use
 composition.

My take on composition vs inheritance is very simple: always use composition, unless you absolutely need inheritance. Sometimes I absolutely need inheritance, and D isn't giving it to me. I don't care about your coding standards. I know how to use C++. I have my own rules about how to use it safely and effectively, rules that I have spent a lifetime refining. I still make mistakes, but almost all of my bugs are of the simple stupid kind that can be made in all languages. I don't need or want D to protect me from the pitfalls of C++ if this means significantly reducing the expressive power of the language. I don't want a safe language for little kids, I want a real language for adults. (And, truly, D is better in this regard than many of its competitors. Perhaps the awesome power of string mixins will be enough to offset its missing features. I will definitely give D2 a try when it is finished.) -- Rainer Deyke - rainerd eldwood.com
Jul 24 2009
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Rainer Deyke wrote:
 Andrei Alexandrescu wrote:
 Well I use it sometimes too, but it's so fraught with peril that
 virtually all coding standards I've ever seen, all books and magazine
 articles on the topic, all pundits, say one thing: don't. Better use
 composition.

My take on composition vs inheritance is very simple: always use composition, unless you absolutely need inheritance. Sometimes I absolutely need inheritance, and D isn't giving it to me. I don't care about your coding standards. I know how to use C++. I have my own rules about how to use it safely and effectively, rules that I have spent a lifetime refining.

Whether we like it or not, programming has a large social component. Andrei
Jul 24 2009
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Rainer Deyke wrote:
 I don't care about your coding standards.  I know how to use C++.  I
 have my own rules about how to use it safely and effectively, rules that
 I have spent a lifetime refining.

I've been writing software for 35 years. I'm still learning new ways of doing things and discarding old ones.
 (And, truly, D is better in this regard than many of its competitors.
 Perhaps the awesome power of string mixins will be enough to offset its
  missing features.

Probably the most frustrating thing to me when coding C++ is the lack of nested functions. The workaround is awfully ugly.
Jul 24 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Walter Bright wrote:
 Rainer Deyke wrote:
 I don't care about your coding standards.  I know how to use C++.  I
 have my own rules about how to use it safely and effectively, rules that
 I have spent a lifetime refining.

I've been writing software for 35 years. I'm still learning new ways of doing things and discarding old ones.

But goto will never die :o). Andrei
Jul 24 2009
prev sibling parent reply Sergey Gromov <snake.scaly gmail.com> writes:
Fri, 24 Jul 2009 16:58:50 -0500, Andrei Alexandrescu wrote:

 deterministic destructors,  arbitrary copy constructors, and optional
 lack of default constructor.

constructors cannot execute code. This is a limitation that we might need to address, although it has some advantages.

There are things that copy constructors can do that the post-blit operator can't do.

Yes, mostly wrong things. I think it would be a huge loss if D copied C++'s model.

This means that structs cannot hold on external resources, ever: struct RAII {...} var a = RAII("foo"); var b = RAII("bar"); a = b; // you just leaked a and corrupted b
Jul 26 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Sergey Gromov wrote:
 Fri, 24 Jul 2009 16:58:50 -0500, Andrei Alexandrescu wrote:
 
 deterministic destructors,  arbitrary copy constructors, and optional
 lack of default constructor.

constructors cannot execute code. This is a limitation that we might need to address, although it has some advantages.

operator can't do.

C++'s model.

This means that structs cannot hold on external resources, ever: struct RAII {...} var a = RAII("foo"); var b = RAII("bar"); a = b; // you just leaked a and corrupted b

You may be making a confusion between assignment and copy construction. Andrei
Jul 26 2009
parent reply Sergey Gromov <snake.scaly gmail.com> writes:
Sun, 26 Jul 2009 21:23:35 -0500, Andrei Alexandrescu wrote:

 Sergey Gromov wrote:
 Fri, 24 Jul 2009 16:58:50 -0500, Andrei Alexandrescu wrote:
 
 deterministic destructors,  arbitrary copy constructors, and optional
 lack of default constructor.

constructors cannot execute code. This is a limitation that we might need to address, although it has some advantages.

operator can't do.

C++'s model.

This means that structs cannot hold on external resources, ever: struct RAII {...} var a = RAII("foo"); var b = RAII("bar"); a = b; // you just leaked a and corrupted b

You may be making a confusion between assignment and copy construction.

Sure I'm confusing them, silly me. The only thing copy-construction is useful for is implementing move semantics, think std::auto_ptr. Seems like everything else can be done in post-blit. The inability to overload opAssign(typeof(this)) is a blocker for robust RAII though.
Jul 27 2009
parent Rainer Deyke <rainerd eldwood.com> writes:
Sergey Gromov wrote:
 The only thing copy-construction is useful for is implementing move
 semantics, think std::auto_ptr.  Seems like everything else can be done
 in post-blit.

The "linked list" implementation of smart pointers also requires a copy constructor. It's (arguably) not a very good design, but it is a valid design.
 The inability to overload opAssign(typeof(this)) is a blocker for robust
 RAII though.

Yes. -- Rainer Deyke - rainerd eldwood.com
Jul 27 2009
prev sibling parent Walter Bright <newshound1 digitalmars.com> writes:
Rainer Deyke wrote:
 1. C++'s object model, complete with polymorphic value types,
 deterministic destructors, arbitrary copy constructors, and optional
 lack of default constructor.  D's structs come close, but I think the
 class/struct split hurts D more than it helps.  And, yes, C++ has a lot
 of room for improvement here.

I'm with Andrei in saying that polymorphic value types are a very bad idea. I've never seen a use case for them that wasn't a mistake.
Jul 23 2009
prev sibling next sibling parent "Nick Sabalausky" <a a.a> writes:
"Rainer Deyke" <rainerd eldwood.com> wrote in message 
news:h49153$2pbq$1 digitalmars.com...
 Walter Bright wrote:
 My experience with C++ people sticking with it is they are so used to
 the problems they no longer see them. To me it's like the mess in one's
 house. One doesn't notice it until going on a vacation (i.e. learning a
 another language), having one's hotel room cleaned every day, then
 coming home and suddenly seeing how untidy it is <g>.

I want to throw these words back at you, because my first impression of D was "the bastard child of C++ and Java, with a random assortment of new features thrown in without rhyme or reason". D is many things, but a simple and elegant language it is not. (This is not a major problem to me, really. I can live with messy languages. I can live with C++. But to think that D is a massive improvement in this area requires a special sort of perspective.)

D is certainly a bit messy compared to many languages, but I have a very difficult time imagining how it could be considered messy in comparison to C++. C++ has decades of accumulated cruft from trying to cram in usable-but-clumbsy new features around piles of backwards-compatible anachronisms. The mess in D barely begins until a level that's far beyond where C++ takes you before getting messy. And this cannot be a result of me having become more accustomed to D than C++ - I've considered C++ the messiest non-dead language I know of since before I came across D, and even since the last time I was using C++ as my primary language.
Jul 23 2009
prev sibling parent reply sclytrack <sclytrack pi.be> writes:
== Quote from Rainer Deyke (rainerd eldwood.com)'s article
 Walter Bright wrote:
 My experience with C++ people sticking with it is they are so used to
 the problems they no longer see them. To me it's like the mess in one's


My experience with D people sticking with it is ... Not knowing that it can be done easier in another language is a bliss.
 house. One doesn't notice it until going on a vacation (i.e. learning a
 another language), having one's hotel room cleaned every day, then
 coming home and suddenly seeing how untidy it is <g>.

D was "the bastard child of C++ and Java, with a random assortment of

Delphi ------ C# = Delphi + Java D = (Java) + C++ Seems to me D only needs to learn from Delphi. Delphi is the first RAD language designed to easily interact with the IDE. Java wasn't, see the tonnes (non-metric unit of amount of code) of code that the IDE produces. I believe now Java has all the necessary features, it is just that swing just isn't the VCL. They could easily add a D style "property/method" syntax but they just won't since they want to stick to swing, which I think they need to drop. Two important features from Delphi 1) properties: Easily distinguishable from normal methods in the reflection, just enough to know what to display in the object inspector and not to rely on the name of the method. Object Inspector is a window displaying two columns, for normal properties and events. Property Name1, Property Value1 Property Name2, Property Value2 What is the purpose of properties? "The purpose of properties is to facilitate the interaction with the IDE" 2) published: Delphi has private, protected, public, published. 2.1) All published methods and properties are shown in the reflection, RTTI (sort of a selective reflection {$M+}). 2.2) Everything passed to a published methods or property is serializable (in Delphi terminology derives from TPersistent or basic type like integer and stuff) 2.3) You can't have published fields only published properties, and methods (Also note D people want properties to look like fields somehow) (Delphi starts their fields with F in front FNumber). Delphi might not have full reflection but the minimum it has is very powerful. The VCL (state of the art library) is well designed, the components are AWARE of either running in the client application or running from within the IDE, hence can change their behaviour, to adapt to the changes, minimizing what the actual IDE has to do. Part of its design is a virtual constructor. C++ + Another Language layered on top of C++ -------------------------------------------- 1) Combining C++ with another language is "fairly" easy. Okay D is a super enhanced C++. C# is a state-of-the-art language for creating applications in a very simple manner. D is nowhere near C#. C++ can easily be combined with Java and C# with the use of swig. D with the introduction of the garbage collector, this becomes difficult. (The "pied" guy might disagree) I think for D to be successful it will not only have to be an enhanced C++ but will have to overtake C#.
Jul 23 2009
next sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
sclytrack wrote:
 == Quote from Rainer Deyke (rainerd eldwood.com)'s article
 Walter Bright wrote:
 My experience with C++ people sticking with it is they are so used to
 the problems they no longer see them. To me it's like the mess in one's


My experience with D people sticking with it is ... Not knowing that it can be done easier in another language is a bliss.
 house. One doesn't notice it until going on a vacation (i.e. learning a
 another language), having one's hotel room cleaned every day, then
 coming home and suddenly seeing how untidy it is <g>.

D was "the bastard child of C++ and Java, with a random assortment of

Delphi ------ C# = Delphi + Java D = (Java) + C++ Seems to me D only needs to learn from Delphi. Delphi is the first RAD language designed to easily interact with the IDE. Java wasn't, see the tonnes (non-metric unit of amount of code) of code that the IDE produces. I believe now Java has all the necessary features, it is just that swing just isn't the VCL. They could easily add a D style "property/method" syntax but they just won't since they want to stick to swing, which I think they need to drop. Two important features from Delphi 1) properties: Easily distinguishable from normal methods in the reflection, just enough to know what to display in the object inspector and not to rely on the name of the method. Object Inspector is a window displaying two columns, for normal properties and events. Property Name1, Property Value1 Property Name2, Property Value2 What is the purpose of properties? "The purpose of properties is to facilitate the interaction with the IDE"

Unfortunately the designers of D doesn't care at all about IDE support for their language, even though in any "why don't you use D" discussion it is mentioned.
Jul 23 2009
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Ary Borenszweig wrote:
 Unfortunately the designers of D doesn't care at all about IDE support 
 for their language, even though in any "why don't you use D" discussion 
 it is mentioned.

The problem is not not caring. For one, I'd love a D IDE as much as the next guy, but I don't have the resources to put into writing one. IDEs come with language acceptance and are seldom written by the creator of the language. By the way, we must be doing something right. As of ten days ago there were 30,800 page views for The Case for D, and I just noticed that in the past week the presale rate for The D Programming Language has doubled. Andrei
Jul 23 2009
next sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
Andrei Alexandrescu wrote:
 Ary Borenszweig wrote:
 Unfortunately the designers of D doesn't care at all about IDE support 
 for their language, even though in any "why don't you use D" 
 discussion it is mentioned.

The problem is not not caring. For one, I'd love a D IDE as much as the next guy, but I don't have the resources to put into writing one. IDEs come with language acceptance and are seldom written by the creator of the language.

I'm not talking about writing an IDE. I'm talking about when thinking of a feature, think how this could be supported in an IDE. For instance properties seem to be a fundamental thing in Delphi and C#. When you are debugging and you watch some varaible, the debugger automatically allows you to expand a node and see the varaible's properties. You can't do that with D because any function that has zero parameters could be a property, even though some functions aren't properties.
 By the way, we must be doing something right. As of ten days ago there 
 were 30,800 page views for The Case for D, and I just noticed that in 
 the past week the presale rate for The D Programming Language has doubled.

Great! :-)
Jul 23 2009
parent reply Eldar Insafutdinov <e.insafutdinov gmail.com> writes:
Ary Borenszweig Wrote:

 Andrei Alexandrescu wrote:
 Ary Borenszweig wrote:
 Unfortunately the designers of D doesn't care at all about IDE support 
 for their language, even though in any "why don't you use D" 
 discussion it is mentioned.

The problem is not not caring. For one, I'd love a D IDE as much as the next guy, but I don't have the resources to put into writing one. IDEs come with language acceptance and are seldom written by the creator of the language.

I'm not talking about writing an IDE. I'm talking about when thinking of a feature, think how this could be supported in an IDE. For instance properties seem to be a fundamental thing in Delphi and C#. When you are debugging and you watch some varaible, the debugger automatically allows you to expand a node and see the varaible's properties. You can't do that with D because any function that has zero parameters could be a property, even though some functions aren't properties.

While working on QtD I have also come up with the conclusion that D needs proper properties. Qt itself greatly relies on properties and it makes a lot of cool things possible. Of course C++ doesn't support them, it is done via Qt metatype system. When D goes popular, IDEs will severely lack this functionality from the language.
Jul 23 2009
next sibling parent reply Lutger <lutger.blijdestijn gmail.com> writes:
Eldar Insafutdinov wrote:

 Ary Borenszweig Wrote:

 For instance properties seem to be a fundamental thing in Delphi and C#.
 When you are debugging and you watch some varaible, the debugger
 automatically allows you to expand a node and see the varaible's
 properties. You can't do that with D because any function that has zero
 parameters could be a property, even though some functions aren't
 properties.

While working on QtD I have also come up with the conclusion that D needs proper properties. Qt itself greatly relies on properties and it makes a lot of cool things possible. Of course C++ doesn't support them, it is done via Qt metatype system. When D goes popular, IDEs will severely lack this functionality from the language.

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?
Jul 23 2009
next sibling parent reply Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
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.D&article_id=81759 Feel free to modify and/or DIPify it. -- Michiel Helvensteijn
Jul 23 2009
next sibling parent Lutger <lutger.blijdestijn gmail.com> writes:
Bill Baxter wrote:

 Not a big issue, but introducing 3 keywords for this one
 feature will be a tough sell.  
 --bb

At least it's not 5 like vb.net, but that beast already has 150 keywords so I guess a couple more doesn't matter that much :)
Jul 23 2009
prev sibling next sibling parent reply Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
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
Jul 23 2009
parent Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
Michiel Helvensteijn wrote:

 set(x, v) (or x.get(v)) assigns v to x.

Small correction: x.set(v) -- Michiel Helvensteijn
Jul 23 2009
prev sibling parent reply Eldar Insafutdinov <e.insafutdinov gmail.com> writes:
Michiel Helvensteijn Wrote:

 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.D&article_id=81759 Feel free to modify and/or DIPify it. -- Michiel Helvensteijn

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.
Jul 23 2009
parent reply Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
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
Jul 23 2009
next sibling parent Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
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
Jul 24 2009
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Jarrett Billingsley wrote:
 On Thu, Jul 23, 2009 at 5:56 PM, Michiel
 Helvensteijn<m.helvensteijn.remove gmail.com> wrote:
 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.

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.

You're suggesting adding something like 25 operator overloads to every property. Can you say "code bloat"? 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);

I think this would be inefficient in many cases. Andrei
Jul 24 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Bill Baxter wrote:
 On Fri, Jul 24, 2009 at 2:19 PM, Andrei
 Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:
 Jarrett Billingsley wrote:
 On Thu, Jul 23, 2009 at 5:56 PM, Michiel
 Helvensteijn<m.helvensteijn.remove gmail.com> wrote:
 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.

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.

property. Can you say "code bloat"? 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);


That is true but I also think: * probably that is the best that can be achieved automatically. * if better can be achieved automatically then the compiler can just do that under the hood. No user code needs to change. * set(get op value) probably won't be inefficient in some cases. * having a op= b work automatically in an inefficient way is better than forcing the users of the code to make the same ineffecient transformation in their code manually (which is the status quo of property syntax in D). So I think how to make a op= b whizzy fast can be decided later. And for now set(get op value) is good enough.

Ok, I got convinced. Andrei
Jul 24 2009
prev sibling next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Lutger" <lutger.blijdestijn gmail.com> wrote in message 
news:h4agu7$2cme$1 digitalmars.com...
 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?

http://prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP4 I'm making a post for this over on D.announce...
Jul 23 2009
next sibling parent "Nick Sabalausky" <a a.a> writes:
"Nick Sabalausky" <a a.a> wrote in message 
news:h4bdmq$115p$1 digitalmars.com...
 "Lutger" <lutger.blijdestijn gmail.com> wrote in message 
 news:h4agu7$2cme$1 digitalmars.com...
 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?

http://prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP4 I'm making a post for this over on D.announce...

Erm... I mean right here on digitalmars.D...
Jul 23 2009
prev sibling parent reply goooooo <goooooo gmail.com> writes:
It is said that "Character decided fate" .
W.B's character decided the fate of watcom C, and now the fate of D.
Just as it is said in the homepage, D is the code for nerds ,not the code for
thinkers as LISP, nor the code for creators as C,nor the code for users like
perl.
Sorry to say so.
Jul 24 2009
parent reply Walter Bright <newshound1 digitalmars.com> writes:
goooooo wrote:
 It is said that "Character decided fate" . W.B's character decided
 the fate of watcom C, and now the fate of D. Just as it is said in
 the homepage, D is the code for nerds ,not the code for thinkers as
 LISP, nor the code for creators as C,nor the code for users like
 perl. Sorry to say so.

I am not and never was associated with Watcom C in any way, other than as a competitor. I have an old copy of it in the basement <g>. The compiler products I've worked on: http://www.walterbright.com
Jul 24 2009
parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
Walter Bright wrote:
 goooooo wrote:
 It is said that "Character decided fate" . W.B's character decided
 the fate of watcom C, and now the fate of D. Just as it is said in
 the homepage, D is the code for nerds ,not the code for thinkers as
 LISP, nor the code for creators as C,nor the code for users like
 perl. Sorry to say so.

I am not and never was associated with Watcom C in any way, other than as a competitor. I have an old copy of it in the basement <g>. The compiler products I've worked on: http://www.walterbright.com

http://www.walterbright.com/garage/index.html YEAAAH!!
Jul 24 2009
parent Walter Bright <newshound1 digitalmars.com> writes:
Jarrett Billingsley wrote:
 What!  Descent!  You don't SELL Descent.  You treasure it for years
 and years, owing your entire interest in programming to it.

Bah, I have a basement full of such treasures. I finally took to the dump my Diablo 630 daisywheel printer. It was in mint condition, with manual, extra ribbons, cables, etc. I bought it for $1,000 back in 1982. It was built like a tank (and sounded like a machine gun when in action!). It produced beautiful printed pages. I couldn't find anyone who wanted it, not even old computer museums.
Jul 24 2009
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Lutger wrote:
 Eldar Insafutdinov wrote:
 
 Ary Borenszweig Wrote:

 For instance properties seem to be a fundamental thing in Delphi and C#.
 When you are debugging and you watch some varaible, the debugger
 automatically allows you to expand a node and see the varaible's
 properties. You can't do that with D because any function that has zero
 parameters could be a property, even though some functions aren't
 properties.

proper properties. Qt itself greatly relies on properties and it makes a lot of cool things possible. Of course C++ doesn't support them, it is done via Qt metatype system. When D goes popular, IDEs will severely lack this functionality from the language.

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?

Yes please. Andrei
Jul 24 2009
prev sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Fri, Jul 24, 2009 at 6:44 PM, Andrei
Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Fri, Jul 24, 2009 at 2:19 PM, Andrei
 Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:
 Jarrett Billingsley wrote:
 On Thu, Jul 23, 2009 at 5:56 PM, Michiel
 Helvensteijn<m.helvensteijn.remove gmail.com> wrote:
 Eldar Insafutdinov wrote:

 from your post:

 property int length {
 =A0 get() { return this.len; }
 =A0 set(newLen) { this.len =3D newLen; }
 =A0 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, whic=






 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=





 variable --, there is no reference to return.

 Besides, in D, you can probably use mixins to copy the entire interfa=





 of a
 type into the property without code duplication.

You're suggesting adding something like 25 operator overloads to every property. =A0Can you say "code bloat"? 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=3D value; Simply becomes: obj.prop.set(obj.prop.get op value);

I think this would be inefficient in many cases.

That is true but I also think: * probably that is the best that can be achieved automatically. * if better can be achieved automatically then the compiler can just do that under the hood. =A0No user code needs to change. * set(get op value) probably won't be inefficient in some cases. * having a op=3D b work automatically in an inefficient way is better than forcing the users of the code to make the same ineffecient transformation in their code manually (which is the status quo of property syntax in D). So I think how to make a op=3D b whizzy fast can be decided later. =A0An=


 for now set(get op value) is good enough.

Ok, I got convinced.

Have you also seen Michiel's suggestion? obj.prop op=3D value; // auto temp =3D obj.prop.get(); // temp op=3D value; // obj.prop.set(value); I think this is probably somewhat more correct, in the face of operator overloading on typeof(temp). That is, if obj.prop is a struct that overloads opAddAssign, you'd want "obj.prop +=3D 5" to really call obj.prop's opAddAssign, rather than its opAdd.
Jul 24 2009
prev sibling next sibling parent Walter Bright <newshound1 digitalmars.com> writes:
Andrei Alexandrescu wrote:
 By the way, we must be doing something right. As of ten days ago there 
 were 30,800 page views for The Case for D, and I just noticed that in 
 the past week the presale rate for The D Programming Language has doubled.

Must be those classicempire affiliate links!!!
Jul 23 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Fri, Jul 24, 2009 at 5:19 PM, Andrei
Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:

 obj.prop op= value;

 Simply becomes:

 obj.prop.set(obj.prop.get op value);

I think this would be inefficient in many cases.

Um, what do you have to write now? "obj.prop = obj.prop op value". All I'm suggesting is that the compiler automatically transform the expression for you. Also, what someone else suggested - that it become "auto temp = obj.prop get; temp op= value; obj.prop.set(temp)" - is technically more correct, in terms of operator overloading (i.e. if the property returns a BigInt, or something).
Jul 24 2009
prev sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Fri, Jul 24, 2009 at 2:19 PM, Andrei
Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:
 Jarrett Billingsley wrote:
 On Thu, Jul 23, 2009 at 5:56 PM, Michiel
 Helvensteijn<m.helvensteijn.remove gmail.com> wrote:
 Eldar Insafutdinov wrote:

 from your post:

 property int length {
 =A0 =A0get() { return this.len; }
 =A0 =A0set(newLen) { this.len =3D newLen; }
 =A0 =A0void opIncrement() { this.len++; }
 }

 I don't think that's flexible to overload every operator to get the be=




 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 actio=



 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.

You're suggesting adding something like 25 operator overloads to every property. =A0Can you say "code bloat"? 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=3D value; Simply becomes: obj.prop.set(obj.prop.get op value);

I think this would be inefficient in many cases.

That is true but I also think: * probably that is the best that can be achieved automatically. * if better can be achieved automatically then the compiler can just do that under the hood. No user code needs to change. * set(get op value) probably won't be inefficient in some cases. * having a op=3D b work automatically in an inefficient way is better than forcing the users of the code to make the same ineffecient transformation in their code manually (which is the status quo of property syntax in D). So I think how to make a op=3D b whizzy fast can be decided later. And for now set(get op value) is good enough. --bb
Jul 24 2009
prev sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Fri, Jul 24, 2009 at 2:58 PM, Ary Borenszweig<ary esperanto.org.ar> wrote:
 Walter Bright wrote:
 goooooo wrote:
 It is said that "Character decided fate" . W.B's character decided
 the fate of watcom C, and now the fate of D. Just as it is said in
 the homepage, D is the code for nerds ,not the code for thinkers as
 LISP, nor the code for creators as C,nor the code for users like
 perl. Sorry to say so.

I am not and never was associated with Watcom C in any way, other than as a competitor. I have an old copy of it in the basement <g>. The compiler products I've worked on: http://www.walterbright.com

http://www.walterbright.com/garage/index.html YEAAAH!!

What! Descent! You don't SELL Descent. You treasure it for years and years, owing your entire interest in programming to it.
Jul 24 2009
prev sibling next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
sclytrack wrote:
 I think for D to be successful it will not only have to be an enhanced C++
 but will have to overtake C#.

I think D should also visibly obviate some use of Python or Perl for prototyping. Thank you for your insightful post, the points on reflection and Delphi were excellent. Andrei
Jul 23 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Thu, Jul 23, 2009 at 2:19 PM, Lutger<lutger.blijdestijn gmail.com> wrote:
 Bill Baxter wrote:

 Not a big issue, but introducing 3 keywords for this one
 feature will be a tough sell.
 --bb

At least it's not 5 like vb.net, but that beast already has 150 keywords so I guess a couple more doesn't matter that much :)

I do think it would be justifiable to add one more keyword for real properties, just not three. If the get/set could somehow be context keywords then that would be nice. I know these sorts of context keywords are ok in D's grammar version(Foo) and foreach(reverse) was bandied about as being acceptable since they have a clear contextual scope, just not sure if get/set inside a property block would qualify. --bb
Jul 23 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Thu, Jul 23, 2009 at 2:25 PM, Steven
Schveighoffer<schveiguy yahoo.com> wrote:
 On Thu, 23 Jul 2009 17:13:13 -0400, Bill Baxter <wbaxter gmail.com> wrote=

 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. =A0Can a compiler guru confirm
 that? =A0Not a big issue, but introducing 3 keywords for this one
 feature will be a tough sell. =A0 Perhaps just

 property int length {
 =A0 =A0() { return this.len; }
 =A0 =A0(newLen) { this.len =3D newLen; }
 }

 would be enough. =A0Maybe I'm wrong about get/set being an issue, though=


 I think you might be wrong. =A0operator functions like opAdd are not keyw=

 but are treated specially by the compiler. =A0The compiler would probably=

 change the get and set functions into mangled symbols that would never be
 generated from a normal function, so no keywords would be required.

That makes sense. Maybe Walter would like to take this opportunity to plug his upcoming compiler building seminar for us compiler ignoramuses. :-) --bb
Jul 23 2009
prev sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Thu, Jul 23, 2009 at 5:56 PM, Michiel
Helvensteijn<m.helvensteijn.remove gmail.com> wrote:
 Eldar Insafutdinov wrote:

 from your post:

 property int length {
 =A0 =A0 get() { return this.len; }
 =A0 =A0 set(newLen) { this.len =3D newLen; }
 =A0 =A0 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 unlimit=

 and unrestricted access to that variable with only one call, and you migh=

 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 o=

 type into the property without code duplication.

You're suggesting adding something like 25 operator overloads to every property. Can you say "code bloat"? 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=3D value; Simply becomes: obj.prop.set(obj.prop.get op value);
Jul 23 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Thu, Jul 23, 2009 at 1:53 PM, Michiel
Helvensteijn<m.helvensteijn.remove gmail.com> wrote:
 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.D&article_id=81759 Feel free to modify and/or DIPify it.

""" 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...."? 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. Can a compiler guru confirm that? Not a big issue, but introducing 3 keywords for this one feature will be a tough sell. Perhaps just property int length { () { return this.len; } (newLen) { this.len = newLen; } } would be enough. Maybe I'm wrong about get/set being an issue, though. --bb
Jul 23 2009
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 23 Jul 2009 17:13:13 -0400, Bill Baxter <wbaxter gmail.com> wrote:

 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.  Can a compiler guru confirm
 that?  Not a big issue, but introducing 3 keywords for this one
 feature will be a tough sell.   Perhaps just

 property int length {
     () { return this.len; }
     (newLen) { this.len = newLen; }
 }

 would be enough.  Maybe I'm wrong about get/set being an issue, though.

I think you might be wrong. operator functions like opAdd are not keywords, but are treated specially by the compiler. The compiler would probably just change the get and set functions into mangled symbols that would never be generated from a normal function, so no keywords would be required. -Steve
Jul 23 2009
prev sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Thu, Jul 23, 2009 at 5:20 PM, Rainer Deyke<rainerd eldwood.com> wrote:
 Walter Bright wrote:
 I don't see what's confusing about this.

 Most iostreams are non-copyable, i.e. the following just plain doesn't
 compile:
 =A0stream_type a;
 =A0stream_type b =3D a;

 Iostreams are not reference types, at all. =A0It's not possible for one
 iostream to (accidentally or intentionally) alias another iostream.
 There are not idiomatically allocated with 'new'. =A0Therefore they avoid
 the problems of having reference types in the language.

I don't get your meaning in that last sentence. What's the problem of having reference types in the language? C++ has reference types in the language -- T&. If you just mean it's not possible to forget to deallocate on scope exit, then you just need to use "scope" in D to get that effect. Or an explicit "scope(exit)" clause.
 Long distance
 bugs with iostreams are highly unlikely.

 Iostreams are passed as references - real references, with the 'T&'
 syntax, equivalent to 'ref T' in D - because that's the only way to pass
 them around. =A0The callee always knows they are receiving a reference,
 because the '&' is an explicit part of the function signature.

Seems like scope handles most of this just fine. Except the case where you want to have an iostream as part of a larger class. But then that larger class is probably going to need deterministic destruction too, so wherever it's used it should probably be scope'ed also. --bb
Jul 23 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Wed, Jul 22, 2009 at 6:49 PM, Walter
Bright<newshound1 digitalmars.com> wrote:
 Bill Baxter wrote:
 Yeh, it's like what's the big diff between a Lamborghini and a Chevy
 Nova anyway? =A0They both have four tires. =A0They both run on gas. =A0S=


 what's all the fuss about the Lamborghini?

It's like a car from the 60's vs a car today. It's hard to see what's rea=

 different, until you spend time driving one. There's just a boatload of
 little improvements in everything that add up to a lot.

 It's no surprise that most people who fix up those old cars also upgrade =

 systems with modern technology.

That's a better analogy. Or like the guy who works on my bicycle was telling me just this week before he got started trying to fix the thing I was complaining about. "In an ideal world every bike would be a $7000 bike." That's because basically everything is built to higher tolerances on a $7000 bike and everything just works exactly like it's supposed to. D is a lot like that $7000 bike -- except, thankfully, for the price tag. --bb
Jul 23 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Thu, Jul 23, 2009 at 12:11 PM, Rainer Deyke<rainerd eldwood.com> wrote:

 Yes, C++ has problems, but these problems can be fixed! =A0The
 struct/class split, on the other hand, introduces many more problems
 that are harder to fix.

You know, this is like the first thing C++ users complain about on the IRC channel when they find D: "what if I want to turn a class into a struct, or vice versa?" I've been using D for five years, and I have never. EVER. Needed or desired to do that. Nor have I heard anyone but new C++ users complaining about it. Classes and structs are fundamentally different concepts. You design your code from the start to use one or the other, because only one makes sense.
Jul 23 2009
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 23 Jul 2009 13:10:59 -0400, Jarrett Billingsley  
<jarrett.billingsley gmail.com> wrote:

 On Thu, Jul 23, 2009 at 12:11 PM, Rainer Deyke<rainerd eldwood.com>  
 wrote:

 Yes, C++ has problems, but these problems can be fixed!  The
 struct/class split, on the other hand, introduces many more problems
 that are harder to fix.

You know, this is like the first thing C++ users complain about on the IRC channel when they find D: "what if I want to turn a class into a struct, or vice versa?" I've been using D for five years, and I have never. EVER. Needed or desired to do that. Nor have I heard anyone but new C++ users complaining about it.

I did. With dcollections, my nodes were classes at first, because they were supposed to be heap-allocated reference types. However, when I realized that with a custom allocator, I could tremendously increase performance, I had to switch to structs. What ended up happening is I simply aliased Node to node *, and that was that. Come to think of it, I probably didn't put enough thought in my choice of classes to begin with. This however, is not a true "change" since I just changed classes to struct references, not to actual value type structs. I plan on doing some more class-to-struct changes, not sure how it will pan out. But I think it certainly does come up that choosing struct or class is not an easy decision, and both can have advantages/disadvantages. However, I don't think C++ solves that problem very well either. The one thing I think is missing from D in this area is struct interfaces. -Steve
Jul 23 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Thu, Jul 23, 2009 at 1:20 PM, Steven
Schveighoffer<schveiguy yahoo.com> wrote:

 However, when I realized that with a custom allocator, I could tremendously
 increase performance, I had to switch to structs.

Um, did you? Because you can have custom allocators for classes too..
Jul 23 2009
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 23 Jul 2009 14:06:12 -0400, Jarrett Billingsley  
<jarrett.billingsley gmail.com> wrote:

 On Thu, Jul 23, 2009 at 1:20 PM, Steven
 Schveighoffer<schveiguy yahoo.com> wrote:

 However, when I realized that with a custom allocator, I could  
 tremendously
 increase performance, I had to switch to structs.

Um, did you? Because you can have custom allocators for classes too..

First, there were other reasons, such as I don't need polymorphism or interfaces for those node types, so switching to structs helped eliminate bloat for those features. What I did was allocate an array of structs vs. allocating each node, which uses the GC less. The less you use the GC the better when it comes to performance :) Can you do that with classes, I don't know. I thought it was impossible to allocate several classes in one block. It was pretty easy to do the custom allocator with structs... -Steve
Jul 23 2009
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 23 Jul 2009 15:11:07 -0400, Walter Bright  
<newshound1 digitalmars.com> wrote:

 Michiel Helvensteijn wrote:
  Properties. Your syntactic sugar:
  int i = c.p; // int i = c.p()
 p = i // c.p(i)
  They can't do these things:
  * No control over their use by class designer: ANY member function  
 with one
 or zero parameters may be called using 'property syntax'. This is not a
 good thing.

Why not? Seriously, what is the semantic difference?

It leads to making things look like properties when they are not. For example, writefln = "hi"; The worst is the assign statement, since there are plenty of legitimate uses of having a single argument function not actually assign anything. It can also lead to ambiguities, such as a property that returns a delegate must be called with double parens: c.member()(); It has nothing to do with how the compiler looks at it semantically, but it has everything to do with how the user reads it. I want the compiler to tell the user "no you can't use that member that way." so I don't get complaints that my "properties" are badly implemented (and yes, I've had this happen, see http://www.dsource.org/projects/tango/ticket/1184) It also forces better coding habits. For example, in C#, when I declare a property it's: int x { get { return _x; } set { _x = value; } // value is a context keyword } With D properties, x() and x(int value) could be scattered anywhere in the class. Notice also, that I can document x as a property, not as it's individual functions.
 * No parameterized properties: c.f(5) = 6; // c.f(5, 6)

Ok.

Ugh, don't do this. You can implement this behavior easily enough. We already have opIndexAssign. -Steve
Jul 23 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Thu, Jul 23, 2009 at 4:34 PM, Rainer Deyke<rainerd eldwood.com> wrote:
 Jarrett Billingsley wrote:
 Classes and structs are fundamentally different concepts. =A0You design
 your code from the start to use one or the other, because only one
 makes sense.

In my first (and to date only) D project, *all* my user-defined types started as structs, and *all* became classes when I found out that D1 structs don't support all of the features I need. =A0(None of them used polymorphism. =A0In C++, all would have been value types.)

And you don't think that has *anything* to do with trying to program C++ in= D.
Jul 23 2009
prev sibling next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Thu, Jul 23, 2009 at 10:49:49PM +0100, Tom S wrote:
 Why is dedicated syntax for comma expressions better than commaExpr(...)?

What do you propose we do about the commas in loops? Breaking them would be a pretty big change to the C folks. With the naked comma tuple, how do you pass them to a function? void func(Tuple!(int, int) a, int b); Is that just the same as: void func(int a, int b, int c); You'd call them the same way without the tuple decoration :S It might be my years of C bias, but the naked tuples just look wrong. -- Adam D. Ruppe http://arsdnet.net
Jul 23 2009
parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Sat, Jul 25, 2009 at 02:15:00PM -0300, Leandro Lucarella wrote:
 if not, it's just syntax sugar for structs,
 or some kind of limited list.

Interestingly, I've been looking at tuples almost entirely as "anonymous structs", if you will. Perhaps this is another bias preventing me from seeing the big advantage of the other syntax. -- Adam D. Ruppe http://arsdnet.net
Jul 25 2009
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Fri, Jul 24, 2009 at 12:03:37AM +0200, Michiel Helvensteijn wrote:
 Would you look at this page and give me your opinion?

Looking at it quickly, the big difference seems to be you leave the tuple word off, and use them in more places. Is Tuple!(int, bool) A = tuple(a, b) really that much worse than: (int, bool) A = (a, b) ? Better yet, of course is: auto A = tuple(a, b); 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. -- Adam D. Ruppe http://arsdnet.net
Jul 23 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Thu, Jul 23, 2009 at 3:21 PM, Walter
Bright<newshound1 digitalmars.com> wrote:
 Rainer Deyke wrote:
 =A0 =A0They're value types (non-copyable for the most part, but stored
 directly instead of as pointers, with RAII), but they're often passed
 around as polymorphic references.

I.e. they're a mess. You just confused the heck out of me.

I think the case he's talking about is just a sort of optimization to use stack allocation instead of heap alloc. void func() { DerivedFoo x; callMethodThatTakesAnyFoo(&x); } I.e. the kind of thing you'd use "scope Foo" for in D. Except that in the C++ case you could have DerivedFoo be part of another struct or class instead of being a local variable. --bb
Jul 23 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Thu, Jul 23, 2009 at 6:10 PM, Adam D. Ruppe<destructionator gmail.com> wrote:
 What do you propose we do about the commas in loops? Breaking them
 would be a pretty big change to the C folks.

It's trivial to allow a comma-separated list of expressions in the for loop header. If Pythonic tuple syntax were used (i.e. parens required), there would be no parsing ambiguity.
Jul 23 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Thu, Jul 23, 2009 at 3:41 PM, Adam D. Ruppe<destructionator gmail.com> wrote:
 On Fri, Jul 24, 2009 at 12:03:37AM +0200, Michiel Helvensteijn wrote:
 Would you look at this page and give me your opinion?

Looking at it quickly, the big difference seems to be you leave the tuple word off, and use them in more places. Is Tuple!(int, bool) A = tuple(a, b) really that much worse than: (int, bool) A = (a, b) ?

Uh, yes. Yes it is. But I have to say I'm always amazed what clutter some people are apparently willing to put up with when I look at just about any page of MSDN. --bb
Jul 23 2009
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Fri, Jul 24, 2009 at 12:37:42AM +0200, Michiel Helvensteijn wrote:
 Hm. Then I believe you haven't read the whole thing. 

Yeah, I just briefly skimmed it. I'll have to go back to it for a full read when I have a little more time.
 Looking like C is not the be-all and end-all of programming languages.

For a language like D, which hopes to hold on to C programmers, it is very important. We're an obstinate bunch, set in our ways. I remember the first time I saw D: I dismissed it because the import statement looked "too Javaish" and didn't come back until a year or two later. A change like this would just be too weird, and would surely alienate some of the intended audience before they get past the first look. -- Adam D. Ruppe http://arsdnet.net
Jul 23 2009
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Thu, Jul 23, 2009 at 11:49:29PM +0100, Tom S wrote:
 It's not much worse, but it's not everything that's to tuples. Here's 
 one more example:
 
 int a, b;

----
 a, b = 2, 3;


Why would you ever want to do that when you have: a = 2; b = 3; I see people ask why would you ever want the existing comma operator, when you can just separate it into two lines, and the replacement use could also just be separated into two lines. The swap function I've seen tossed around could just be swap(x,y) instead of y,x = x,y too. A fancier rearrange could be done with a template, so: (x, y, z) = (z, y, z) becomes: rearrange(x, y, z, z, y, x); I could see a function returning it as being potentially useful for the x,y case: Tuple!(int, int) getPoint() { return tuple(x, y); } ... x, y = getPoint(); But, a better way to do this would be: Tuple!(int, "x", int, "y") getPoint() { return tuple(x, y); } ... auto p = getPoint(); // work with p.x and p.y It is two brief lines longer to copy them to a local x and y if you want to. -- Adam D. Ruppe http://arsdnet.net
Jul 23 2009
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Thu, Jul 23, 2009 at 05:53:35PM -0700, Bill Baxter wrote:
 Uh, yes.  Yes it is.
 But I have to say I'm always amazed what clutter some people are
 apparently willing to put up with when I look at just about any page
 of MSDN.

And I'm amazed at the illegibility some people are apparently willing to put up with whenever I look at just about any scripting language code. (Or regular expressions, my God!) I certainly wouldn't go into Java territory for bondage and discipline, but some amount of verbosity helps keep me sane.
 
 --bb

-- Adam D. Ruppe http://arsdnet.net
Jul 23 2009
prev sibling next sibling parent Jesse Phillips <jessekphillips gmail.com> writes:
On Thu, 23 Jul 2009 21:22:03 -0400, Adam D. Ruppe wrote:

 
 I could see a function returning it as being potentially useful for the
 x,y case:
 
 Tuple!(int, int) getPoint() { return tuple(x, y); } ...
 
 x, y = getPoint();
 
 
 But, a better way to do this would be:
 
 Tuple!(int, "x", int, "y") getPoint() { return tuple(x, y); } ...
 
 auto p = getPoint();
 // work with p.x and p.y
 
 It is two brief lines longer to copy them to a local x and y if you want
 to.

Thanks for the tutorial, expect to see it on Wiki4D within a year :D
Jul 23 2009
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 24 Jul 2009 13:37:16 -0400, Walter Bright  
<newshound1 digitalmars.com> wrote:

 Daniel Keep wrote:
 Actually, I've now come up with a counter-example for the idea of using
 pure at all:

That's right, lazy evaluation can't be pure. So, the question is is this an important enough case to justify a whole new syntax?

Don't get lost in the pure discussion. There are many reasons to have a dedicated property syntax, even for non-pure properties. I don't think properties should be necessarily pure anyways. How do you have a pure setter? It's more of a convention that a property getter should not change the state of the containing entity, a pretty much non-enforcable convention. That's not to say that you couldn't mark a property as const or pure, just that it shouldn't HAVE to be that way. -Steve
Jul 24 2009
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 24 Jul 2009 14:10:59 -0400, Walter Bright  
<newshound1 digitalmars.com> wrote:

 Steven Schveighoffer wrote:
 I don't think properties should be necessarily pure anyways.  How do  
 you have a pure setter?  It's more of a convention that a property  
 getter should not change the state of the containing entity, a pretty  
 much non-enforcable convention.

That's my problem with properties as a distinct syntax - they don't have distinct uses or behaviors.

If you delineate what can be called how, then you elminate syntax ambiguities from occurring, and eliminate bizarro cases of syntax. The difficulty is that the "human meaning" of a property is different than the human meaning of a function. To the compiler, they're all functions, so you as the compiler writer aren't seeing that they are different. I think we all agree that writefln = "hi"; makes absolutely no sense to a person. But it makes complete sense to the compiler, because it has no idea what the word "writefln" means to a person. It's the exact same reason + is not the concatenation operator. Semantically, making + concatenate two strings together would be completely unambiguous from adding two integers together because strings do not define addition, and integers do not define concatenation. From your own documentation, someone seeing "10" + 3 might think that he would get 13 or "103". Even if the compiler defines what "should" happen, and the rules are unambiguous, it looks incorrect to the user. But having ~ be the concatenation operator makes it completely unambiguous what the syntax means, regardless of what the types are. So the compiler and the user are talking the same language, and the user isn't freaked out by the "human meaning" of the syntax. -Steve
Jul 24 2009
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 24 Jul 2009 15:12:10 -0400, Ary Borenszweig <ary esperanto.org.ar>  
wrote:

 Maybe what scares Walter is a whole new syntax for properties. If at  
 least you could say which functions are properties and which are not,  
 that would be a small change and it'll make it possible for other  
 things. Something like:

His point is that there are no benefits to the semantic meaning of the code by declaring something a property. It's still a function, still gets implemented by a function. It's like if you say functions can now be called like this: foo^arg But he's not getting that the compiler isn't the only one reading the code, and D isn't the only language being used. You are also using a person's knowledge of math (x = y) and a person's native language. At least the native language, the compiler knows and cares nothing about, but the developer and user care greatly (and want the conventions enforced). -Steve
Jul 24 2009
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 24 Jul 2009 15:26:58 -0400, Michiel Helvensteijn  
<m.helvensteijn.remove gmail.com> wrote:


 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.

This is typical Walter :) He'll argue the easy ones all day long, and stay silent on the harder-to-refute ones. Then one day, you'll see the feature you wanted suddenly and without warning appear in the compiler (I'm still holding my breath on a few). Not that this means properties are going to be one of those features, but still. With Walter, silence is usually all you get when he's coming around to your side :) It's a good strategy for someone who's word is almost law when it comes to D. You have to be careful what you say, flip-flopping around only leads to knee-jerk feature additions, more bikeshed discussions, and more people clammoring for feature additions (hey, you added this, why not that!). I have great respect for the balance he has to deal with between adding interesting features and keeping a sane spec. -Steve
Jul 24 2009
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 24 Jul 2009 21:36:53 -0400, Daniel Keep  
<daniel.keep.lists gmail.com> wrote:


 There's also the argument for debuggers being able to automatically
 display properties; I think this one is fairly borderline since if I was
 writing a debugger, it would only *automatically* display the result of
 pure functions, property or not.

I agree with this. A property should only be callable by the debugger if it is pure. I don't think properties should be required to be pure, because pure functions are far too restrictive for properties. Note that in other debuggers which debug code that is fully runtime inspectable, such as Visual C#'s debugger, the IDE will tell you if evaluating a property will result in an object change, so they must mark the property somehow. I think the other reasons for having property syntax are much more important than this. -Steve
Jul 26 2009
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 24 Jul 2009 22:58:33 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Rainer Deyke wrote:
 Ary Borenszweig wrote:
 Maybe what scares Walter is a whole new syntax for properties. If at
 least you could say which functions are properties and which are not,
 that would be a small change and it'll make it possible for other
 things. Something like:

 int property foo(); // getter
 int property foo(int value); // setter

int getfoo(); // getter int setfoo(int); // setter

This is pretty clean, and in keep with the opXxx approach. Actually how about defining property foo by defining opGet_foo and opSet_foo.

I would be OK with defining properties any of these ways. Although the definition of properties is ugly, it's the usability and meaning which are most important. Using opGet and opSet is probably the better method, since nobody is going to name their normal members that way. In fact, I think C++.Net did something similar in earlier versions. Something like to call or define properties you defined the function get_propname and set_propname. -Steve
Jul 26 2009
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 24 Jul 2009 17:40:37 -0400, Walter Bright  
<newshound1 digitalmars.com> wrote:

 Ary Borenszweig wrote:
 Maybe what scares Walter is a whole new syntax for properties.

It doesn't scare me. It's trivial to add more syntax. It's just that D is complex enough - there needs to be some very good reasons for adding more syntax that has apparently zero semantic information that would be different from the usual function syntax.

OK, so you don't like the idea of adding dedicated properties. What is *your* solution to forbidding abuses like this: writefln = "hi"; ??? -Steve
Jul 27 2009
prev sibling next sibling parent Sergey Gromov <snake.scaly gmail.com> writes:
Wed, 22 Jul 2009 23:10:53 +0200, Michiel Helvensteijn wrote:

 * Tuples (no dedicated syntax, no parallel assignment, no non-flattening
 tuples without workarounds, no returning tuples)

I'm planning to write a DIP on better tuple support. Here is a brief overview of my ideas. I think I'll blog a bit more before filing an actual DIP. http://snakecoder.wordpress.com/2009/07/28/language-support-for-tuples-in-d
Jul 27 2009
prev sibling parent language_fan <foo bar.com.invalid> writes:
Wed, 22 Jul 2009 16:20:36 -0700, Walter Bright thusly wrote:

 Jarrett Billingsley wrote:
 Ha.  Had D differed *too* much from C++, then we'd run the risk of
 scaring off the C++ snobs simply because it wasn't familiar enough to
 them.

It's a good point. Radically different languages tend to fail simply because few are willing to expend the effort to learn it. This is why Haskell will never catch on.

Do you think it is the syntax or the semantics that is the cause? D is getting closer and closer to languages like Haskell. You can fit in many of the missing features without a sweat, but some fundamental parts of the languages already are contradictory. Some ideas: add tuples, algebraic data types, higher order types, existential and universal quantification, dynamic types, pattern matching, type classes, monad comprehensions, built-in currying, and guards. Maybe you don't see it as a problem yet, but D seems to suffer from serious featuritis; the philosophy seems to be: if some feature is implementable but yet unimplemented, it will be implemented. More features creep in until the language sinks. Isn't it too early to state whether Haskell will never catch on? Will D ever catch on? Both communities have grown since the births of the languages.
Jul 29 2009
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Walter Bright wrote:
 http://www.reddit.com/r/programming/comments/93jh5/ask_proggit_the_d_program
ing_language_looks/ 

I noticed some people complain about installation difficulties, is there progress on the community project for writing installer for the three major OSs? Andrei
Jul 22 2009
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wed, Jul 22, 2009 at 06:27:50PM -0500, Andrei Alexandrescu wrote:
 I noticed some people complain about installation difficulties, is there 
 progress on the community project for writing installer for the three 
 major OSs?

I think the installation difficulties are the result of poor instructions (especially on Linux), not anything technical. The website talks about copying files places. This isn't necessary: the way it works is to unzip it and go. It doesn't get any simpler, but the instructions don't really reflect that. I actually got a private email from a new D user over the weekend talking about how hard it is on Linux. I replied with my method: 1) Make helper scripts in /usr/bin with this content: $ cat /usr/bin/dmd #!/bin/bash /lib/ld-linux.so.2 /home/me/d/dmd2/linux/bin/dmd $* 2) Download the DMD zip from the changelog page into the path your script references (/home/me/d in my example). 3) Unzip it. 4) Have fun coding! (Note you can do something very similar on Windows with a helper .bat file.) That's how easy installing DMD is, but this guy, and many others, don't see it that way. I blame this page: http://www.digitalmars.com/d/2.0/dmd-linux.html#installation The Windows page isn't much better. That is much harder and less clear than it needs to be. I really think fixing those pages to have simpler, clearer instructions will make the requests for installers and packages go away.
 
 Andrei

-- Adam D. Ruppe http://arsdnet.net
Jul 22 2009
next sibling parent Walter Bright <newshound1 digitalmars.com> writes:
Adam D. Ruppe wrote:
 That's how easy installing DMD is, but this guy, and many others, don't
 see it that way. I blame this page:
 http://www.digitalmars.com/d/2.0/dmd-linux.html#installation
 
 The Windows page isn't much better.

Please post patches to bugzilla!
Jul 22 2009
prev sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Adam D. Ruppe" <destructionator gmail.com> wrote in message 
news:mailman.131.1248306024.14071.digitalmars-d puremagic.com...
 That's how easy installing DMD is, but this guy, and many others, don't
 see it that way. I blame this page:
 http://www.digitalmars.com/d/2.0/dmd-linux.html#installation

Really? That surprises me. I consider myself relatively green when it comes to Linux, and I've never once tried to use/install DMD on Linux (yet), or looked at that page before, but for Linux that looks pretty darn easy. Not apt-get easy of course, but even I've dealt with far worse than this. Not that it couldn't or shouldn't be improved, of course, but if someone is complaining that it's *dmd* that's too hard to install on Linux, then it sounds like they're in for a rather rough ride period ;)
Jul 23 2009
parent reply Michiel Helvensteijn <m.helvensteijn.remove gmail.com> writes:
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
Jul 23 2009
parent naryl <cy ngs.ru> writes:
Michiel Helvensteijn Wrote:
 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.

Available versions: (~)1.016!m!s (~)2.008-r1!m!s You can use this overlay for the latest versions: http://www.assembla.com/wiki/show/d-overlay We usually update it in one day to one week from dmd release.
Jul 23 2009
prev sibling next sibling parent Michel Fortin <michel.fortin michelf.com> writes:
On 2009-07-22 19:27:50 -0400, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 Walter Bright wrote:
 http://www.reddit.com/r/programming/comments/93jh5/ask_proggit_the_d_programming_language_looks/


I
 

progress on the community project for writing installer for the three major OSs?

My plan currently is to improve D for Xcode, make it work with DMD, create one or two project templates for D to display when you create a new project from Xcode, patch Apple's version of GDB to have better demangling support, and create an nice installer for all of this, ideally bundled with DMD 1 and 2 (if Walter permits). That should fix the install and toolchain problem on Mac OS X in a nice way. I plan to have this done by mid-August. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jul 22 2009
prev sibling next sibling parent reply Jesse Phillips <jessekphillips gmail.com> writes:
On Wed, 22 Jul 2009 18:27:50 -0500, Andrei Alexandrescu wrote:

 Walter Bright wrote:
 http://www.reddit.com/r/programming/comments/93jh5/


 
 I noticed some people complain about installation difficulties, is there
 progress on the community project for writing installer for the three
 major OSs?
 
 Andrei

I'm intending a rework of: http://www.prowiki.org/wiki4d/wiki.cgi?D__Tutorial/InstallingDCompiler but haven't got around to it and can only cover Linux and Windows. The end result will be at: http://www.prowiki.org/wiki4d/wiki.cgi?D__Tutorial/StartingWithD/Compiler/ DMD
Jul 22 2009
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Jesse Phillips wrote:
 On Wed, 22 Jul 2009 18:27:50 -0500, Andrei Alexandrescu wrote:
 
 Walter Bright wrote:
 http://www.reddit.com/r/programming/comments/93jh5/


 I noticed some people complain about installation difficulties, is there
 progress on the community project for writing installer for the three
 major OSs?

 Andrei

I'm intending a rework of: http://www.prowiki.org/wiki4d/wiki.cgi?D__Tutorial/InstallingDCompiler but haven't got around to it and can only cover Linux and Windows. The end result will be at: http://www.prowiki.org/wiki4d/wiki.cgi?D__Tutorial/StartingWithD/Compiler/ DMD

Thanks, we need more of that stuff. I think this is a common experience (pasted from the reddit discussion): ========== i couldn't manage to get the command line toolchain up and running in linux either. yes, part of it was me being lazy, but there really is no good documentation saying "this is where your D installation needs to go, these are the environment variables you need, this is how to write a makefile or equivalent, this is the filesystem layout the build tool expects, this is how to use a c library, etc". ========== A while ago Walter put a good amount of work into accelerating code generation by avoiding writing object files to disk. He mentioned that that's a nice feature that old and new users will notice. I agree with that, but I also think installation has a huge importance. Having streamlined code generation but a crappy installer is like showing up at a first date pocketing a condom, but wearing an MSDN conference T-shirt. Andrei
Jul 22 2009
prev sibling next sibling parent Jesse Phillips <jessekphillips gmail.com> writes:
On Wed, 22 Jul 2009 22:19:29 -0500, Andrei Alexandrescu wrote:

 Jesse Phillips wrote:
 On Wed, 22 Jul 2009 18:27:50 -0500, Andrei Alexandrescu wrote:
 
 Walter Bright wrote:
 http://www.reddit.com/r/programming/comments/93jh5/


 I noticed some people complain about installation difficulties, is
 there progress on the community project for writing installer for the
 three major OSs?

 Andrei

I'm intending a rework of: http://www.prowiki.org/wiki4d/wiki.cgi?D__Tutorial/InstallingDCompiler but haven't got around to it and can only cover Linux and Windows. The end result will be at: http://www.prowiki.org/wiki4d/wiki.cgi?D__Tutorial/StartingWithD/


 DMD

Thanks, we need more of that stuff. I think this is a common experience (pasted from the reddit discussion): ========== i couldn't manage to get the command line toolchain up and running in linux either. yes, part of it was me being lazy, but there really is no good documentation saying "this is where your D installation needs to go, these are the environment variables you need, this is how to write a makefile or equivalent, this is the filesystem layout the build tool expects, this is how to use a c library, etc". ========== A while ago Walter put a good amount of work into accelerating code generation by avoiding writing object files to disk. He mentioned that that's a nice feature that old and new users will notice. I agree with that, but I also think installation has a huge importance. Having streamlined code generation but a crappy installer is like showing up at a first date pocketing a condom, but wearing an MSDN conference T-shirt. Andrei

Oh, I know, I posted this response: http://www.reddit.com/r/programming/comments/93jh5/ ask_proggit_the_d_programming_language_looks/c0bbbs5 As for the needing more of it, we actually have too much. http://www.prowiki.org/wiki4d/wiki.cgi?EvaluationGuide http://www.prowiki.org/wiki4d/wiki.cgi?HowToGentoo http://www.prowiki.org/wiki4d/wiki.cgi?HowToUbuntu The trend seems to be, make your own, reference the old, and have everything outdated and complicated. There is a lot of good information, but it has to be presented properly with a concentrated effort (Kind of like the community being stretched across D1/Tango/D2).
Jul 22 2009
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 7/23/09 1:27 AM, Andrei Alexandrescu wrote:
 Walter Bright wrote:
 http://www.reddit.com/r/programming/comments/93jh5/ask_proggit_the_d_programming_language_looks/

I noticed some people complain about installation difficulties, is there progress on the community project for writing installer for the three major OSs? Andrei

Yes: http://www.dsource.org/projects/dmd-installer I'm still waiting for Walter to add the osx installer to the dmd download page.
Jul 23 2009
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2009-07-23 05:37:24 -0400, Jacob Carlborg <doob me.com> said:

 Yes: http://www.dsource.org/projects/dmd-installer
 I'm still waiting for Walter to add the osx installer to the dmd download page.

Speaking of that OS X DMD installer, are you sure installing it at /usr/share/dmd/ is a good idea? Normally /usr/share is reserved for architecture-independent data[1], not executable files. What about /usr/local/dmd with symlinks in /usr/local/bin for executables /usr/local/lib for phobos and druntime and /usr/local/man for man pages. Or perhaps install /Library/D/{dmd,dmd2} so the files are more user accessible and easy to change if you got the zip archive (/usr is a hidden dir on Mac OS X). If I'm not mistaken, both your D1 and D2 installer install at the same location and they will overwrite each other. I'd much prefer if D2 and D1 could coexist without having to go with a special installer or custom installation instructions. Otherwise it'll be hard for me to offer the choice between D1 and D2 in Xcode (and I certainly do want that choice to be available). Thoughts? [1]: http://www.pathname.com/fhs/2.2/fhs-4.11.html -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jul 23 2009
next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Michel Fortin wrote:
 If I'm not mistaken, both your D1 and D2 installer install at the same 
 location and they will overwrite each other. I'd much prefer if D2 and 
 D1 could coexist without having to go with a special installer or custom 
 installation instructions. Otherwise it'll be hard for me to offer the 
 choice between D1 and D2 in Xcode (and I certainly do want that choice 
 to be available).
 
 Thoughts?

I've been switching the directories to {dmd, dmd2} so they can coexist.
Jul 23 2009
next sibling parent reply Lutger <lutger.blijdestijn gmail.com> writes:
Jarrett Billingsley wrote:

 On Thu, Jul 23, 2009 at 1:59 PM, Walter
 Bright<newshound1 digitalmars.com> wrote:
 Michel Fortin wrote:
 If I'm not mistaken, both your D1 and D2 installer install at the same
 location and they will overwrite each other. I'd much prefer if D2 and
 D1 could coexist without having to go with a special installer or custom
 installation instructions. Otherwise it'll be hard for me to offer the
 choice between D1 and D2 in Xcode (and I certainly do want that choice
 to be available).

 Thoughts?

I've been switching the directories to {dmd, dmd2} so they can coexist.

Will you rename the DMD2 compiler to 'dmd2' as well?

That would be very convenient, please consider this.
Jul 23 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Lutger wrote:
 Jarrett Billingsley wrote:
 
 On Thu, Jul 23, 2009 at 1:59 PM, Walter
 Bright<newshound1 digitalmars.com> wrote:
 Michel Fortin wrote:
 If I'm not mistaken, both your D1 and D2 installer install at the same
 location and they will overwrite each other. I'd much prefer if D2 and
 D1 could coexist without having to go with a special installer or custom
 installation instructions. Otherwise it'll be hard for me to offer the
 choice between D1 and D2 in Xcode (and I certainly do want that choice
 to be available).

 Thoughts?



That would be very convenient, please consider this.

I think moving forward D2 will be the norm, so I suggest going with dmd1 and dmd dir names and dmd1 and dmd binary names. Andrei
Jul 23 2009
next sibling parent reply Lutger <lutger.blijdestijn gmail.com> writes:
Andrei Alexandrescu wrote:

 Lutger wrote:
 Jarrett Billingsley wrote:
 
 On Thu, Jul 23, 2009 at 1:59 PM, Walter
 Bright<newshound1 digitalmars.com> wrote:
 Michel Fortin wrote:
 If I'm not mistaken, both your D1 and D2 installer install at the same
 location and they will overwrite each other. I'd much prefer if D2 and
 D1 could coexist without having to go with a special installer or
 custom installation instructions. Otherwise it'll be hard for me to
 offer the choice between D1 and D2 in Xcode (and I certainly do want
 that choice to be available).

 Thoughts?



That would be very convenient, please consider this.

I think moving forward D2 will be the norm, so I suggest going with dmd1 and dmd dir names and dmd1 and dmd binary names. Andrei

Also fine, as long as they are different to ease more complex setups, plus it will make it much more convenient to create linux packages for this.
Jul 23 2009
parent Lutger <lutger.blijdestijn gmail.com> writes:
Bill Baxter wrote:

 On Thu, Jul 23, 2009 at 12:09 PM, Lutger<lutger.blijdestijn gmail.com>
 wrote:
 Andrei Alexandrescu wrote:

 Lutger wrote:
 Jarrett Billingsley wrote:

 On Thu, Jul 23, 2009 at 1:59 PM, Walter
 Bright<newshound1 digitalmars.com> wrote:
 Michel Fortin wrote:
 If I'm not mistaken, both your D1 and D2 installer install at the
 same location and they will overwrite each other. I'd much prefer if
 D2 and D1 could coexist without having to go with a special
 installer or custom installation instructions. Otherwise it'll be
 hard for me to offer the choice between D1 and D2 in Xcode (and I
 certainly do want that choice to be available).

 Thoughts?

coexist.


That would be very convenient, please consider this.

I think moving forward D2 will be the norm, so I suggest going with dmd1 and dmd dir names and dmd1 and dmd binary names. Andrei

Also fine, as long as they are different to ease more complex setups, plus it will make it much more convenient to create linux packages for this.

Shouldn't the strategy taken be something more akin to what multi-version packages like python and perl already do? They don't just automatically rename old python to be python<OldVersion> after every new version comes out. On windows they call it python.exe but put it in a different directory. On versions of linux I think there are some fancy schemes for setting up symlinks to particular versions to be the default. Can't recall what that system was called. "Defaults" or something like it. Anyway, seems like on linux dmd should work with that rather than just going and changing the names of exes according to whim. --bb

Yes, I admit this is the preferred and in the end only sane way of doing it. (i have set it up like this come to think of it, don't know why). For people for which there is no default because they do work with both it is less nice though, imho.
Jul 23 2009
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Jarrett Billingsley wrote:
 Yeah, let me know when that happens.  Until then, I'd like to continue
 to be able to use my build tools that were designed for D1 without
 having to modify all their config files.

I don't know what build tools you're using, but consider make: ------ win32.mak --------- DMD=\dmd\windows\bin\dmd target : foo.obj foo.obj : foo.d $(DMD) -c foo -------------------------- Now, we can drive it with a makefile that customizes the macros like so: ------ makefile ---------- target: make -fwin32.mak DMD=\dmd2\windows\bin\dmd -------------------------- I use this technique a lot. You can also have makefiles recursively call themselves and reset the macros: ---------- makefile -------- DMD=\dmd\windows\bin\dmd target : foo.obj target2: make target DMD=\dmd2\windows\bin\dmd foo.obj : foo.d $(DMD) -c foo ----------------------------
Jul 23 2009
next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Jarrett Billingsley wrote:
 This "D" programming language is great because it obviates make.

Ok, now about make's ability to switch compilers without having to edit config files?
Jul 23 2009
next sibling parent grauzone <none example.net> writes:
Walter Bright wrote:
 Jarrett Billingsley wrote:
 This "D" programming language is great because it obviates make.

Ok, now about make's ability to switch compilers without having to edit config files?

So that's the killer feature of make? I don't know about you, but I always use only one D compiler. It's in $PATH, and the actual binary can be I-don't-know-where. Now nobody is saying that dsss/rebuild/bud/xfbuild eliminate _all_ uses of make. But for a typical D project, writing makefiles is pure bloat and a waste of time.
Jul 23 2009
prev sibling parent reply Don <nospam nospam.com> writes:
Walter Bright wrote:
 Jarrett Billingsley wrote:
 This "D" programming language is great because it obviates make.

Ok, now about make's ability to switch compilers without having to edit config files?

I don't do it that way. I can't imagine when you would mix D1 and D2 in a single build. Instead, I have a set of trivial scripts to change the symlink for the 'dmd' directory. Nothing else needs to be aware of the compiler version. From then on, I just use bud. I'll be pretty annoyed if the D2 compiler changes its name to DMD2.
Jul 24 2009
parent Michel Fortin <michel.fortin michelf.com> writes:
On 2009-07-24 03:51:50 -0400, Don <nospam nospam.com> said:

 Walter Bright wrote:
 Jarrett Billingsley wrote:
 This "D" programming language is great because it obviates make.

Ok, now about make's ability to switch compilers without having to edit config files?

I don't do it that way. I can't imagine when you would mix D1 and D2 in a single build. Instead, I have a set of trivial scripts to change the symlink for the 'dmd' directory. Nothing else needs to be aware of the compiler version. From then on, I just use bud. I'll be pretty annoyed if the D2 compiler changes its name to DMD2.

My opinion is that the best way forward is to have dmd1, dmd2, and a symlink called dmd to one or the other. That way in a makefile you can explicitly request for one or the other if you want, but you don't have to: you can switch at will. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jul 24 2009
prev sibling parent =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Walter Bright wrote:

 I don't know what build tools you're using, but consider make:
 
 ------ win32.mak ---------
 
 DMD=\dmd\windows\bin\dmd
 
 target : foo.obj
 
 foo.obj : foo.d
     $(DMD) -c foo
 --------------------------

And for GNU make, it uses the variables $(DC) and $(DMD) where DC is the D compiler (like CC) and DMD the wrapper. The annoying part is changing the DFLAGS for the compiler, and/or translating any needed linker flags for the wrapper... ifeq ("$(COMPILER)","DMD") DC ?= dmd DMD ?= dmd DFLAGS = -O -g version=-version output=-of$ endif ifeq ("$(COMPILER)","LDC") DC ?= ldc DMD ?= ldmd DFLAGS = -O version=-d-version output=-of=$ endif ifeq ("$(COMPILER)","GDC") DC ?= gdc DMD ?= gdmd DFLAGS = -O2 -g version=-fversion output=-o $ endif %.o:%.d $(DC) $(DFLAGS) -c $(output) $< --anders
Aug 01 2009
prev sibling next sibling parent Walter Bright <newshound1 digitalmars.com> writes:
Jarrett Billingsley wrote:
 Will you rename the DMD2 compiler to 'dmd2' as well?

No. If they're in different directory trees, there's no reason to. After all, that's the whole point of having directories!
Jul 23 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Thu, Jul 23, 2009 at 4:03 PM, Jarrett
Billingsley<jarrett.billingsley gmail.com> wrote:
 On Thu, Jul 23, 2009 at 3:54 PM, Walter
 Bright<newshound1 digitalmars.com> wrote:
 Jarrett Billingsley wrote:
 This "D" programming language is great because it obviates make.

Ok, now about make's ability to switch compilers without having to edit config files?

So editing every make file you have is better? =A0:P

Ah, nevermind.
Jul 23 2009
prev sibling parent Michel Fortin <michel.fortin michelf.com> writes:
On 2009-07-23 13:59:46 -0400, Walter Bright <newshound1 digitalmars.com> said:

 Michel Fortin wrote:
 If I'm not mistaken, both your D1 and D2 installer install at the same 
 location and they will overwrite each other. I'd much prefer if D2 and 
 D1 could coexist without having to go with a special installer or 
 custom installation instructions. Otherwise it'll be hard for me to 
 offer the choice between D1 and D2 in Xcode (and I certainly do want 
 that choice to be available).
 
 Thoughts?

I've been switching the directories to {dmd, dmd2} so they can coexist.

I know. But the OS X installer I see on dsource doesn't seem to reflect that: it always install at /usr/share/dmd/ (and /usr/share is a stange choice too). Now that I look at it, it seems to predate the switch to separate directories. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Jul 23 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Thu, Jul 23, 2009 at 3:54 PM, Walter
Bright<newshound1 digitalmars.com> wrote:
 Jarrett Billingsley wrote:
 This "D" programming language is great because it obviates make.

Ok, now about make's ability to switch compilers without having to edit config files?

So editing every make file you have is better? :P
Jul 23 2009
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 7/23/09 12:32 PM, Michel Fortin wrote:
 On 2009-07-23 05:37:24 -0400, Jacob Carlborg <doob me.com> said:

 Yes: http://www.dsource.org/projects/dmd-installer
 I'm still waiting for Walter to add the osx installer to the dmd
 download page.

Speaking of that OS X DMD installer, are you sure installing it at /usr/share/dmd/ is a good idea? Normally /usr/share is reserved for architecture-independent data[1], not executable files. What about /usr/local/dmd with symlinks in /usr/local/bin for executables /usr/local/lib for phobos and druntime and /usr/local/man for man pages. Or perhaps install /Library/D/{dmd,dmd2} so the files are more user accessible and easy to change if you got the zip archive (/usr is a hidden dir on Mac OS X). If I'm not mistaken, both your D1 and D2 installer install at the same location and they will overwrite each other. I'd much prefer if D2 and D1 could coexist without having to go with a special installer or custom installation instructions. Otherwise it'll be hard for me to offer the choice between D1 and D2 in Xcode (and I certainly do want that choice to be available). Thoughts? [1]: http://www.pathname.com/fhs/2.2/fhs-4.11.html

Sorry I haven't replied sooner I've been on vacation. I looked at a gdc installer and looked where it placed the compiler and did the same. I don't know where it's best to place the compiler. /Jacob Carlborg
Jul 31 2009
parent reply =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Jacob Carlborg wrote:

 Speaking of that OS X DMD installer, are you sure installing it at
 /usr/share/dmd/ is a good idea? [...]

did the same. I don't know where it's best to place the compiler.

You can use /opt/dmd and /opt/dmd2, if you don't want to use the regular file hierarchy in hier(7) DMD = /opt/dmd2/osx/bin/dmd Or you can use e.g. /usr/local/bin and rename to dmd2 and dmd2.conf (which takes some trickery...) DMD = dmd2 --anders
Aug 01 2009
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2009-08-01 04:41:38 -0400, Anders F BjŲrklund <afb algonet.se> said:

 Jacob Carlborg wrote:
 
 Speaking of that OS X DMD installer, are you sure installing it at
 /usr/share/dmd/ is a good idea? [...]

did the same. I don't know where it's best to place the compiler.

You can use /opt/dmd and /opt/dmd2, if you don't want to use the regular file hierarchy in hier(7) DMD = /opt/dmd2/osx/bin/dmd Or you can use e.g. /usr/local/bin and rename to dmd2 and dmd2.conf (which takes some trickery...) DMD = dmd2

In hier(7), it says that "/usr/local" is for "executables, libraries, etc. not included by the basic operating system", so I guess DMD fits this quite well. I'm preparing an installer for D for Xcode and made it install DMD at /usr/local/dmd and /usr/local/dmd2, with symlinks at /usr/local/bin/dmd (system-prefered version) /usr/local/bin/dmd1 (1.x) and /usr/local/bin/dmd2 (2.x). This makes it easy to choose the version you want within Xcode. For some reasons, the symlinks works fine with Xcode. But they aren't working from the command line (dmd complains that it can't find object.o). I've made a small C program to replace the symlink: #include <unistd.h> int main(unsigned int argc, char **argv) { argv[0] = "/usr/local/dmd/osx/bin/dmd"; execv("/usr/local/dmd/osx/bin/dmd", argv); } No more problem from the command line. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Aug 01 2009
next sibling parent =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Michel Fortin wrote:

 You can use /opt/dmd and /opt/dmd2, if you don't
 want to use the regular file hierarchy in hier(7)


 In hier(7), it says that "/usr/local" is for "executables, libraries, 
 etc. not included by the basic operating system", so I guess DMD fits 
 this quite well.

I normally* use the regular /usr/local/bin and /usr/local/lib and so on, when using /usr/local and otherwise /opt for various vendor layouts... But I suppose /usr/local/dmd "works" just fine. Renaming dmd to dmd1 probably makes sense, once dmd2 is released, and switching with the symlink. Was using something similar to switch between the Phobos and Tango libraries in earlier versions. --anders * GDC was using /usr/bin, since it was sharing some files with /usr/bin/gcc already anyway.
Aug 01 2009
prev sibling parent reply Sergey Gromov <snake.scaly gmail.com> writes:
Sat, 1 Aug 2009 07:55:08 -0400, Michel Fortin wrote:

 On 2009-08-01 04:41:38 -0400, Anders F BjŲrklund <afb algonet.se> said:
 
 Jacob Carlborg wrote:
 
 Speaking of that OS X DMD installer, are you sure installing it at
 /usr/share/dmd/ is a good idea? [...]

did the same. I don't know where it's best to place the compiler.

You can use /opt/dmd and /opt/dmd2, if you don't want to use the regular file hierarchy in hier(7) DMD = /opt/dmd2/osx/bin/dmd Or you can use e.g. /usr/local/bin and rename to dmd2 and dmd2.conf (which takes some trickery...) DMD = dmd2

In hier(7), it says that "/usr/local" is for "executables, libraries, etc. not included by the basic operating system", so I guess DMD fits this quite well. I'm preparing an installer for D for Xcode and made it install DMD at /usr/local/dmd and /usr/local/dmd2, with symlinks at /usr/local/bin/dmd (system-prefered version) /usr/local/bin/dmd1 (1.x) and /usr/local/bin/dmd2 (2.x). This makes it easy to choose the version you want within Xcode. For some reasons, the symlinks works fine with Xcode. But they aren't working from the command line (dmd complains that it can't find object.o). I've made a small C program to replace the symlink: #include <unistd.h> int main(unsigned int argc, char **argv) { argv[0] = "/usr/local/dmd/osx/bin/dmd"; execv("/usr/local/dmd/osx/bin/dmd", argv); } No more problem from the command line.

Here's a nice document about directory layout in UNIX-like OSes: http://www.pathname.com/fhs/pub/fhs-2.3.html I think MacOS should follow this layout at least in part. In particular /usr/local/ is used for locally installed packages which otherwise respect the standard directory structure found in / or /usr/. That is, binaries go into /usr/local/bin/, libraries in /usr/local/lib/ etc. If a package wants to keep its own structure it's supposted to go into /opt/, like /opt/dmd2/whatever.
Aug 01 2009
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2009-08-01 20:15:41 -0400, Sergey Gromov <snake.scaly gmail.com> said:

 Here's a nice document about directory layout in UNIX-like OSes:
 
 http://www.pathname.com/fhs/pub/fhs-2.3.html
 
 I think MacOS should follow this layout at least in part.  In particular
 /usr/local/ is used for locally installed packages which otherwise
 respect the standard directory structure found in / or /usr/.  That is,
 binaries go into /usr/local/bin/, libraries in /usr/local/lib/ etc.  If
 a package wants to keep its own structure it's supposted to go into
 /opt/, like /opt/dmd2/whatever.

Well, given that this is Mac OS X we could also put this in /Library/D/dmd and /Library/D/dmd2, two directories which aren't hidden by the file browser. Then put symlinks in /usr/local/bin and /usr/local/lib pointing there. Users will then be able to upgrade without an installer by simply replacing the folder at /Library/D/dmd & dmd2 with a newly downloaded one. I think that's better than /opt, as /opt isn't present by default on Mac OS X, isn't hidden by the Finder when present (contrary to all other "UNIX" directories at the root) and thus would look a little out of place on the hard drive. And there's already /Library/Python, /Library/PHP and /Library/Ruby in that /Library directory to set a precedent. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Aug 01 2009
next sibling parent =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Michel Fortin wrote:

 Well, given that this is Mac OS X we could also put this in 
 /Library/D/dmd and /Library/D/dmd2, two directories which aren't hidden 
 by the file browser. Then put symlinks in /usr/local/bin and 
 /usr/local/lib pointing there. Users will then be able to upgrade 
 without an installer by simply replacing the folder at /Library/D/dmd & 
 dmd2 with a newly downloaded one.

That's how the zip files work, yes ? Possibly PATH instead of symlinks. Main difference between /Library/D and ~ is that it requires "admin" privileges while anyone can install into ~/dmd (even if not an admin) The /usr installer for GDC requires root, so it auths as admin first. Then again that gdc needed to be installed into system gcc locations, so it wasn't really relocatable like the upstream tarball from dgcc.
 I think that's better than /opt, as /opt isn't present by default on Mac 
 OS X, isn't hidden by the Finder when present (contrary to all other 
 "UNIX" directories at the root) and thus would look a little out of 
 place on the hard drive. And there's already /Library/Python, 
 /Library/PHP and /Library/Ruby in that /Library directory to set a 
 precedent.

I think /Library/{Python,Perl,Ruby} are mostly used for user modules ? The actual interpreters are normally installed under /usr or /usr/local Possibly symlinked, in case of a framework installation (like Python's) You could also use the /Developer hierarchy for installing compilers. But I would use a "commandline" directory for a commandline tool, rather than having it Finder-browsable. It might make sense for docs and such. --anders
Aug 02 2009
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 8/2/09 03:40, Michel Fortin wrote:
 On 2009-08-01 20:15:41 -0400, Sergey Gromov <snake.scaly gmail.com> said:

 Here's a nice document about directory layout in UNIX-like OSes:

 http://www.pathname.com/fhs/pub/fhs-2.3.html

 I think MacOS should follow this layout at least in part. In particular
 /usr/local/ is used for locally installed packages which otherwise
 respect the standard directory structure found in / or /usr/. That is,
 binaries go into /usr/local/bin/, libraries in /usr/local/lib/ etc. If
 a package wants to keep its own structure it's supposted to go into
 /opt/, like /opt/dmd2/whatever.

Well, given that this is Mac OS X we could also put this in /Library/D/dmd and /Library/D/dmd2, two directories which aren't hidden by the file browser. Then put symlinks in /usr/local/bin and /usr/local/lib pointing there. Users will then be able to upgrade without an installer by simply replacing the folder at /Library/D/dmd & dmd2 with a newly downloaded one. I think that's better than /opt, as /opt isn't present by default on Mac OS X, isn't hidden by the Finder when present (contrary to all other "UNIX" directories at the root) and thus would look a little out of place on the hard drive. And there's already /Library/Python, /Library/PHP and /Library/Ruby in that /Library directory to set a precedent.

I think I like /usr/local best. /Library is used for resources: http://developer.apple.com/documentation/MacOSX/Conceptual/BPFileSystem/Articles/LibraryDirectory.html#//apple_ref/doc/uid/20002282-BAJHCHJI "The Library directory is a special directory used to store application-specific and system-specific resources". What about /Applications?
Aug 03 2009
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2009-08-03 06:59:14 -0400, Jacob Carlborg <doob me.com> said:

 I think I like /usr/local best.

I like /usr/local best too.
 /Library is used for resources: 
 http://developer.apple.com/documentation/MacOSX/Conceptual/BPFileSystem/Articles/LibraryDirectory.html#//apple_ref/doc/uid/20002282-BAJHCHJI

"The
 
 Library directory is a special directory used to store 
 application-specific and system-specific resources".

Indeed.
 What about /Applications?

I thought that was for applications. DMD isn't an appliction, it's a command-line tool. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Aug 03 2009
parent reply =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Michel Fortin wrote:
 I think I like /usr/local best.

I like /usr/local best too.

The objection (if any) was mostly about "/usr/local/dmd/osx/bin" vs /usr/local/bin, but using /usr/local/{dmd,dmd2} should be OK.
 Library directory is a special directory used to store
 application-specific and system-specific resources".

Indeed.

Such as the language extensions in /Library/Perl and /Library/Python already mentioned, elsewhere in /usr/lib/perl5 and /usr/lib/python2.X
 What about /Applications?

I thought that was for applications. DMD isn't an appliction, it's a command-line tool.

And even if it was, it would probably go in /Developer anyway ? Like /Developer/Applications/CodeBlocks.app does, for instance. --anders
Aug 03 2009
parent reply Jacob Carlborg <doob me.com> writes:
On 8/3/09 14:32, Anders F BjŲrklund wrote:
 Michel Fortin wrote:
 I think I like /usr/local best.

I like /usr/local best too.

The objection (if any) was mostly about "/usr/local/dmd/osx/bin" vs /usr/local/bin, but using /usr/local/{dmd,dmd2} should be OK.

I was thinking about using /usr/local/{dmd,dmd2} and then create symlinks to /usr/local/bin. But that will create problems with the dmd.conf because it also needs a symlink in /usr/local/bin and then the conf file for dmd and dmd1 will conflict.
 Library directory is a special directory used to store
 application-specific and system-specific resources".

Indeed.

Such as the language extensions in /Library/Perl and /Library/Python already mentioned, elsewhere in /usr/lib/perl5 and /usr/lib/python2.X
 What about /Applications?

I thought that was for applications. DMD isn't an appliction, it's a command-line tool.

And even if it was, it would probably go in /Developer anyway ? Like /Developer/Applications/CodeBlocks.app does, for instance. --anders

Aug 07 2009
next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2009-08-07 08:05:04 -0400, Jacob Carlborg <doob me.com> said:

 On 8/3/09 14:32, Anders F BjŲrklund wrote:
 Michel Fortin wrote:
 I think I like /usr/local best.

I like /usr/local best too.

The objection (if any) was mostly about "/usr/local/dmd/osx/bin" vs /usr/local/bin, but using /usr/local/{dmd,dmd2} should be OK.

I was thinking about using /usr/local/{dmd,dmd2} and then create symlinks to /usr/local/bin. But that will create problems with the dmd.conf because it also needs a symlink in /usr/local/bin and then the conf file for dmd and dmd1 will conflict.

The solution is to create a "symlink program" and drop it in /usr/local/bin. I know it works; I wrote one to do just that: #include <unistd.h> int main(unsigned int argc, char **argv) { argv[0] = "/usr/local/dmd/osx/bin/dmd"; execv("/usr/local/dmd/osx/bin/dmd", argv); } -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Aug 07 2009
parent reply =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Michel Fortin wrote:
 The objection (if any) was mostly about "/usr/local/dmd/osx/bin"
 vs /usr/local/bin, but using /usr/local/{dmd,dmd2} should be OK.

I was thinking about using /usr/local/{dmd,dmd2} and then create symlinks to /usr/local/bin. But that will create problems with the dmd.conf because it also needs a symlink in /usr/local/bin and then the conf file for dmd and dmd1 will conflict.

The solution is to create a "symlink program" and drop it in /usr/local/bin. I know it works; I wrote one to do just that: #include <unistd.h> int main(unsigned int argc, char **argv) { argv[0] = "/usr/local/dmd/osx/bin/dmd"; execv("/usr/local/dmd/osx/bin/dmd", argv); }

I did that for my linux package, but used shell instead. Then the dmd.conf was a link back to the real config file, to /etc/dmd.conf for dmd and to /etc/dmd2.conf for dmd2... /usr/bin/dmd2 -> /usr/libexec/dmd2/dmd /usr/libexec/dmd2/dmd.conf -> /etc/dmd2.conf Then the conf files didn't conflict anymore. --anders
Aug 07 2009
parent reply Jacob Carlborg <doob me.com> writes:
On 8/7/09 17:32, Anders F BjŲrklund wrote:
 Michel Fortin wrote:
 The objection (if any) was mostly about "/usr/local/dmd/osx/bin"
 vs /usr/local/bin, but using /usr/local/{dmd,dmd2} should be OK.

I was thinking about using /usr/local/{dmd,dmd2} and then create symlinks to /usr/local/bin. But that will create problems with the dmd.conf because it also needs a symlink in /usr/local/bin and then the conf file for dmd and dmd1 will conflict.

The solution is to create a "symlink program" and drop it in /usr/local/bin. I know it works; I wrote one to do just that: #include <unistd.h> int main(unsigned int argc, char **argv) { argv[0] = "/usr/local/dmd/osx/bin/dmd"; execv("/usr/local/dmd/osx/bin/dmd", argv); }

I did that for my linux package, but used shell instead. Then the dmd.conf was a link back to the real config file, to /etc/dmd.conf for dmd and to /etc/dmd2.conf for dmd2... /usr/bin/dmd2 -> /usr/libexec/dmd2/dmd /usr/libexec/dmd2/dmd.conf -> /etc/dmd2.conf Then the conf files didn't conflict anymore. --anders

If I understand you correctly you have a symlink "/usr/bin/dmd2" pointing to "/usr/libexec/dmd2/dmd" and then a symlink "/usr/libexec/dmd2/dmd.conf" pointing to "/etc/dmd2.conf". I can't see how that would work, correct me if I'm wrong: dmd will only search for a conf file named dmd.conf in the same path as the dmd executable, in /etc or in the user home directory. dmd will not find the file in /etc because it's named "dmd2.conf". The file "usr/libexec/dmd2/dmd.conf" will not work because the dmd.conf will needs to be in the same directory as the symlink and not the actual executable, this was the first I tried. /Jacob Carlborg
Aug 12 2009
parent reply =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Jacob Carlborg wrote:

 The solution is to create a "symlink program" and drop it in
 /usr/local/bin. I know it works; I wrote one to do just that:

 #include <unistd.h>

 int main(unsigned int argc, char **argv) {
 argv[0] = "/usr/local/dmd/osx/bin/dmd";
 execv("/usr/local/dmd/osx/bin/dmd", argv);
 }

I did that for my linux package, but used shell instead. Then the dmd.conf was a link back to the real config file, to /etc/dmd.conf for dmd and to /etc/dmd2.conf for dmd2... /usr/bin/dmd2 -> /usr/libexec/dmd2/dmd /usr/libexec/dmd2/dmd.conf -> /etc/dmd2.conf Then the conf files didn't conflict anymore. --anders

If I understand you correctly you have a symlink "/usr/bin/dmd2" pointing to "/usr/libexec/dmd2/dmd" and then a symlink "/usr/libexec/dmd2/dmd.conf" pointing to "/etc/dmd2.conf". I can't see how that would work, correct me if I'm wrong: dmd will only search for a conf file named dmd.conf in the same path as the dmd executable, in /etc or in the user home directory. dmd will not find the file in /etc because it's named "dmd2.conf". The file "usr/libexec/dmd2/dmd.conf" will not work because the dmd.conf will needs to be in the same directory as the symlink and not the actual executable, this was the first I tried.

Right, /usr/libexec/dmd2/dmd is the actual program. And /usr/bin/dmd2 was a wrapper that exec'd it... #!/bin/sh exec /usr/libexec/dmd2/dmd "$*" Guess one could use the same workaround for moving dmd over to "dmd1", and make dmd into a symlink ? dmd -> dmd1 # depending on dmd -> dmd2 # your preference --anders http://www.digitalmars.com/d/archives/digitalmars/D/announce/DMD_1.029_and_2.013_releases_11949.html#N11988
Aug 12 2009
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2009-08-12 19:37:13 -0400, Anders F BjŲrklund <afb algonet.se> said:

 Guess one could use the same workaround for moving
 dmd over to "dmd1", and make dmd into a symlink ?
 
 dmd -> dmd1 # depending on
 dmd -> dmd2 # your preference

That's something I'd really like to see. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Aug 12 2009
parent =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= <afb algonet.se> writes:
Michel Fortin wrote:

 Guess one could use the same workaround for moving
 dmd over to "dmd1", and make dmd into a symlink ?

 dmd -> dmd1 # depending on
 dmd -> dmd2 # your preference

That's something I'd really like to see.

It's done the same with GCC, too: /usr/bin/gcc -> gcc-4.0 /usr/bin/gcc-3.3 /usr/bin/gcc-4.0 /usr/bin/gcc2 /usr/bin/gcc3 Was even a gcc_select(8) program. --anders PS. But now it's all gcc-4.2 instead, and with or without LLVM is the question. Of course neither of the Apple compilers works very well with GDC any longer...
Aug 13 2009
prev sibling parent Michel Fortin <michel.fortin michelf.com> writes:
On 2009-08-07 08:05:04 -0400, Jacob Carlborg <doob me.com> said:

 I was thinking about using /usr/local/{dmd,dmd2} and then create 
 symlinks to /usr/local/bin. But that will create problems with the 
 dmd.conf because it also needs a symlink in /usr/local/bin and then the 
 conf file for dmd and dmd1 will conflict.

Also, could you make symlinks for "dmd" (prefered version), "dmd1" and "dmd2" in /usr/local/bin ? This should allow projects to use explicitely dmd1 or dmd2 when needed, while the user could rebind dmd to one or the other depending on his needs. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Aug 07 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Thu, Jul 23, 2009 at 1:59 PM, Walter
Bright<newshound1 digitalmars.com> wrote:
 Michel Fortin wrote:
 If I'm not mistaken, both your D1 and D2 installer install at the same
 location and they will overwrite each other. I'd much prefer if D2 and D1
 could coexist without having to go with a special installer or custom
 installation instructions. Otherwise it'll be hard for me to offer the
 choice between D1 and D2 in Xcode (and I certainly do want that choice to be
 available).

 Thoughts?

I've been switching the directories to {dmd, dmd2} so they can coexist.

Will you rename the DMD2 compiler to 'dmd2' as well?
Jul 23 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Thu, Jul 23, 2009 at 2:23 PM, Andrei
Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:
 Lutger wrote:
 Jarrett Billingsley wrote:

 On Thu, Jul 23, 2009 at 1:59 PM, Walter
 Bright<newshound1 digitalmars.com> wrote:
 Michel Fortin wrote:
 If I'm not mistaken, both your D1 and D2 installer install at the same
 location and they will overwrite each other. I'd much prefer if D2 and
 D1 could coexist without having to go with a special installer or
 custom
 installation instructions. Otherwise it'll be hard for me to offer the
 choice between D1 and D2 in Xcode (and I certainly do want that choice
 to be available).

 Thoughts?

I've been switching the directories to {dmd, dmd2} so they can coexist.

Will you rename the DMD2 compiler to 'dmd2' as well?

That would be very convenient, please consider this.

I think moving forward D2 will be the norm, so I suggest going with dmd1 and dmd dir names and dmd1 and dmd binary names.

Yeah, let me know when that happens. Until then, I'd like to continue to be able to use my build tools that were designed for D1 without having to modify all their config files.
Jul 23 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Thu, Jul 23, 2009 at 12:09 PM, Lutger<lutger.blijdestijn gmail.com> wrote:
 Andrei Alexandrescu wrote:

 Lutger wrote:
 Jarrett Billingsley wrote:

 On Thu, Jul 23, 2009 at 1:59 PM, Walter
 Bright<newshound1 digitalmars.com> wrote:
 Michel Fortin wrote:
 If I'm not mistaken, both your D1 and D2 installer install at the same
 location and they will overwrite each other. I'd much prefer if D2 and
 D1 could coexist without having to go with a special installer or
 custom installation instructions. Otherwise it'll be hard for me to
 offer the choice between D1 and D2 in Xcode (and I certainly do want
 that choice to be available).

 Thoughts?



That would be very convenient, please consider this.

I think moving forward D2 will be the norm, so I suggest going with dmd1 and dmd dir names and dmd1 and dmd binary names. Andrei

Also fine, as long as they are different to ease more complex setups, plus it will make it much more convenient to create linux packages for this.

Shouldn't the strategy taken be something more akin to what multi-version packages like python and perl already do? They don't just automatically rename old python to be python<OldVersion> after every new version comes out. On windows they call it python.exe but put it in a different directory. On versions of linux I think there are some fancy schemes for setting up symlinks to particular versions to be the default. Can't recall what that system was called. "Defaults" or something like it. Anyway, seems like on linux dmd should work with that rather than just going and changing the names of exes according to whim. --bb
Jul 23 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Thu, Jul 23, 2009 at 12:13 PM, Walter
Bright<newshound1 digitalmars.com> wrote:
 Jarrett Billingsley wrote:
 Will you rename the DMD2 compiler to 'dmd2' as well?

No. If they're in different directory trees, there's no reason to. After all, that's the whole point of having directories!

That seems to be the way they do things in Windows, but usually they set up various extra symlinks on unix systems so that you can call a particular version of a program when there are multiple installed. Like gcc-2.95, etc. --bb
Jul 23 2009
prev sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Thu, Jul 23, 2009 at 3:22 PM, Walter
Bright<newshound1 digitalmars.com> wrote:
 Jarrett Billingsley wrote:
 Yeah, let me know when that happens. =A0Until then, I'd like to continue
 to be able to use my build tools that were designed for D1 without
 having to modify all their config files.

I don't know what build tools you're using, but consider make:

Walter, I'm pretty shocked by this response. How long have Bud and DSSS existed? D users who *don't* use them are the exception. You even patched DMD recently to make it easier for xfBuild to do its job. This "D" programming language is great because it obviates make. You should try it sometime! I think you might like it ;)
Jul 23 2009
prev sibling next sibling parent reply Knud Soerensen <4tuu4k002 sneakemail.com> writes:
Walter Bright wrote:
 http://www.reddit.com/r/programming/comments/93jh5/ask_proggit_the_d_program
ing_language_looks/ 
 

Let me start with an example. Some time ago I need a script to get and process some data. I trough why not use D, but I couldn't find a function in the standard library which would get a simple web page with http. Instead of find and downloading other libraries I switched to peal and had it running in no time. I think it is the choice of problem domain for D. Successful language are typical the first moves in a new and popular problem domain. FORTRAN - vector processing. PHP - server side web programing. Java - platform independent client side programing. etc. If you want people to switch you need provide the tools for solving this problems. To get the Fortran crowd D needs faster vector processing. To get the PHP crowd D needs libraries that support web programming. To get the java crowd, it should be possible to run platform independent D programs in you browser. etc. I know the real focus for D system programing and the C++ people. I think one of D's strongest points for people to make the switch is build in unit testing. (at least this is the strongest point for me) But the very simple implementation of unit testing in D nearly ruin the advantage it gives. (see suggestion from the wishlist below) C++ have a lot of good libraries to solve all type of problems, for me it wouldn't be a problem if I knew that the D libraries would be a much better quality. A indicator for this would be if I knew that the library was properly unit tested. A simple way to ensure that could if the compiler issued a error/warning if a function had no unit tests or contracts. What follows is some unit test suggestions from http://all-technology.com/eigenpolls/dwishlist Because I would like to hear your opinion about them. ** unit test & code separation I think it would be more useful if the code and the unit test where two separate binaries. Sometimes you need to move the production binary to another machine/environment. It would be nice if one could move the test binary with it and test that everything works. It would also allow for arguments to the test binary, so that you would be able to run a specific unit test. ** black box unit testing The d compiler should enforce black box unit tests. Which is unit tests that only use the classes exposed interface.(public, protected) Together with 100% unit test coverage it helps ensure that the code is modular,decoupled and that you can change the private parts without changing the unit tests. For those how is not ready for this high code standard, there might be a --allow-white-box switch. ** Unit test isolation I would like to be able to isolate the unit test, so that if one fail the next still runs. unittest() { test("test1") { assert(...); assert(...) } test("test1") { assert(...); assert(...) } for (i=3;i<10;i++) { test("test"~i) { assert(...); assert(...) } } } ** Unit test measurements In combination with test isolation it would be nice to have d output memory and time used in each unit test. -- Join me on CrowdNews http://crowdnews.eu/users/addGuide/42/ Facebook http://www.facebook.com/profile.php?id=1198821880 Linkedin http://www.linkedin.com/pub/0/117/a54 Mandala http://www.mandala.dk/view-profile.php4?profileID=7660
Jul 23 2009
next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Knud Soerensen wrote:
 Some time ago I need a script to get and process some data.
 I trough why not use D, but I couldn't find a function in the standard 
 library which would get a simple web page with http.
 Instead of find and downloading other libraries I switched to peal and 
 had it running in no time.
 
 I think it is the choice of problem domain for D.

I'd love to have some functions in Phobos that do this. Can you write a module and contribute it? Phobos is definitely short on a lot of networking functionality.
 I know the real focus for D system programing and the C++ people.
 
 I think one of D's strongest points for people to make the switch is 
 build in unit testing. (at least this is the strongest point for me)
 But the very simple implementation of unit testing in D nearly ruin the 
 advantage it gives. (see suggestion from the wishlist below)

Even at its very simple support, it's a huge win. It raises the bar on what is minimally acceptable, and has been responsible for a big improvement in the quality of Phobos.
 A simple way to ensure that could if the compiler issued a error/warning 
 if a function had no unit tests or contracts.

I worry that such would be crying wolf. But dmd does have a coverage analyzer built in - which I think is more useful. It'll show which lines were executed by the unit tests, and which were not.
 
 What follows is some unit test suggestions from 
 http://all-technology.com/eigenpolls/dwishlist
 Because I would like to hear your opinion about them.
 
 ** unit test & code separation
 I think it would be more useful if the code
 and the unit test where two separate binaries.
 
 Sometimes you need to move the production binary to another 
 machine/environment.
 It would be nice if one could move the test binary with it and test that 
 everything works.
 
 It would also allow for arguments to the test binary,
 so that you would be able to run a specific unit test.

I made the decision at one point that unit tests weren't there to test that the compiler generated code correctly, they were to test the logic of the user code. Hence, one does a separate build for unit tests than production release. The release version should get the black box tests, not unit tests.
 ** black box unit testing
 The d compiler should enforce black box unit tests.
 
 Which is unit tests that only use the classes exposed interface.(public, 
 protected)
 
 Together with 100% unit test coverage it helps ensure that
 the code is modular,decoupled and that you can change
 the private parts without changing the unit tests.
 
 For those how is not ready for this high code standard,
 there might be a --allow-white-box switch.

The compiler doesn't need to help here. There's nothing preventing one from using unittests in this manner. Just import the .di file, which is the exposed interface, then write a unit test block.
 ** Unit test isolation
 I would like to be able to isolate the unit test,
 so that if one fail the next still runs.

You can do this by simply not using "assert" for the actual test. Use: if (!x) writeln("test for x failed"); instead of: assert(x); You can, of course, make a template like Andrei's enforce() to make the if test and message a bit more convenient.
 ** Unit test measurements
 In combination with test isolation
 it would be nice to have d output
 memory and time used in each unit test.

Use the -profile switch.
Jul 23 2009
next sibling parent reply Lutger <lutger.blijdestijn gmail.com> writes:
Walter Bright wrote:

 Knud Soerensen wrote:

 
 I think one of D's strongest points for people to make the switch is
 build in unit testing. (at least this is the strongest point for me)
 But the very simple implementation of unit testing in D nearly ruin the
 advantage it gives. (see suggestion from the wishlist below)

Even at its very simple support, it's a huge win. It raises the bar on what is minimally acceptable, and has been responsible for a big improvement in the quality of Phobos.

It's interesting why unittest (and assert) are such big success. My idea is that it's not in spite of, but because of their utter simplicity. I speculate that if it would have been different, for example if you would had to create a new file for a unittest, it would not have been used so much. ...
 
 ** Unit test isolation
 I would like to be able to isolate the unit test,
 so that if one fail the next still runs.

You can do this by simply not using "assert" for the actual test. Use: if (!x) writeln("test for x failed"); instead of: assert(x); You can, of course, make a template like Andrei's enforce() to make the if test and message a bit more convenient.

But within sight there is something much better. druntime defines a function setAssertHandler to configure a user defined function for handling assertions! Combine this with version(unittest) and the Runtime.moduleUnitTester callback et voila!: profit* I still see two major points of improvement: - unittests are anonymous things. It would be a big improvement to be able to say unittest("Test foobar") { } and retrieve the named test via the runtime provided hooks - all unittests from one module are lumped together in it's ModuleInfo object. I would rather like to see an array of named unittests instead. The rationale for these improvements is that the language and standard library only defines very minimal, low impact ways of writing tests. At the same time, the building blocks are provided to create more advanced tools. This way you can also start out writing simple tests, and then not have to rewrite those again when you want to use some fancy continuous integration suite for D. At the moment, it's simply not possible to progress to more elaborate testing without breaking everything and starting from scratch. * Well I think so, I haven't been able to make use of it (segfaults) but it would be sweet.
Jul 23 2009
parent Walter Bright <newshound1 digitalmars.com> writes:
Lutger wrote:
 It's interesting why unittest (and assert) are such big success. My idea is 
 that it's not in spite of, but because of their utter simplicity. I 
 speculate that if it would have been different, for example if you would had 
 to create a new file for a unittest, it would not have been used so much.

I tend to agree. I've found over and over, that if you drive things down to their simplest essence, they'll get wide adoption. If someone needs to read a manual with long lists of options, they'll pass it by. For instance, look at the installer thing. I think that downloading a zip file, and unzipping it, is so trivial. Yet this seems to be a blocker for people using D, over and over I hear about how hard it is to install. I find this baffling. But yet, it's obviously an issue.
Jul 24 2009
prev sibling parent Knud Soerensen <4tuu4k002 sneakemail.com> writes:
Walter Bright wrote:

 I know the real focus for D system programing and the C++ people.

 I think one of D's strongest points for people to make the switch is 
 build in unit testing. (at least this is the strongest point for me)
 But the very simple implementation of unit testing in D nearly ruin 
 the advantage it gives. (see suggestion from the wishlist below)

Even at its very simple support, it's a huge win. It raises the bar on what is minimally acceptable, and has been responsible for a big improvement in the quality of Phobos.

It is between using D with its very simple unit test framework or C++/java/etc with a very good unit testing framework. I think that D should provide a framework on the same level or maybe just make the best unit testing framework on the planet.
 
 A simple way to ensure that could if the compiler issued a 
 error/warning if a function had no unit tests or contracts.

I worry that such would be crying wolf. But dmd does have a coverage analyzer built in - which I think is more useful. It'll show which lines were executed by the unit tests, and which were not.

Yes, the coverage analyzer is very good, but how do you ensure that the library developers actually use it ?? The feature should be introduce slowly, by first printing a warning when a testing binary was build. Then step it up to a error for testing binary. Then a warning for production binaries and in a dissent future also errors on production binaries. Already at the first step, we would see if the D community find it useful. In its last step it would unsure that everybody using some unknown D code would know that it had some level of test coverage and quality. It is not as fine masked as 100% coverage test but would ensure that ever function had some test code and that without run a coverage analyzes. How hard do you think it would be to make ?
 
 
 What follows is some unit test suggestions from 
 http://all-technology.com/eigenpolls/dwishlist
 Because I would like to hear your opinion about them.

 ** unit test & code separation
 I think it would be more useful if the code
 and the unit test where two separate binaries.

 Sometimes you need to move the production binary to another 
 machine/environment.
 It would be nice if one could move the test binary with it and test 
 that everything works.

 It would also allow for arguments to the test binary,
 so that you would be able to run a specific unit test.

I made the decision at one point that unit tests weren't there to test that the compiler generated code correctly, they were to test the logic of the user code. Hence, one does a separate build for unit tests than production release.

if the assumptions you make in your code about the environment is correct.
 The release version should get the black box tests, not unit tests.
 
 
 
 ** black box unit testing
 The d compiler should enforce black box unit tests.

 Which is unit tests that only use the classes exposed 
 interface.(public, protected)

 Together with 100% unit test coverage it helps ensure that
 the code is modular,decoupled and that you can change
 the private parts without changing the unit tests.

 For those how is not ready for this high code standard,
 there might be a --allow-white-box switch.

The compiler doesn't need to help here. There's nothing preventing one from using unittests in this manner. Just import the .di file, which is the exposed interface, then write a unit test block.

Yes, you can do that. But why should you have to jump trough loops to write good test code. I think the default behavior should support writing good modular tests. Imagine we have a team with 20 programmers working a big project. The project standard for unit testing is to include .di file and write unit test on the public interface. Now imagine one bad programmer broke the standard and wrote a unit test on a private function. Now, how would you discover that, without going trough every d file ? If it is default behavior was not to allow unit testing private function then the bad programmer would have to use the --allow-white-box switch and you could just compile without it to discover the problem. -- Join me on CrowdNews http://crowdnews.eu/users/addGuide/42/ Facebook http://www.facebook.com/profile.php?id=1198821880 Linkedin http://www.linkedin.com/pub/0/117/a54 Mandala http://www.mandala.dk/view-profile.php4?profileID=7660
Jul 23 2009
prev sibling next sibling parent "Nick Sabalausky" <a a.a> writes:
"Knud Soerensen" <4tuu4k002 sneakemail.com> wrote in message 
news:h49mfs$vf2$1 digitalmars.com...
 Some time ago I need a script to get and process some data.
 I trough why not use D, but I couldn't find a function in the standard 
 library which would get a simple web page with http.
 Instead of find and downloading other libraries I switched to peal and had 
 it running in no time.

 ** Unit test isolation
 I would like to be able to isolate the unit test,
 so that if one fail the next still runs.

You may want to keep an eye on my SemiTwist D Tools http://www.dsource.org/projects/semitwist/ I haven't gotten around to releasing it yet, but it includes an alternate to assert that delays the "exit app" until you tell it to: int x = 7; mixin(deferAssert!("x == 9")); mixin(deferAssert!("2+2==5", "Reality is broken")); flushAsserts(); // Can put this at the beginning of main to wait for all unittests to run before bailing. // Now you get both errors, not just the first one. Unfortunately I wasn't able to get around the awkward "mixin" part though. (It also doesn't seem to work inside in{} out{} blocks, not sure why yet, I think there may be some limitation I'm not aware of about the code allowed in those.) In the same project I'm also working on a library that will provide, with one import, a full kitchen-sink scripting-style environment that should make the tasks like your example above much much easier in D.
Jul 23 2009
prev sibling next sibling parent Jesse Phillips <jessekphillips gmail.com> writes:
On Thu, 23 Jul 2009 22:06:23 +0200, Knud Soerensen wrote:

 Walter Bright wrote:
 
 I know the real focus for D system programing and the C++ people.

 I think one of D's strongest points for people to make the switch is
 build in unit testing. (at least this is the strongest point for me)
 But the very simple implementation of unit testing in D nearly ruin
 the advantage it gives. (see suggestion from the wishlist below)

Even at its very simple support, it's a huge win. It raises the bar on what is minimally acceptable, and has been responsible for a big improvement in the quality of Phobos.

It is between using D with its very simple unit test framework or C++/java/etc with a very good unit testing framework. I think that D should provide a framework on the same level or maybe just make the best unit testing framework on the planet.

But those languages don't have Unit testing. There are libraries that let you do Unit testing in those languages, but it isn't the language. Hence the creation of DUnit.
Jul 23 2009
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 24 Jul 2009 05:26:39 -0400, Walter Bright  
<newshound1 digitalmars.com> wrote:

 Lutger wrote:
 It's interesting why unittest (and assert) are such big success. My  
 idea is that it's not in spite of, but because of their utter  
 simplicity. I speculate that if it would have been different, for  
 example if you would had to create a new file for a unittest, it would  
 not have been used so much.

I tend to agree. I've found over and over, that if you drive things down to their simplest essence, they'll get wide adoption. If someone needs to read a manual with long lists of options, they'll pass it by. For instance, look at the installer thing. I think that downloading a zip file, and unzipping it, is so trivial. Yet this seems to be a blocker for people using D, over and over I hear about how hard it is to install. I find this baffling. But yet, it's obviously an issue.

Downloading, unzipping (where?), setting up your path, marking the binary as executable (on *nix). Much easier to use the OS's installer and let the package tell me how to set it up. Getting the files and expanding them isn't the difficult part :) -Steve
Jul 24 2009
prev sibling next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Mon, Jul 27, 2009 at 7:33 PM, escalan<escalan gmail.com> wrote:
 Hi, I'm new here. A simple idea I've had is to simply use aliases for defining
properties.

 If you allow writing aliases as expressions, you have get properties. Then a
simple extension to the syntax would also allow for writing set properties.

 alias (a) property;
 alias (a = n) property(n);

 foo(property); // Get
 property = 32; // Set

 This virtually eliminates any problems with properties, and it doesn't require
any new keywords. It won't break existing aliases either.

Except if you want to do anything more complex in your setter/getter than a simple expression.
Jul 27 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Tue, Jul 28, 2009 at 10:20 AM, Steven
Schveighoffer<schveiguy yahoo.com> wrote:
 On Tue, 28 Jul 2009 12:30:00 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 Steven Schveighoffer wrote:


 What if the compiler allowed you to call functions as long as what you
 typed was an unambiguous prefix of the function name
 why don't we have a
 wonderful time-saving feature like this? =A0Because it would be a nightma=

 read.

 So now C# has two ways of providing a readonly field. Doesn't quite look
 like an example to follow.

Just like D! Yes, that's right. =A0readonly is analogous to const.

 That's what I'm saying: if it could do anything, at least don't pretend
 it's anything special. It's a function!

=A0=A0So would you argue that C# or D with operator overloading isn't better because operators are just functions, why call them something else=

Bravo! Fine, rational arguments, Steve.
 Well maybe you could change TimeSpan.

=A0Lovely. =A0Force the developer to rename his functions because D is =



 weak to allow defining a correct interface.

Or maybe because her use of name was too ambiguous.

I want to use the parentheses or lack thereof as part of the human meanin=

 for the function/property. =A0Making them optional means I can't do that.

I think Andrei's right here. .seconds() really was too ambiguous a name to begin with. Even if we had properties I would be inclined to think that was just something you forgot to mark as a property because a property-like meaning is all that makes sense to me. The meaning of .fromSeconds() is much more obvious. The example of adjectives or nouns that are also verbs is much better --- .empty vs .empty(). Others that come to mind: clean, dirty, end, begin. (begin isn't really a noun but it's been used that way for so long in STL that C++ people think of it as a synonym for "beginning".) --bb
Jul 28 2009
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 28 Jul 2009 13:51:11 -0400, Bill Baxter <wbaxter gmail.com> wrote:

 On Tue, Jul 28, 2009 at 10:20 AM, Steven
 Schveighoffer<schveiguy yahoo.com> wrote:
 I want to use the parentheses or lack thereof as part of the human  
 meaning
 for the function/property.  Making them optional means I can't do that.

I think Andrei's right here. .seconds() really was too ambiguous a name to begin with. Even if we had properties I would be inclined to think that was just something you forgot to mark as a property because a property-like meaning is all that makes sense to me. The meaning of .fromSeconds() is much more obvious.

I think in the sense that 'seconds' is not a verb, and therefore, it's not obvious (perhaps to some) that TimeSpan.seconds(5); returns a TimeSpan that represents 5 seconds is a valid point. But what happens in those cases is the user is slightly confused and looks up the docs (probably once). The argument from Andrei is simply dodging the issue. ts.seconds = 5; Means the same thing (even with Andrei's new rule), and not because I poorly named the function, but because I happened to name it the same as a member function. That you can call a static function via an instance is one bug IMO, and the other is that the function is even considered as a property.
 The example of adjectives or nouns that are also verbs is much better
 --- .empty  vs .empty().    Others that come to mind:  clean, dirty,
 end, begin.  (begin isn't really a noun but it's been used that way
 for so long in STL that C++ people think of it as a synonym for
 "beginning".)

I was using a real-life example, I think that has some power to it. But you are right, naming the static method differently was probably the right move anyways, and there are better theoretical examples. There was some pressure to make the usage less verbose... -Steve
Jul 28 2009
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 28 Jul 2009 14:19:49 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Bill Baxter wrote:
 On Tue, Jul 28, 2009 at 10:20 AM, Steven
 Schveighoffer<schveiguy yahoo.com> wrote:
 On Tue, 28 Jul 2009 12:30:00 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 Steven Schveighoffer wrote:


 What if the compiler allowed you to call functions as long as what you
 typed was an unambiguous prefix of the function name
 why don't we have a
 wonderful time-saving feature like this?  Because it would be a  
 nightmare to
 read.

 So now C# has two ways of providing a readonly field. Doesn't quite  
 look
 like an example to follow.

Yes, that's right. readonly is analogous to const.

 That's what I'm saying: if it could do anything, at least don't  
 pretend
 it's anything special. It's a function!

So would you argue that C# or D with operator overloading isn't better because operators are just functions, why call them something else?


I don't think it's a good argument. Operators are functions with a specific syntax, is all. D is not even pretending any different: it simply rewrites the usual syntax into function calls. We should do the same with properties.

I was using this as an example of how your arguments against property definitions sound to me. Operators are not the same as properties -- the definition syntax is the same word, every time. So once you learn that the non-english term opAdd defines what happens when you type +, you can repeatedly use that knowledge. For example, I know that for the following code: x + y; I know this means "add x to y," and it might call opAdd or it might be a builtin operation, I don't care, but I know it means to add. It might even execute arbitrary code that does something completely different, but it's not my fault because the author didn't follow the standard convention. I don't have to look it up, or know what the author of object x meant, the meaning is not subject to debate or English ambiguity. However, when I see: x.empty; I can't tell what is implied here. empty could be a field or property, in which case the user made a logic error, or it could be a function that empties x, or it could be some code that does something completely different. I assume the author is going to name his functions after what they do, similarly to how opAdd should be used for addition. English is not precise, and can have multiple meanings for the same exact word. Context is important. But it gets worse. Now I see this: y.empty; Oh, I learned what empty meant before, right? WRONG! y could be written by a completely different author, and could have the opposite meaning. The problem is, you can't come up with a non-prejudiced definition of what empty should always mean, because the English term itself is ambiguous. All you can do is use conventions that can be defined, such as () performs an action, but lack of () denotes a field, or come up with java-like conventions (e.g. doXxx means it's a function). So if I can couple the term empty with the context of lack of parentheses meaning field, I can deduce the meaning of empty *without looking it up*. The advantage is not having to look up what code means because the author did a good job of naming the function/property. This is currently impossible with D. Coming up with bizarre rules that require pairs of functions doesn't make things any easier. I still have to look up the usage of empty every time I encounter a new usage of it, because it could mean one of two things. -Steve
Jul 28 2009
prev sibling next sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Tue, Jul 28, 2009 at 11:19 AM, Andrei
Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:
 Bill Baxter wrote:
 On Tue, Jul 28, 2009 at 10:20 AM, Steven
 Schveighoffer<schveiguy yahoo.com> wrote:
 On Tue, 28 Jul 2009 12:30:00 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 Steven Schveighoffer wrote:


 What if the compiler allowed you to call functions as long as what you
 typed was an unambiguous prefix of the function name
 why don't we have a
 wonderful time-saving feature like this? =A0Because it would be a night=



 to
 read.

...
 So now C# has two ways of providing a readonly field. Doesn't quite lo=




 like an example to follow.

Just like D! Yes, that's right. =A0readonly is analogous to const.

...
 That's what I'm saying: if it could do anything, at least don't preten=




 it's anything special. It's a function!

... =A0So would you argue that C# or D with operator overloading isn't better because operators are just functions, why call them something else?

Bravo! =A0Fine, rational arguments, Steve.

I don't think it's a good argument. Operators are functions with a specif=

 syntax, is all. D is not even pretending any different: it simply rewrite=

 the usual syntax into function calls. We should do the same with properti=

I think I basically agree with you on that except: 1) The function call syntax should be disabled on properties to avoid ambiguities like returned delegates or things with opCall. 2) the function name that properties are rewritten into should be hidden from the programmer. With opAdd etc, the function you are trying to write corresponds to a symbol, so you can't have it be your identifier. So goofy names like opAdd are necessary and unavoidable. With properties, the thing in question has a name, so it is more pleasing to actually use it. But certainly, property accesses will still be rewritten as functions. It could even be opGet_foo internally. But who wants to look at a dozen functions with names like opGet_ opSet_? Yes, my main argument against opGet_ is that it is butt-ugly. The problem is that most every class has multiple properties. So every class will have to sprout this ugliness. But sprouting a few property {...} blocks or even "property:" sections is not so bad. In fact I seen no reason why you couldn't just make the rule be that we rewrite the properties both at point of use *and* at point of declaration. property int foo() { return x_; } would be rewritten int opGet_foo() { return x_; } And I suppose I don't see any reason to stop anyone from writing the latter if they somehow find it more aesthetically pleasing. Or find it more useful for code generation or something. --bb
Jul 28 2009
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 28 Jul 2009 16:08:58 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Steven Schveighoffer wrote:
 However, when I see:
  x.empty;
  I can't tell what is implied here.

You can. In either C# or D language it could execute arbitrary code that you better know what it's supposed to do. D simply doesn't make it "bad style" as C# stupidly does.

still not getting it, are you... Just forget it, I think this is a lost cause, I keep making the same points over and over again, and you keep not reading them. -Steve
Jul 28 2009
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 28 Jul 2009 16:21:09 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Steven Schveighoffer wrote:
 On Tue, 28 Jul 2009 16:08:58 -0400, Andrei Alexandrescu  
 <SeeWebsiteForEmail erdani.org> wrote:

 Steven Schveighoffer wrote:
 However, when I see:
  x.empty;
  I can't tell what is implied here.

You can. In either C# or D language it could execute arbitrary code that you better know what it's supposed to do. D simply doesn't make it "bad style" as C# stupidly does.

Just forget it, I think this is a lost cause, I keep making the same points over and over again, and you keep not reading them.

I do read them and understand them. I mean, it's not rocket surgery. At the end of the day you say "x = a.b;" looks more like sheer access because that's what happens for fields already.

No, b has no meaning. It's not an English word. a.filter() looks like it should filter something. a.filter looks like it should access a filter. But in D, a.filter could mean either, which I guess is fine if you want to play it that way, but it's far inferior to C#, where a.filter should return a filter, and a.filter() should perform a filtering action. If it doesn't, the author wrote his code incorrectly. It's as simple as that.
 Then you say "a.b()" in any context looks more like an action because  
 it's clear that there's a function call involved.

Again, b means nothing, so I would have no idea in C# or D. -Steve
Jul 28 2009
prev sibling parent Bill Baxter <wbaxter gmail.com> writes:
On Tue, Jul 28, 2009 at 1:49 PM, Andrei
Alexandrescu<SeeWebsiteForEmail erdani.org> wrote:
 aarti_pl wrote:
 What would you do if you were me?

 Andrei

You should just accept what others want *although* you don't agree... Steve's arguments are very good and convincing, and unfortunately somehow you don't get them. And I don't see your arguments being superior at all.

I do get his arguments. Not being convinced does not mean I don't understand them. You seem to assume that as soon as I understood his arguments I'd automatically agree, so somehow I don't understand them

I think the expectation is more that you would address or respond to his argument rather than making your own argument again. Or say something like this: The fundamental difference in our viewpoints is that you believe that expressing extra semantic information to people who read the code is more valuable that saving some typing. I believe the opposite. (feel free to rewrite as you wish) Then it is clear that you have understood his argument and have some idea how and where the difference in opinion really comes from. Simply repeating your argument makes it look as though you have not read his.
 Sorry for thread hijacking, but such discussions make me want not to use D
 any more... I am writing because I still have some hope...

D has great features, and probably less warts than most other languages. I understand how you feel, but I'd also hope that realistically your use of the language hinges on a little more than this one issue.

I don't think it's this one issue he's talking about. I think the issue is an occasionally repeated history of questionable changes in D made in the face of strong community opposition. Like foreach_reverse. Such choices may be perfectly valid, but if you find yourself repeatedly not seeing eye-to-eye with the designers of a language, you have to wonder if you're in the right language community. --bb
Jul 28 2009