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

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

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

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.

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?

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

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

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

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.

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. 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.)
And you don't think that has *anything* to do with trying to program C++ in D.