www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Old problem with performance

reply Weed <resume755 mail.ru> writes:
(Has started here:
http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=81359)

To me still does not give rest performance of classes (in comparison
with C++ or with D structs)

I still think that it is a serious problem.

Colleagues from our national D forum have asked to show it and I have
written simple examples on D. I want to share with you too them.

On my computer the code with structure (i.e. object by value) runs in 6
times faster than a code with a class:

$ time ./struct

real    0m8.515s
user    0m7.796s
sys     0m0.016s
$ time ./class

real    0m52.185s
user    0m40.543s
sys     0m0.076s

The code on C++ is also approximately in 6 times faster a code with
classes on D. (I do not give an example on C++ because classes on C++
work just as structures in D.)

I think with it it is necessary to do something.


Examples code:

//========================
struct C {
    int i;
    real[5] unused; // to prevent returning this object in registers

    C opAdd( C src ) {
        C ret;
        ret.i = i + src.i;
        return ret;
    }
}

int main() {
    C c1;
    C c2;

    // initialise i by "random" value to prevent compile-time calculation
    c1.i = cast(int)&c1;
    c2.i = 0;

    for(int i = 0; i < 50_000_000; ++i)
        c2 = c1 + c1 + c1;

    return c2.i;
}

//========================

class C {
    int i;
    real[5] unused; // to prevent returning this object in registers

    C opAdd( C src ) {
        auto ret = new C;
        ret.i = i + src.i;
        return ret;
    }
}

int main() {
    auto c1 = new C;
    auto c2 = new C;

    // initialise i by "random" value to prevent compile-time calculation
    c1.i = cast(int)&c1;
    c2.i = 0;

    for(int i = 0; i < 50_000_000; ++i)
        c2 = c1 + c1 + c1;

    return c2.i;
}
//========================
Feb 07 2009
next sibling parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Weed wrote:
 [snip]
If I had to take a guess, I'd say that it's six times slower because you're performing 100 million allocations. You aren't benchmarking class/struct overhead, you're benchmarking the overhead of doing 100 million allocations. You're comparing apples and heffalumps. -- Daniel
Feb 08 2009
next sibling parent reply Weed <resume755 mail.ru> writes:
Daniel Keep :
 Weed wrote:
 [snip]
If I had to take a guess, I'd say that it's six times slower because you're performing 100 million allocations. You aren't benchmarking class/struct overhead, you're benchmarking the overhead of doing 100 million allocations. You're comparing apples and heffalumps.
Yes, but problem is that D does not leave way to create a class instance without allocation
Feb 08 2009
next sibling parent Weed <resume755 mail.ru> writes:
Weed :
 Daniel Keep :
 Weed wrote:
 [snip]
If I had to take a guess, I'd say that it's six times slower because you're performing 100 million allocations. You aren't benchmarking class/struct overhead, you're benchmarking the overhead of doing 100 million allocations. You're comparing apples and heffalumps.
Yes, but problem is that D does not leave way to create a class instance without allocation
I should explain that I compare not only structs and classes in D but also classes in C++, there classes work as fast as well as structures in case of usage of overload of operators.
Feb 08 2009
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Weed wrote:
 Daniel Keep :
 Weed wrote:
 [snip]
If I had to take a guess, I'd say that it's six times slower because you're performing 100 million allocations. You aren't benchmarking class/struct overhead, you're benchmarking the overhead of doing 100 million allocations. You're comparing apples and heffalumps.
Yes, but problem is that D does not leave way to create a class instance without allocation
You can allocate a class on the stack with: scope c = new C();
Feb 08 2009
parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Walter Bright wrote:
 Weed wrote:
 Daniel Keep пишет:
 Weed wrote:
 [snip]
If I had to take a guess, I'd say that it's six times slower because you're performing 100 million allocations. You aren't benchmarking class/struct overhead, you're benchmarking the overhead of doing 100 million allocations. You're comparing apples and heffalumps.
Yes, but problem is that D does not leave way to create a class instance without allocation
You can allocate a class on the stack with: scope c = new C();
Which helps (a bit) with the two instances allocated in main(), but is rather unhelpful with the 100_000_000 allocated in opAdd() (they're returned)...
Feb 08 2009
next sibling parent Sean Kelly <sean invisibleduck.org> writes:
Frits van Bommel wrote:
 Walter Bright wrote:
 Weed wrote:
 Daniel Keep пишет:
 Weed wrote:
 [snip]
If I had to take a guess, I'd say that it's six times slower because you're performing 100 million allocations. You aren't benchmarking class/struct overhead, you're benchmarking the overhead of doing 100 million allocations. You're comparing apples and heffalumps.
Yes, but problem is that D does not leave way to create a class instance without allocation
You can allocate a class on the stack with: scope c = new C();
Which helps (a bit) with the two instances allocated in main(), but is rather unhelpful with the 100_000_000 allocated in opAdd() (they're returned)...
It's kind of a lame solution, but if the return value is const then the class could just hold a reference to an internal value it changes as needed. Sean
Feb 08 2009
prev sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Frits van Bommel wrote:
 Which helps (a bit) with the two instances allocated in main(), but is 
 rather unhelpful with the 100_000_000 allocated in opAdd() (they're 
 returned)...
The use of classes in this example is like using a screwdriver as a hammer. It'll work in a pinch, but a hammer works a lot better. If you're allocating 100_000_000 classes in a tight loop, some refactoring looks to be in order. In particular, classes are *meant* to be used as reference types, but the program is trying to treat them as value types. Virtual functions are orthogonal to what value types are - a continuing problem C++ programs have is conflating value types with reference types.
Feb 08 2009
next sibling parent reply Derek Parnell <derek psych.ward> writes:
On Sun, 08 Feb 2009 11:13:00 -0800, Walter Bright wrote:


 In particular, classes are *meant* to be used as reference types, but 
 the program is trying to treat them as value types. Virtual functions 
 are orthogonal to what value types are - a continuing problem C++ 
 programs have is conflating value types with reference types.
In D, what is the recommend technique to derive one user-defined value type from another? -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
Feb 08 2009
next sibling parent reply Walter Bright <newshound1 digitalmars.com> writes:
Derek Parnell wrote:
 On Sun, 08 Feb 2009 11:13:00 -0800, Walter Bright wrote:
 
 
 In particular, classes are *meant* to be used as reference types, but 
 the program is trying to treat them as value types. Virtual functions 
 are orthogonal to what value types are - a continuing problem C++ 
 programs have is conflating value types with reference types.
In D, what is the recommend technique to derive one user-defined value type from another?
There isn't one. Deriving types only makes sense when expecting polymorphic behavior, which is completely orthogonal to the whole idea of a value type. A polymorphic type should be a reference type. A value type can have *aggregation*, however, as in: struct Sbase { ... base members ... } struct S { Sbase base; ... more members ... } You can also embed interfaces in a struct: interface I { ... } struct S { I i; }
Feb 08 2009
next sibling parent reply Derek Parnell <derek psych.ward> writes:
On Sun, 08 Feb 2009 14:37:18 -0800, Walter Bright wrote:

 Derek Parnell wrote:
 On Sun, 08 Feb 2009 11:13:00 -0800, Walter Bright wrote:
 
 In particular, classes are *meant* to be used as reference types, but 
 the program is trying to treat them as value types. Virtual functions 
 are orthogonal to what value types are - a continuing problem C++ 
 programs have is conflating value types with reference types.
In D, what is the recommend technique to derive one user-defined value type from another?
There isn't one. Deriving types only makes sense when expecting polymorphic behavior, which is completely orthogonal to the whole idea of a value type. A polymorphic type should be a reference type.
Thank you. I was using "derive" in the English language sense rather than the O-O sense, but I get your point - for example a 'currency' value type is only ever to be used as a currency value and not any of its base value types. Fair enough.
 A value type can have *aggregation*, however, as in:
 
 struct Sbase
 {
      ... base members ...
 }
 
 struct S
 {
      Sbase base;
      ... more members ...
 }

 You can also embed interfaces in a struct:
 
 interface I { ... }
 struct S
 {
      I i;
 }
This is what I thought too. In D, a value type can be derived from another value type by using a combination of data aggregation (data inheritance if you will) and interface aggregation (method inheritance?). I feel that D could do with a little more syntax support for derived value types though, because at times it is a bit awkward and/or verbose. I'll dig up some examples of what I mean. -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
Feb 08 2009
parent dsimcha <dsimcha yahoo.com> writes:
== Quote from Derek Parnell (derek psych.ward)'s article
 This is what I thought too. In D, a value type can be derived from another
 value type by using a combination of data aggregation (data inheritance if
 you will) and interface aggregation (method inheritance?).
 I feel that D could do with a little more syntax support for derived value
 types though, because at times it is a bit awkward and/or verbose. I'll dig
 up some examples of what I mean.
In D2, you could try aggregation and opDot() w/ ref return. See http://digitalmars.com/d/2.0/operatoroverloading.html#Dot . That pretty much simulates a form of inheritance w/o polymorphism. struct Foo { int i; void doStuff() { // Do stuff. } } struct Bar { private Foo foo; ref Foo opDot() { return foo; } } void main() { Bar bar; bar.doStuff(); // Calls Bar.foo.doStuff(). } One caveat, though, is that operator overloading behaves weirdly w/ this. See bug 2327: http://d.puremagic.com/issues/show_bug.cgi?id=2327
Feb 08 2009
prev sibling parent Chad J <gamerchad __spam.is.bad__gmail.com> writes:
Walter Bright wrote:
 Derek Parnell wrote:
 On Sun, 08 Feb 2009 11:13:00 -0800, Walter Bright wrote:


 In particular, classes are *meant* to be used as reference types, but
 the program is trying to treat them as value types. Virtual functions
 are orthogonal to what value types are - a continuing problem C++
 programs have is conflating value types with reference types.
In D, what is the recommend technique to derive one user-defined value type from another?
There isn't one. Deriving types only makes sense when expecting polymorphic behavior, which is completely orthogonal to the whole idea of a value type. A polymorphic type should be a reference type.
So far I am seeing that the slicing problem arises from the ability to place extra data into derived types. But what of method inheritance? It seems that something like this could work: scope class A { int x, y; int foo() { etc... } } class B : A { // More data members are now forbidden. int foo() { etc... } void bar(char[] baz) {...} } struct S { // in-place allocation scope A qux; scope A quux; } void main() { S s; s.qux = new B; }
Feb 08 2009
prev sibling next sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Mon, 09 Feb 2009 01:24:34 +0300, Derek Parnell <derek psych.ward> wrote:

 On Sun, 08 Feb 2009 11:13:00 -0800, Walter Bright wrote:


 In particular, classes are *meant* to be used as reference types, but
 the program is trying to treat them as value types. Virtual functions
 are orthogonal to what value types are - a continuing problem C++
 programs have is conflating value types with reference types.
In D, what is the recommend technique to derive one user-defined value type from another?
A mixin, perhaps: struct Brush { // ... } struct ColoredBrush { mixin Brush; Color color; }
Feb 08 2009
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Derek Parnell wrote:
 On Sun, 08 Feb 2009 11:13:00 -0800, Walter Bright wrote:
 
 
 In particular, classes are *meant* to be used as reference types, but 
 the program is trying to treat them as value types. Virtual functions 
 are orthogonal to what value types are - a continuing problem C++ 
 programs have is conflating value types with reference types.
In D, what is the recommend technique to derive one user-defined value type from another?
Go to the future and use the alias this thingie. Andrei
Feb 08 2009
prev sibling parent reply Weed <resume755 mail.ru> writes:
Walter Bright :
 Frits van Bommel wrote:
 Which helps (a bit) with the two instances allocated in main(), but is
 rather unhelpful with the 100_000_000 allocated in opAdd() (they're
 returned)...
The use of classes in this example is like using a screwdriver as a hammer. It'll work in a pinch, but a hammer works a lot better. If you're allocating 100_000_000 classes in a tight loop, some refactoring looks to be in order. In particular, classes are *meant* to be used as reference types, but the program is trying to treat them as value types.
But without such types the bulky code turns out (examples in this branch already presented)
 Virtual functions
 are orthogonal to what value types are - a continuing problem C++
 programs have is conflating value types with reference types.
The compiler cannot optimize such code? No We have virtual machine for fast allocations of memory at such heavy using of objects? No Perfectly - it is necessary to leave this question to the programmer: the class will be stored in a stack or in a heap is better will solve the programmer instead of the compiler. It is impossible to lose to an C++ in what.
Feb 08 2009
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Mon, Feb 09, 2009 at 09:59:50AM +0700, Weed wrote:
 Perfectly - it is necessary to leave this question to the programmer:
 the class will be stored in a stack or in a heap is better will solve
 the programmer instead of the compiler.
scope class does just that. You can also put a custom allocator in your class and do whatever you want. -- Adam D. Ruppe http://arsdnet.net
Feb 08 2009
parent Weed <resume755 mail.ru> writes:
Adam D. Ruppe :
 On Mon, Feb 09, 2009 at 09:59:50AM +0700, Weed wrote:
 Perfectly - it is necessary to leave this question to the programmer:
 the class will be stored in a stack or in a heap is better will solve
 the programmer instead of the compiler.
scope class does just that.
No, D do not allow return scope value.
 You can also put a custom allocator in your
 class and do whatever you want.
 
Often you add custom allocator in the classes who uses overload? You begin to do it after that talk? :)
Feb 08 2009
prev sibling parent reply Yigal Chripun <yigal100 gmail.com> writes:
Daniel Keep wrote:
 Weed wrote:
 [snip]
If I had to take a guess, I'd say that it's six times slower because you're performing 100 million allocations. You aren't benchmarking class/struct overhead, you're benchmarking the overhead of doing 100 million allocations. You're comparing apples and heffalumps. -- Daniel
I'm curious, What is a heffalump?
Feb 08 2009
parent BCS <none anon.com> writes:
Hello Yigal,

 I'm curious, What is a heffalump?
 
http://en.wikipedia.org/wiki/Heffalump
Feb 08 2009
prev sibling next sibling parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Sun, 08 Feb 2009 10:26:37 +0300, Weed <resume755 mail.ru> wrote:

 (Has started here:
 http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=81359)

 To me still does not give rest performance of classes (in comparison
 with C++ or with D structs)

 I still think that it is a serious problem.

 Colleagues from our national D forum have asked to show it and I have
 written simple examples on D. I want to share with you too them.

 On my computer the code with structure (i.e. object by value) runs in 6
 times faster than a code with a class:

 $ time ./struct

 real    0m8.515s
 user    0m7.796s
 sys     0m0.016s
 $ time ./class

 real    0m52.185s
 user    0m40.543s
 sys     0m0.076s

 The code on C++ is also approximately in 6 times faster a code with
 classes on D. (I do not give an example on C++ because classes on C++
 work just as structures in D.)

 I think with it it is necessary to do something.


 Examples code:

 //========================
 struct C {
     int i;
     real[5] unused; // to prevent returning this object in registers

     C opAdd( C src ) {
         C ret;
         ret.i = i + src.i;
         return ret;
     }
 }

 int main() {
     C c1;
     C c2;

     // initialise i by "random" value to prevent compile-time calculation
     c1.i = cast(int)&c1;
     c2.i = 0;

     for(int i = 0; i < 50_000_000; ++i)
         c2 = c1 + c1 + c1;

     return c2.i;
 }

 //========================

 class C {
     int i;
     real[5] unused; // to prevent returning this object in registers

     C opAdd( C src ) {
         auto ret = new C;
         ret.i = i + src.i;
         return ret;
     }
 }

 int main() {
     auto c1 = new C;
     auto c2 = new C;

     // initialise i by "random" value to prevent compile-time calculation
     c1.i = cast(int)&c1;
     c2.i = 0;

     for(int i = 0; i < 50_000_000; ++i)
         c2 = c1 + c1 + c1;

     return c2.i;
 }
 //========================
Your C objects have value semantics. For value semantics you should use value types. Alternatively you may want to use the following trick (I used it for lazy string concatenation in C+): class C { int value; this(int dim)(ref Sum!(dim) sum) { value = sum.value; } Sum!(2) opAdd(C other) { return Sum!(2)(this, other); } } struct Sum(int dimension) { private C[dimension] objects; this(C first, C second) { objects[0] = first; objects[1] = second; } this(int dim)(ref Sum!(dim) sum1, ref Sum!(dimension-dim) sum2) { objects[0..dim][] = sum1.objects[]; objects[dim+1..dimension] = sum2.objects[]; } this(ref Sum!(dimension-1) sum, C obj) { objects[0..$-1][] = sum.objects[]; objects[$-1] = obj; } Sum!(dimension+1) opAdd(C other) { return Sum!(dimension+1)(this, other); } Sum!(dimension+otherDimension) opAdd(otherDimension)(Sum!(otherDimension) other) { return Sum!(dimension+otherDimension)(this, other); } int value() { int value = 0; foreach (C c; objects) { value += c.value; } return value; } } Apparently, it doesn't work at the moment because ctor can't be a template :( Is there an enhancement request in bugzilla? It prevents this pattern from working.
Feb 08 2009
parent reply Weed <resume755 mail.ru> writes:
Denis Koroskin :

 Your C objects have value semantics. For value semantics you should use value
types.
At present in D is not contain support of value types for objects. (I consider that it is necessary)
 Alternatively you may want to use the following trick (I used it for lazy
string concatenation in C+):
[skip]
 Apparently, it doesn't work at the moment because ctor can't be a
 template :(
 Is there an enhancement request in bugzilla? It prevents this pattern
 from working.
+ it is difficult and also it will be even more difficult if it will be necessary to make support for the construction like: space_ship_1.calculatePathTo("Moon").getCheckpoint(3).getCoords; In this example we create a temporary class "path", create temporary class "checkpoint" and we take coords of checkpoint of this path. It is not expedient to us to store all this path and checkpoint because it is vary. (from http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=81432)
Feb 08 2009
parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Sun, 08 Feb 2009 17:07:31 +0300, Weed <resume755 mail.ru> wrote:

 Denis Koroskin пишет:

 Your C objects have value semantics. For value semantics you should use  
 value types.
At present in D is not contain support of value types for objects. (I consider that it is necessary)
 Alternatively you may want to use the following trick (I used it for  
 lazy string concatenation in C+):
[skip]
 Apparently, it doesn't work at the moment because ctor can't be a
 template :(
 Is there an enhancement request in bugzilla? It prevents this pattern
 from working.
+ it is difficult and also it will be even more difficult if it will be necessary to make support for the construction like: space_ship_1.calculatePathTo("Moon").getCheckpoint(3).getCoords; In this example we create a temporary class "path", create temporary class "checkpoint" and we take coords of checkpoint of this path. It is not expedient to us to store all this path and checkpoint because it is vary. (from http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=81432)
I believe you should stick with structs for that.
Feb 08 2009
parent reply Weed <resume755 mail.ru> writes:
Denis Koroskin :

 [skip]

 Apparently, it doesn't work at the moment because ctor can't be a
 template :(
 Is there an enhancement request in bugzilla? It prevents this pattern
 from working.
+ it is difficult and also it will be even more difficult if it will be necessary to make support for the construction like: space_ship_1.calculatePathTo("Moon").getCheckpoint(3).getCoords; In this example we create a temporary class "path", create temporary class "checkpoint" and we take coords of checkpoint of this path. It is not expedient to us to store all this path and checkpoint because it is vary. (from http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=81432)
I believe you should stick with structs for that.
Let's assume, polymorphism is necessary to these objects
Feb 08 2009
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2009-02-08 09:30:08 -0500, Weed <resume755 mail.ru> said:

 Let's assume, polymorphism is necessary to these objects
Polymorphism doesn't work very well while passing objects by value, even in C++. This is called the slicing problem. <http://stackoverflow.com/questions/274626/what-is-the-slicing-problem-in-c> I think D does a good job at avoiding that problem. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Feb 08 2009
next sibling parent reply Rainer Deyke <rainerd eldwood.com> writes:
Michel Fortin wrote:
 Polymorphism doesn't work very well while passing objects by value, even
 in C++. This is called the slicing problem.
I have heard about the slicing problem. I know what it is. But in all my years of using C++ as my primary language, I have never actually encountered it. I don't believe it actually exists. -- Rainer Deyke - rainerd eldwood.com
Feb 08 2009
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Rainer Deyke wrote:
 Michel Fortin wrote:
 Polymorphism doesn't work very well while passing objects by value, even
 in C++. This is called the slicing problem.
I have heard about the slicing problem. I know what it is. But in all my years of using C++ as my primary language, I have never actually encountered it. I don't believe it actually exists.
How long have you used C++? This is not a tendentious question. In the recent years, the advent of quality smart pointers, an increased scrutiny of use of inheritance, and the teaching of idioms associated with reference types has greatly diminished slicing accidents. But in the olden days, people were inheriting value types left and right because it was the emperor's new clothes. Andrei
Feb 08 2009
parent reply Rainer Deyke <rainerd eldwood.com> writes:
Andrei Alexandrescu wrote:
 How long have you used C++?
My first serious C++ project was started in 1997.
 This is not a tendentious question. In the recent years, the advent of
 quality smart pointers, an increased scrutiny of use of inheritance, and
 the teaching of idioms associated with reference types has greatly
 diminished slicing accidents. But in the olden days, people were
 inheriting value types left and right because it was the emperor's new
 clothes.
Slicing is caused by naive copying of polymorphic types, which is only tangentially related to inheriting value types. Example 1 (C++): struct point2d { int x, int y; }; struct point3d : public point2d { int z; } 'point2d' is a non-polymorphic value type. Slicing behavior exists, is intentional, and does not invalidate any invariants. Example 2 (C++): class data_source { public: virtual char read_byte() = 0; }; class input_file : public data_source { public: char read_byte() = 0; }; 'input_file' is a value type that implements an interface. No slicing problem exists because 'data_source' is an abstract type. Example 3 (C++): class person { public: person(person const& org) { assert(typeid(org) == typeid(*this)); } virtual ~person() {} }; class avatar : public person, public deity { }; 'person' and 'avatar' are value types that can be used polymorphically. In any context 'person&' may be either a reference to an instance of class 'person' or a polymorphic reference to an instance of any class that inherits from 'person'. Unfortunately the C++ type system does not distinguish between these two uses. It is an error (checked at runtime) to construct a new 'person' from a polymorphic reference, but any other use of 'person' as a value type or a polymorphic type is valid. No slicing problem exists except through user error. Example 4 (D): class RubberChicken { RubberChicken dup() { return new RubberChicken(); } } class RubberChickenWithAPulleyInTheMiddle { private Pulley pulley; // Forget to override 'dup'. } Here 'RubberChicken' is a reference type, but due to programmer error, the slicing problem still exists. -- Rainer Deyke - rainerd eldwood.com
Feb 08 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Rainer Deyke wrote:
 Example 3 (C++):
 
 class person {
 public:
   person(person const& org) {
     assert(typeid(org) == typeid(*this));
   }
   virtual ~person() {}
 };
 
 class avatar : public person, public deity {
 };
 
 'person' and 'avatar' are value types that can be used polymorphically.
  In any context 'person&' may be either a reference to an instance of
 class 'person' or a polymorphic reference to an instance of any class
 that inherits from 'person'.  Unfortunately the C++ type system does not
 distinguish between these two uses.  It is an error (checked at runtime)
 to construct a new 'person' from a polymorphic reference, but any other
 use of 'person' as a value type or a polymorphic type is valid.  No
 slicing problem exists except through user error.
The slicing problem exists in spades in this example, or better put its converse (your code will fire asserts when it shouldn't). The reason is rather subtle, so please try the code out to edify yourself. Andrei
Feb 08 2009
parent reply Rainer Deyke <rainerd eldwood.com> writes:
Andrei Alexandrescu wrote:
 The slicing problem exists in spades in this example, or better put its
 converse (your code will fire asserts when it shouldn't). The reason is
 rather subtle, so please try the code out to edify yourself.
You're referring to the automatically generated copy constructor in class 'avatar' which calls the copy constructor in class 'person', right? That's a bug in my silly untested example code, but it's not the slicing problem. Fix 1: class person { person(person const& org, bool allow_slicing = false) { assert(allow_slicing || typeid(org) == typeid(*this)); } }; class avatar : public person, public deity { avatar(avatar const& org, bool allow_slicing = false) : person(org, true) { } }; Fix 2: Trust the programmer to pay attention and remove the silly unnecessary assertion from class 'person'. -- Rainer Deyke - rainerd eldwood.com
Feb 08 2009
next sibling parent Christopher Wright <dhasenan gmail.com> writes:
Rainer Deyke wrote:
 Andrei Alexandrescu wrote:
 The slicing problem exists in spades in this example, or better put its
 converse (your code will fire asserts when it shouldn't). The reason is
 rather subtle, so please try the code out to edify yourself.
You're referring to the automatically generated copy constructor in class 'avatar' which calls the copy constructor in class 'person', right? That's a bug in my silly untested example code, but it's not the slicing problem.
It's also a problem whenever you use avatar by value. It's only by programmer discipline that you avoid the slicing problem.
Feb 09 2009
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Rainer Deyke wrote:
 Andrei Alexandrescu wrote:
 The slicing problem exists in spades in this example, or better put its
 converse (your code will fire asserts when it shouldn't). The reason is
 rather subtle, so please try the code out to edify yourself.
You're referring to the automatically generated copy constructor in class 'avatar' which calls the copy constructor in class 'person', right? That's a bug in my silly untested example code, but it's not the slicing problem. Fix 1: class person { person(person const& org, bool allow_slicing = false) { assert(allow_slicing || typeid(org) == typeid(*this)); } }; class avatar : public person, public deity { avatar(avatar const& org, bool allow_slicing = false) : person(org, true) { } };
So the problem exists since you are explicitly addressing it.
 Fix 2:
 
 Trust the programmer to pay attention and remove the silly unnecessary
 assertion from class 'person'.
 
 
So the problem exists since you are trusting the programmer to avoid it. Andrei
Feb 09 2009
parent reply Rainer Deyke <rainerd eldwood.com> writes:
Andrei Alexandrescu wrote:
 So the problem exists since you are trusting the programmer to avoid it.
The slicing problem exists in the sense that it is possible for a bad programmer to accidentally slice an object. However: - This is not a problem with the language, but an avoidable programmer error in the language. - There are far more common programmer errors in C++ against which D does not guard. For example, dangling pointers to stack variables that have gone out of scope. - D's response to this perceived problem is far too heavy-handed, because it disallows useful correct code. - I would even say that the reference type classes in D lead to more problems. It is very easy for two objects in D to accidentally share internal state, something that is impossible with value types. - Even if the slicing problem were a major issue in C++, it should be possible to partially or totally fix it at the language level in D without sacrificing inheritance for value types. -- Rainer Deyke - rainerd eldwood.com
Feb 09 2009
parent reply Christopher Wright <dhasenan gmail.com> writes:
Rainer Deyke wrote:
 Andrei Alexandrescu wrote:
 So the problem exists since you are trusting the programmer to avoid it.
The slicing problem exists in the sense that it is possible for a bad programmer to accidentally slice an object. However: - This is not a problem with the language, but an avoidable programmer error in the language.
Yes. There are many examples of this: memory leaks, array bounds errors, invalid casts, that sort of thing. If you don't mind explicitly coding around these, stay with C or C++. You'll have these errors, but if you're careful and disciplined, it won't happen too often. It will, however, take time and attention to avoid these errors, and to debug them when you slip up. In some cases, a language change can eliminate a class of bugs. Sometimes it's worthwhile. In my experience, the cost of forbidding polymorphic value types is pretty much zero.
   - There are far more common programmer errors in C++ against which D
 does not guard.  For example, dangling pointers to stack variables that
 have gone out of scope.
Yep. Escape analysis is tricky, but I'd like to see it in D.
   - D's response to this perceived problem is far too heavy-handed,
 because it disallows useful correct code.
Well, D is a systems language, so you can still get the same effect, but it's sufficiently difficult and ugly that it is likely not worthwhile. On the other hand, you can probably simplify it to a single template mixin (see the thread on struct interfaces). Given that it is not a common need (as far as I can tell) and is an inherently unsafe thing, I believe that it is reasonable.
   - I would even say that the reference type classes in D lead to more
 problems.  It is very easy for two objects in D to accidentally share
 internal state, something that is impossible with value types.
struct A { int* i; } A a, b; int* i = new int; a.i = i; b.i = i; Hey look, they share internal state! What mechanism for sharing state is available to by-reference objects but not by-value objects?
Feb 11 2009
parent reply Rainer Deyke <rainerd eldwood.com> writes:
Christopher Wright wrote:
   - I would even say that the reference type classes in D lead to more
 problems.  It is very easy for two objects in D to accidentally share
 internal state, something that is impossible with value types.
struct A { int* i; } A a, b; int* i = new int; a.i = i; b.i = i; Hey look, they share internal state!
That's not accidental. You did that on purpose.
 What mechanism for sharing state is available to by-reference objects
 but not by-value objects?
struct C { T t; } C c1; C c2 = c1; If T was a reference type, 'c1' and 'c2' now share state, and it's up to the programmer to write code to prevent this. Moreover, the D language doesn't even give a hint as to whether T or a reference type or a value type. If T is a template parameter, it could be both. What I'd really like to see is a hybrid of struct and class that has the RAII and value semantics of a struct, but the polymorphism of classes. polymorphic_struct A { } polymorphic_struct B : A { } { B b; A a = b; // Creates a true non-sliced copy of 'b'. } // Destructors are called when the variables go out of scope. At the implementation level, the objects could be placed on the heap unless the compiler determines that this is not necessary. The goal is not performance, but consistent value semantics throughout the language. The alternative is to work backwards and create a wrapper for classes to give them value semantics: struct value_semantics(T) { this(T v) { this.value = v; } this(this) { this.value = this.value.dup; } ~this() { delete this.v; } T opDot() { return this; } T value; } -- Rainer Deyke - rainerd eldwood.com
Feb 12 2009
next sibling parent reply Christopher Wright <dhasenan gmail.com> writes:
Rainer Deyke wrote:
 What mechanism for sharing state is available to by-reference objects
 but not by-value objects?
struct C { T t; } C c1; C c2 = c1; If T was a reference type, 'c1' and 'c2' now share state, and it's up to the programmer to write code to prevent this. Moreover, the D language doesn't even give a hint as to whether T or a reference type or a value type. If T is a template parameter, it could be both.
Okay, reference types don't have value semantics. That's exactly what I would expect. Why is it a problem? Because there is no explicit builtin copying mechanism for classes? If there were such, would it be a problem if copying were not the default?
Feb 12 2009
parent reply Rainer Deyke <rainerd eldwood.com> writes:
Christopher Wright wrote:
 Rainer Deyke wrote:
 What mechanism for sharing state is available to by-reference objects
 but not by-value objects?
struct C { T t; } C c1; C c2 = c1; If T was a reference type, 'c1' and 'c2' now share state, and it's up to the programmer to write code to prevent this. Moreover, the D language doesn't even give a hint as to whether T or a reference type or a value type. If T is a template parameter, it could be both.
Okay, reference types don't have value semantics. That's exactly what I would expect.
That sounds tautological, but many newcomers to D are surprised by reference semantics when they expected value semantics.
 Why is it a problem?
Because reference types don't play well with RAII types. Because unintentional object aliasing a problem orders of magnitude more common than unintentional object slicing, and at least an order of magnitude harder to detect and fix. Because you can't correctly duplicate a multi-dimensional dynamic array in D by using the built-in 'dup' property. Because having two syntactically similar ways of creating user-defined types with different features sets and different semantics is confusing, especially if you later decide that you need a struct to be a class and all your copies turn into reference or vice versa.
 Because there is no explicit builtin
 copying mechanism for classes? If there were such, would it be a problem
 if copying were not the default?
What exactly do you have in mind? Would it allow classes to correctly work with RAII types? Would it prevent unintentional object aliasing? Would it allow multi-dimensional arrays to be correctly duplicated? Would it remove the need for both classes and structs in the language, or at least the need to switch between the two? -- Rainer Deyke - rainerd eldwood.com
Feb 12 2009
parent reply Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
Rainer Deyke wrote:
 Because unintentional object aliasing a problem orders of magnitude more
 common than unintentional object slicing, and at least an order of
 magnitude harder to detect and fix.
 
 Because you can't correctly duplicate a multi-dimensional dynamic array
 in D by using the built-in 'dup' property.
Simply because shallow copies are the default. Usually you can't even have automatic deep copies. What if the array was supposed to be malloc'd or put in a contiguous memory block taken from a memory cache? A .dup that made a deep copy of it would introduce even a larger problem (since it would seem correct) than remembering that dups/struct copies are shallow by default and you need special code to do otherwise.
 Because having two syntactically similar ways of creating user-defined
 types with different features sets and different semantics is confusing,
  especially if you later decide that you need a struct to be a class and
 all your copies turn into reference or vice versa.
 [snip]
 Would it remove the need for both classes and structs in the language,
It's not a bug, it's a feature. What if I decide that I want my int to be a float? Suddenly I have to add all those NaN checks, change my scanf calls, inspect all divisions and places where rounding might happen, not to mention any inline asm or binary shifts... Let's unify floats and ints so this cannot happen. -- Tomasz Stachowiak http://h3.team0xf.com/ h3/h3r3tic on #D freenode
Feb 12 2009
parent reply Rainer Deyke <rainerd eldwood.com> writes:
Tom S wrote:
 Rainer Deyke wrote:
 Because you can't correctly duplicate a multi-dimensional dynamic array
 in D by using the built-in 'dup' property.
Simply because shallow copies are the default. Usually you can't even have automatic deep copies. What if the array was supposed to be malloc'd or put in a contiguous memory block taken from a memory cache? A .dup that made a deep copy of it would introduce even a larger problem (since it would seem correct) than remembering that dups/struct copies are shallow by default and you need special code to do otherwise.
C++ has a way of specifying how deep you want your copies to be at the declaration point: std::vector<boost::shared_ptr<std::vector<int> > > v1, v2; v2 = v1; // Shallow copy. std::vector<std::vector<int> > v3, v4; v4 = v3; // Deep copy. Granted, C++ is a mess and you could do something similar in D by wrapping the reference in a value_semantics wrapper. value_semantics!(value_semantics!(int[])[]) v5, v6; v6 = v5; // Deep copy due to the value_semantics templated struct. Unfortunately this doesn't solve the RAII problem: if value_semantics!(T) deletes the contained reference in its destructor, then it is no longer safe to embed a value_semantics!(T) variable in memory managed by the garbage collector.
 Would it remove the need for both classes and structs in the language,
It's not a bug, it's a feature.
Having both value types and reference types in the language is (arguably) a feature. Having no syntactic distinction between them at the point of use is at best a misfeature. Forcing programmers to change their value types into reference types when they need polymorphism or inheritance, even though safe polymorphic value types are possible, is clearly a misfeature.
 [...] change my scanf calls [...]
Are you serious? -- Rainer Deyke - rainerd eldwood.com
Feb 12 2009
parent Christopher Wright <dhasenan gmail.com> writes:
Rainer Deyke wrote:
 Unfortunately this doesn't solve the RAII problem: if
 value_semantics!(T) deletes the contained reference in its destructor,
 then it is no longer safe to embed a value_semantics!(T) variable in
 memory managed by the garbage collector.
You can take additional steps to ensure safety with notifyRegister, if the type is an object. It's a hole in the language that you can't get notified about the destruction of anything but an object. Maybe there is some way to do this via the runtime and the collector rather than the variable.
Feb 13 2009
prev sibling parent reply Tom S <h3r3tic remove.mat.uni.torun.pl> writes:
Rainer Deyke wrote:
 Christopher Wright wrote:
 What mechanism for sharing state is available to by-reference objects
 but not by-value objects?
struct C { T t; } C c1; C c2 = c1; If T was a reference type, 'c1' and 'c2' now share state, and it's up to the programmer to write code to prevent this.
No, they don't. Each instance of C has its own copy of the 't' reference.
 Moreover, the D language
 doesn't even give a hint as to whether T or a reference type or a value
 type.
Like you can't write "typedef X* T;" in C...
 If T is a template parameter, it could be both.
That's what IsExpression and static assertions are for. -- Tomasz Stachowiak http://h3.team0xf.com/ h3/h3r3tic on #D freenode
Feb 12 2009
parent reply Rainer Deyke <rainerd eldwood.com> writes:
Tom S wrote:
 Rainer Deyke wrote:
 If T was a reference type, 'c1' and 'c2' now share state, and it's up to
 the programmer to write code to prevent this.
No, they don't. Each instance of C has its own copy of the 't' reference.
That's like saying object slicing is an intentional feature. Given the intended semantics of 'C', it's a bug.
 Moreover, the D language
 doesn't even give a hint as to whether T or a reference type or a value
 type.
Like you can't write "typedef X* T;" in C...
The C programmer who does that should be shot. In C++ this idiom has some valid uses (iterators, template metaprogramming), but there remains an important distinction: the syntax for dealing with variables of type 'X*' is different than the syntax for dealing with variables of type 'X'. -- Rainer Deyke - rainerd eldwood.com
Feb 12 2009
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Rainer Deyke wrote:
 Tom S wrote:
 Rainer Deyke wrote:
 If T was a reference type, 'c1' and 'c2' now share state, and it's up to
 the programmer to write code to prevent this.
No, they don't. Each instance of C has its own copy of the 't' reference.
That's like saying object slicing is an intentional feature. Given the intended semantics of 'C', it's a bug.
It's not a bug. There are differences between value types and reference types. Just like how there are differences between atomic types and aggregate types. Or constant types and mutable types. If you want a distinct copy of something, then copy it. -- Daniel
Feb 12 2009
parent reply Rainer Deyke <rainerd eldwood.com> writes:
Daniel Keep wrote:
 It's not a bug.  There are differences between value types and reference
 types.  Just like how there are differences between atomic types and
 aggregate types.  Or constant types and mutable types.
This is a bug: struct MathematicalVector { this(int size) { this.values = new T[size]; } // No copy constructor. // Insert standard mathematical operators here. private T[] values; // Implementation detail. } I want MathematicalVector to be a value type (which is why I declared it as a struct). However, it doesn't behave a value type because I forgot to write the copy constructor. D doesn't cause the bug, but it certainly makes it easier to accidentally write this kind of bug. By contrast, the compiler-generated copy constructors in C++ usually do the right thing for all but a handful of low-level resource-management classes. Which is not to say that C++ doesn't have problems of its own - clearly it does, or I wouldn't be looking at D. -- Rainer Deyke - rainerd eldwood.com
Feb 12 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Rainer Deyke wrote:
 Daniel Keep wrote:
 It's not a bug.  There are differences between value types and reference
 types.  Just like how there are differences between atomic types and
 aggregate types.  Or constant types and mutable types.
This is a bug: struct MathematicalVector { this(int size) { this.values = new T[size]; } // No copy constructor. // Insert standard mathematical operators here. private T[] values; // Implementation detail. } I want MathematicalVector to be a value type (which is why I declared it as a struct). However, it doesn't behave a value type because I forgot to write the copy constructor. D doesn't cause the bug, but it certainly makes it easier to accidentally write this kind of bug. By contrast, the compiler-generated copy constructors in C++ usually do the right thing for all but a handful of low-level resource-management classes. Which is not to say that C++ doesn't have problems of its own - clearly it does, or I wouldn't be looking at D.
C++ ctors won't do the right thing if you use pointers, which is the moral equivalent of using T[] inside MathematicalVector. If you refer to std::vector instead, then that's a carefully-defined type that does have the right copy constructor defined. Andrei
Feb 12 2009
parent reply Rainer Deyke <rainerd eldwood.com> writes:
Andrei Alexandrescu wrote:
 C++ ctors won't do the right thing if you use pointers, which is the
 moral equivalent of using T[] inside MathematicalVector. If you refer to
 std::vector instead, then that's a carefully-defined type that does have
 the right copy constructor defined.
So where's the D equivalent of std::vector? Phobos has nothing. Tango has containers, but they are also reference types. I was under the impression that native arrays were intended to be used directly in D, something I rarely do in C++. Certainly neither of the standard libraries has any hesitation about passing unadorned dynamic arrays around. -- Rainer Deyke - rainerd eldwood.com
Feb 13 2009
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Rainer Deyke wrote:
 Andrei Alexandrescu wrote:
 C++ ctors won't do the right thing if you use pointers, which is the
 moral equivalent of using T[] inside MathematicalVector. If you refer to
 std::vector instead, then that's a carefully-defined type that does have
 the right copy constructor defined.
So where's the D equivalent of std::vector? Phobos has nothing.
It will.
 I was under the impression that native arrays were intended to be used
 directly in D, something I rarely do in C++.  Certainly neither of the
 standard libraries has any hesitation about passing unadorned dynamic
 arrays around.
Phobos2 plans to consistently consider T[] a range, not a full-fledged array. A range corresponds to a pair of iterators in STL. Andrei
Feb 13 2009
parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Fri, 13 Feb 2009 17:24:54 +0300, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 Rainer Deyke wrote:
 Andrei Alexandrescu wrote:
 C++ ctors won't do the right thing if you use pointers, which is the
 moral equivalent of using T[] inside MathematicalVector. If you refer  
 to
 std::vector instead, then that's a carefully-defined type that does  
 have
 the right copy constructor defined.
So where's the D equivalent of std::vector? Phobos has nothing.
It will.
 I was under the impression that native arrays were intended to be used
 directly in D, something I rarely do in C++.  Certainly neither of the
 standard libraries has any hesitation about passing unadorned dynamic
 arrays around.
Phobos2 plans to consistently consider T[] a range, not a full-fledged array. A range corresponds to a pair of iterators in STL. Andrei
Will T[] get front, back, empty properties, and popFront(), popBack() methods? Perhaps, its the time T[] internal structure is changed! For example, ptr+size replaced by two pointers, some additional fields added etc..
Feb 13 2009
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Denis Koroskin wrote:
 On Fri, 13 Feb 2009 17:24:54 +0300, Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org> wrote:
 
 Rainer Deyke wrote:
 Andrei Alexandrescu wrote:
 C++ ctors won't do the right thing if you use pointers, which is the
 moral equivalent of using T[] inside MathematicalVector. If you 
 refer to
 std::vector instead, then that's a carefully-defined type that does 
 have
 the right copy constructor defined.
So where's the D equivalent of std::vector? Phobos has nothing.
It will.
 I was under the impression that native arrays were intended to be used
 directly in D, something I rarely do in C++.  Certainly neither of the
 standard libraries has any hesitation about passing unadorned dynamic
 arrays around.
Phobos2 plans to consistently consider T[] a range, not a full-fledged array. A range corresponds to a pair of iterators in STL. Andrei
Will T[] get front, back, empty properties, and popFront(), popBack() methods?
Yes, not as methods, but as free functions.
 Perhaps, its the time T[] internal structure is changed!
 For example, ptr+size replaced by two pointers, some additional fields 
 added etc..
I agree. Walter said let's get ranges going and then we can look into optimizing the structure. Ranges seem to work really well so the structural change will follow soon. Andrei
Feb 13 2009
prev sibling parent Yigal Chripun <yigal100 gmail.com> writes:
Denis Koroskin wrote:
 On Fri, 13 Feb 2009 17:24:54 +0300, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 Rainer Deyke wrote:
 Andrei Alexandrescu wrote:
 C++ ctors won't do the right thing if you use pointers, which is the
 moral equivalent of using T[] inside MathematicalVector. If you
 refer to
 std::vector instead, then that's a carefully-defined type that does
 have
 the right copy constructor defined.
So where's the D equivalent of std::vector? Phobos has nothing.
It will.
 I was under the impression that native arrays were intended to be used
 directly in D, something I rarely do in C++. Certainly neither of the
 standard libraries has any hesitation about passing unadorned dynamic
 arrays around.
Phobos2 plans to consistently consider T[] a range, not a full-fledged array. A range corresponds to a pair of iterators in STL. Andrei
Will T[] get front, back, empty properties, and popFront(), popBack() methods? Perhaps, its the time T[] internal structure is changed! For example, ptr+size replaced by two pointers, some additional fields added etc..
once upon a time there was a huge discussion about template syntax. one of the suggestions was: A!(T) => A[t] with such syntax we could use: Array[T] - this would be an array with the added capacity field Map[Key, Value] - instead of the current AA's Set[T] - example of user defined template ... Array[int] arr1; // dyn. array Array[int, 3] arr2; static array with size 3 or maybe even better: if n is constant => static array, otherwise dyn. with pre-set capacity Array[int] arr3(n); auto r = arr1[]; // range/slice of arr1 IMHO, it's not a good idea to have container types in the language. they should be provided by the stdlib and the language needs to provide only the syntax to make such types behave like builtins. D already provides operator overloads for that.
Feb 13 2009
prev sibling parent Weed <resume755 mail.ru> writes:
Rainer Deyke :
 Michel Fortin wrote:
 Polymorphism doesn't work very well while passing objects by value, even
 in C++. This is called the slicing problem.
I have heard about the slicing problem. I know what it is. But in all my years of using C++ as my primary language, I have never actually encountered it. I don't believe it actually exists.
I am absolutely agree with you. Besides, slicing it is possible to detect in a compile time in many cases. It can be too grandiloquent sounds, but in D us have deprived of one degree of freedom - freedom to use a stack.
Feb 08 2009
prev sibling parent reply Weed <resume755 mail.ru> writes:
Michel Fortin :
 On 2009-02-08 09:30:08 -0500, Weed <resume755 mail.ru> said:
 
 Let's assume, polymorphism is necessary to these objects
Polymorphism doesn't work very well while passing objects by value, even in C++. This is called the slicing problem. <http://stackoverflow.com/questions/274626/what-is-the-slicing-problem-in-c> I think D does a good job at avoiding that problem.
By performance loss :(
Feb 08 2009
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2009-02-08 23:43:13 -0500, Weed <resume755 mail.ru> said:

 Michel Fortin пишет:
 On 2009-02-08 09:30:08 -0500, Weed <resume755 mail.ru> said:
 
 Let's assume, polymorphism is necessary to these objects
Polymorphism doesn't work very well while passing objects by value, even in C++. This is called the slicing problem. <http://stackoverflow.com/questions/274626/what-is-the-slicing-problem-in-c> I think D does a good job at avoiding that problem.
By performance loss :(
No. By forbiding the cases that leads to slicing, like returning a polymorphic object by value. Returning something by-value always cause slicing in C++. Try this C++ code: #include <iostream> class A { public: virtual void hello() { std::cout << "hello from A" << std::endl; } }; class B : public A { public: virtual void hello() { std::cout << "hello from B" << std::endl; } }; A test() { B b; b.hello(); // prints "hello from B" return b; } int main() { test().hello(); // prints "hello from A" A a = test(); a.hello(); // prints "hello from A" } Here, returning B by value "slices" the object, transforming it into a A. There is absolutely no polymorphic behaviour when returning by value. It's as if virtual functions weren't virtual at all: your B object is transformed to a A when it is returned. To preserve polymorphism, you need to return a pointer or a reference, but then test() can't allocate the object on the stack. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Feb 09 2009
parent reply Weed <resume755 mail.ru> writes:
Michel Fortin :
 On 2009-02-08 23:43:13 -0500, Weed <resume755 mail.ru> said:
 
 Michel Fortin :
 On 2009-02-08 09:30:08 -0500, Weed <resume755 mail.ru> said:

 Let's assume, polymorphism is necessary to these objects
Polymorphism doesn't work very well while passing objects by value, even in C++. This is called the slicing problem. <http://stackoverflow.com/questions/274626/what-is-the-slicing-problem-in-c> I think D does a good job at avoiding that problem.
By performance loss :(
No. By forbiding the cases that leads to slicing, like returning a polymorphic object by value.
Let's think, can there are other ways to solve problem? Here, for example my reasons: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=81958
Feb 09 2009
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2009-02-09 07:00:56 -0500, Weed <resume755 mail.ru> said:

 No. By forbiding the cases that leads to slicing, like returning a
 polymorphic object by value.
Let's think, can there are other ways to solve problem? Here, for example my reasons: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=81958
I'm
 
not sure I'm getting what you mean in that post. It seems like you want the ability to copy classes, and thus pass them by value, but only when there would be no type conversion. I'm not getting where this can be useful though: by forcing your classes to be of a specific type, with no derived types allowed, you're losing polymorphism. The only advantage you have is that your type can be derived from another so you can reuse some of its implementation. There are other ways to acheive that in D however (mixins come to mind). -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Feb 09 2009
next sibling parent Michel Fortin <michel.fortin michelf.com> writes:
On 2009-02-09 07:34:44 -0500, Michel Fortin <michel.fortin michelf.com> said:

 The only advantage you have is that your type can be derived from 
 another so you can reuse some of its implementation. There are other 
 ways to acheive that in D however (mixins come to mind).
That said, I'm not against adding struct inheritance if it can be done in a way that avoids slicing problems. I think this can be acheived by making slicing innoculous: 1. forbid overriding base members 2. forbid destructors in derived strucs (or else slicing would lose the destructor) Open questions: Is that constraining enough to avoid slicing problems? Do these constrains make the feature irrelevant? -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Feb 09 2009
prev sibling next sibling parent reply Don <nospam nospam.com> writes:
Michel Fortin wrote:
 On 2009-02-09 07:00:56 -0500, Weed <resume755 mail.ru> said:
 
 No. By forbiding the cases that leads to slicing, like returning a
 polymorphic object by value.
Let's think, can there are other ways to solve problem? Here, for example my reasons: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmar .D&article_id=81958
I'm

 not sure I'm getting what you mean in that post.
 
 It seems like you want the ability to copy classes, and thus pass them 
 by value, but only when there would be no type conversion.
 
 I'm not getting where this can be useful though: by forcing your classes 
 to be of a specific type, with no derived types allowed, you're losing 
 polymorphism. The only advantage you have is that your type can be 
 derived from another so you can reuse some of its implementation. There 
 are other ways to acheive that in D however (mixins come to mind).
 
The one case I could think of was the strategy pattern: no data is added (including, no virtual functions) -- the only thing that's added is a different implementation of an existing virtual function. In such a situation, the slicing problem cannot happen. You can have an array of polymorphic types. But the language won't allow it. However, I've encountered this problem in C++ as well. Allowing stack-based classes is NOT sufficient to solve it. What you actually want is a struct with a vtable pointer stored IN the struct itself (rather than one instance of the vtable per struct).
Feb 09 2009
parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Mon, 09 Feb 2009 15:53:59 +0300, Don <nospam nospam.com> wrote:

 Michel Fortin wrote:
 On 2009-02-09 07:00:56 -0500, Weed <resume755 mail.ru> said:

 No. By forbiding the cases that leads to slicing, like returning a
 polymorphic object by value.
Let's think, can there are other ways to solve problem? Here, for example my reasons: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=81958
I'm

 not sure I'm getting what you mean in that post.
  It seems like you want the ability to copy classes, and thus pass them  
 by value, but only when there would be no type conversion.
  I'm not getting where this can be useful though: by forcing your  
 classes to be of a specific type, with no derived types allowed, you're  
 losing polymorphism. The only advantage you have is that your type can  
 be derived from another so you can reuse some of its implementation.  
 There are other ways to acheive that in D however (mixins come to mind).
The one case I could think of was the strategy pattern: no data is added (including, no virtual functions) -- the only thing that's added is a different implementation of an existing virtual function. In such a situation, the slicing problem cannot happen.
Michel has posted (2 posts up) an example of a class that happen to have no member fields at all (virtual methods only). And yet it still suffers from slicing.
 You can have an array of  
 polymorphic types. But the language won't allow it.

 However, I've encountered this problem in C++ as well. Allowing  
 stack-based classes is NOT sufficient to solve it. What you actually  
 want is a struct with a vtable pointer stored IN the struct itself  
 (rather than one instance of the vtable per struct).
Feb 09 2009
parent Michel Fortin <michel.fortin michelf.com> writes:
On 2009-02-09 16:02:10 -0500, "Denis Koroskin" <2korden gmail.com> said:

 The one case I could think of was the strategy pattern: no data is 
 added  (including, no virtual functions) -- the only thing that's added 
 is a  different implementation of an existing virtual function. In such 
 a  situation, the slicing problem cannot happen.
Michel has posted (2 posts up) an example of a class that happen to have no member fields at all (virtual methods only). And yet it still suffers from slicing.
Indeed. But that's in C++. It could certainly be possible to make that work differently in another language. I'm not sure it's worth it for D though. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Feb 09 2009
prev sibling parent Weed <resume755 mail.ru> writes:
Michel Fortin :
 On 2009-02-09 07:00:56 -0500, Weed <resume755 mail.ru> said:
 
 No. By forbiding the cases that leads to slicing, like returning a
 polymorphic object by value.
Let's think, can there are other ways to solve problem? Here, for example my reasons: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=81958
I'm

 not sure I'm getting what you mean in that post.
 
 It seems like you want the ability to copy classes, and thus pass them
 by value, but only when there would be no type conversion.
 
Yes, this is the easiest way that came to my head
 I'm not getting where this can be useful though: by forcing your classes
 to be of a specific type, with no derived types allowed, you're losing
 polymorphism.
Yes
 The only advantage you have is that your type can be
 derived from another so you can reuse some of its implementation.
And still able to pass class instance through a stack! And I do not propose to remove the traditional class in the heap
 There
 are other ways to acheive that in D however (mixins come to mind).
 
Feb 09 2009
prev sibling next sibling parent reply naryl <cy ngs.ru> writes:
It's a bit offtopic but I'd be grateful if someone can explain why D with
structs completes this simple benchmark (see attachment) so slowly compared to
C++ with classes on stack:

D struct - 27.85s 
C++ stack - 8.32s

D class - 271.58s
C++ heap - 249.32s

Compiled with "dmd -O". -release decreases performance by 10% in this case.
-inline doesn't affects it at all.
Feb 08 2009
next sibling parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Sun, 08 Feb 2009 18:09:41 +0300, naryl <cy ngs.ru> wrote:

 It's a bit offtopic but I'd be grateful if someone can explain why D  
 with structs completes this simple benchmark (see attachment) so slowly  
 compared to C++ with classes on stack:

 D struct - 27.85s
 C++ stack - 8.32s

 D class - 271.58s
 C++ heap - 249.32s

 Compiled with "dmd -O". -release decreases performance by 10% in this  
 case. -inline doesn't affects it at all.
Well, you don't compare C++ vs D struct speed but rather C++ vs D IO. I believe writefln is a bottleneck.
Feb 08 2009
parent "Denis Koroskin" <2korden gmail.com> writes:
On Sun, 08 Feb 2009 18:20:47 +0300, Denis Koroskin <2korden gmail.com> wrote:

 On Sun, 08 Feb 2009 18:09:41 +0300, naryl <cy ngs.ru> wrote:

 It's a bit offtopic but I'd be grateful if someone can explain why D  
 with structs completes this simple benchmark (see attachment) so slowly  
 compared to C++ with classes on stack:

 D struct - 27.85s
 C++ stack - 8.32s

 D class - 271.58s
 C++ heap - 249.32s

 Compiled with "dmd -O". -release decreases performance by 10% in this  
 case. -inline doesn't affects it at all.
Well, you don't compare C++ vs D struct speed but rather C++ vs D IO. I believe writefln is a bottleneck.
Nevermind, I didn't understand the benchmark from quick glance.
Feb 08 2009
prev sibling parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Sun, 08 Feb 2009 18:09:41 +0300, naryl <cy ngs.ru> wrote:

 It's a bit offtopic but I'd be grateful if someone can explain why D  
 with structs completes this simple benchmark (see attachment) so slowly  
 compared to C++ with classes on stack:

 D struct - 27.85s
 C++ stack - 8.32s

 D class - 271.58s
 C++ heap - 249.32s

 Compiled with "dmd -O". -release decreases performance by 10% in this  
 case. -inline doesn't affects it at all.
I noticed that you calculate Fib(27) in fibs.cc and Fib(40) in fibs.d Can this affect such a big difference between C++ and D version?
Feb 08 2009
parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Sun, 08 Feb 2009 18:40:53 +0300, Denis Koroskin <2korden gmail.com> wrote:

 On Sun, 08 Feb 2009 18:09:41 +0300, naryl <cy ngs.ru> wrote:

 It's a bit offtopic but I'd be grateful if someone can explain why D  
 with structs completes this simple benchmark (see attachment) so slowly  
 compared to C++ with classes on stack:

 D struct - 27.85s
 C++ stack - 8.32s

 D class - 271.58s
 C++ heap - 249.32s

 Compiled with "dmd -O". -release decreases performance by 10% in this  
 case. -inline doesn't affects it at all.
I noticed that you calculate Fib(27) in fibs.cc and Fib(40) in fibs.d Can this affect such a big difference between C++ and D version?
They both perform roughly the same when this typo is corrected.
Feb 08 2009
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Denis Koroskin wrote:
 On Sun, 08 Feb 2009 18:40:53 +0300, Denis Koroskin <2korden gmail.com> 
 wrote:
 
 On Sun, 08 Feb 2009 18:09:41 +0300, naryl <cy ngs.ru> wrote:

 It's a bit offtopic but I'd be grateful if someone can explain why D 
 with structs completes this simple benchmark (see attachment) so 
 slowly compared to C++ with classes on stack:

 D struct - 27.85s
 C++ stack - 8.32s

 D class - 271.58s
 C++ heap - 249.32s

 Compiled with "dmd -O". -release decreases performance by 10% in this 
 case. -inline doesn't affects it at all.
I noticed that you calculate Fib(27) in fibs.cc and Fib(40) in fibs.d Can this affect such a big difference between C++ and D version?
They both perform roughly the same when this typo is corrected.
It was a ploy! :o) Andrei
Feb 08 2009
prev sibling parent reply naryl <cy ngs.ru> writes:
Denis Koroskin Wrote:

 On Sun, 08 Feb 2009 18:40:53 +0300, Denis Koroskin <2korden gmail.com> wrote:
 
 On Sun, 08 Feb 2009 18:09:41 +0300, naryl <cy ngs.ru> wrote:

 It's a bit offtopic but I'd be grateful if someone can explain why D  
 with structs completes this simple benchmark (see attachment) so slowly  
 compared to C++ with classes on stack:

 D struct - 27.85s
 C++ stack - 8.32s

 D class - 271.58s
 C++ heap - 249.32s

 Compiled with "dmd -O". -release decreases performance by 10% in this  
 case. -inline doesn't affects it at all.
I noticed that you calculate Fib(27) in fibs.cc and Fib(40) in fibs.d Can this affect such a big difference between C++ and D version?
They both perform roughly the same when this typo is corrected.
Sorry. :) For n=40 I get: C++ compiled with "g++ -O fibs.cc" - 5.37s D compiled with "dmd -O -inline fibs.d" - 14.32s D compiled with "dmd -O -inline -release fibs.d" - 15.20s DMD 2.023 is still almost three times slower.
Feb 08 2009
parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Sun, 08 Feb 2009 20:24:08 +0300, naryl <cy ngs.ru> wrote:

 Denis Koroskin Wrote:

 On Sun, 08 Feb 2009 18:40:53 +0300, Denis Koroskin <2korden gmail.com>  
 wrote:

 On Sun, 08 Feb 2009 18:09:41 +0300, naryl <cy ngs.ru> wrote:

 It's a bit offtopic but I'd be grateful if someone can explain why D
 with structs completes this simple benchmark (see attachment) so  
slowly
 compared to C++ with classes on stack:

 D struct - 27.85s
 C++ stack - 8.32s

 D class - 271.58s
 C++ heap - 249.32s

 Compiled with "dmd -O". -release decreases performance by 10% in this
 case. -inline doesn't affects it at all.
I noticed that you calculate Fib(27) in fibs.cc and Fib(40) in fibs.d Can this affect such a big difference between C++ and D version?
They both perform roughly the same when this typo is corrected.
Sorry. :) For n=40 I get: C++ compiled with "g++ -O fibs.cc" - 5.37s D compiled with "dmd -O -inline fibs.d" - 14.32s D compiled with "dmd -O -inline -release fibs.d" - 15.20s DMD 2.023 is still almost three times slower.
Here is code, setting and result I got. D version: import std.stdio; extern(Windows) int timeGetTime(); struct Fib { private int _value; int value() { if(_value <= 2) return 1; scope f1 = Fib(_value - 1); scope f2 = Fib(_value - 2); return f1.value() + f2.value(); } } void main() { int start = timeGetTime(); int value = 0; foreach (i; 0 .. 10) { value += Fib(40).value; } int stop = timeGetTime(); writefln(value); writefln("Time elapsed: %s", stop - start); } C++ version: #include <stdio.h> #include <windows.h> class Fib { private: int _value; public: Fib(int n) { _value = n; } int value() { if(_value <= 2) return 1; Fib f1 = Fib(_value - 1); Fib f2 = Fib(_value - 2); return f1.value() + f2.value(); } }; int main() { int start = timeGetTime(); int value = 0; for(int i=0; i<10; i++) { Fib x = Fib(40); value += x.value(); } int stop = timeGetTime(); printf("%d\n", value); printf("Time elapsed: %d\n", stop - start); return 0; } And here are results (best/average of 3 runs): DMD2.023 - 12.492/12.576 ms (-O -inline) DMC8.42n - 13.941/14.131 ms (-O -inline)
Feb 08 2009
next sibling parent reply naryl <cy ngs.ru> writes:
Denis Koroskin Wrote:
 And here are results (best/average of 3 runs):
 
 DMD2.023 - 12.492/12.576 ms (-O -inline)
 DMC8.42n - 13.941/14.131 ms (-O -inline)
 
 
The only explanation I see is gcc does some optimization that dmd backend doesn't.
Feb 08 2009
next sibling parent grauzone <none example.net> writes:
naryl wrote:
 Denis Koroskin Wrote:
 And here are results (best/average of 3 runs):

 DMD2.023 - 12.492/12.576 ms (-O -inline)
 DMC8.42n - 13.941/14.131 ms (-O -inline)
The only explanation I see is gcc does some optimization that dmd backend doesn't.
That's a good explanation. The only positive thing about the dmd backend (or dmd in general) is its compile speed.
Feb 08 2009
prev sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Sun, 08 Feb 2009 23:45:41 +0300, naryl <cy ngs.ru> wrote:

 Denis Koroskin Wrote:
 And here are results (best/average of 3 runs):

 DMD2.023 - 12.492/12.576 ms (-O -inline)
 DMC8.42n - 13.941/14.131 ms (-O -inline)
The only explanation I see is gcc does some optimization that dmd backend doesn't.
Yes, that's why you can't claim D is slow because GCC outperforms DMD.
Feb 08 2009
prev sibling parent reply Weed <resume755 mail.ru> writes:
Denis Koroskin :

 And here are results (best/average of 3 runs):
 
 DMD2.023 - 12.492/12.576 ms (-O -inline)
 DMC8.42n - 13.941/14.131 ms (-O -inline)
 
 
Try to return from value() a class instance
Feb 08 2009
parent reply naryl <cy ngs.ru> writes:
Weed Wrote:
 Denis Koroskin �����:
 
 And here are results (best/average of 3 runs):
 
 DMD2.023 - 12.492/12.576 ms (-O -inline)
 DMC8.42n - 13.941/14.131 ms (-O -inline)
 
 
Try to return from value() a class instance
In this case both C++ and D performance drops almost tenfold.
Feb 08 2009
parent Weed <resume755 mail.ru> writes:
naryl :
 Weed Wrote:
 Denis Koroskin :

 And here are results (best/average of 3 runs):

 DMD2.023 - 12.492/12.576 ms (-O -inline)
 DMC8.42n - 13.941/14.131 ms (-O -inline)
Try to return from value() a class instance
In this case both C++ and D performance drops almost tenfold.
Hmmm. Can you show code?
Feb 08 2009
prev sibling next sibling parent reply Radu <radu.racariu void.space> writes:
Weed wrote:
 (Has started here:
 http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=81359)

 To me still does not give rest performance of classes (in comparison
 with C++ or with D structs)

 I still think that it is a serious problem.

 Colleagues from our national D forum have asked to show it and I have
 written simple examples on D. I want to share with you too them.

 On my computer the code with structure (i.e. object by value) runs in 6
 times faster than a code with a class:

 $ time ./struct

 real    0m8.515s
 user    0m7.796s
 sys     0m0.016s
 $ time ./class

 real    0m52.185s
 user    0m40.543s
 sys     0m0.076s

 The code on C++ is also approximately in 6 times faster a code with
 classes on D. (I do not give an example on C++ because classes on C++
 work just as structures in D.)

 I think with it it is necessary to do something.


 Examples code:

 //========================
 struct C {
     int i;
     real[5] unused; // to prevent returning this object in registers

     C opAdd( C src ) {
         C ret;
         ret.i = i + src.i;
         return ret;
     }
 }

 int main() {
     C c1;
     C c2;

     // initialise i by "random" value to prevent compile-time calculation
     c1.i = cast(int)&c1;
     c2.i = 0;

     for(int i = 0; i < 50_000_000; ++i)
         c2 = c1 + c1 + c1;

     return c2.i;
 }

 //========================

 class C {
     int i;
     real[5] unused; // to prevent returning this object in registers

     C opAdd( C src ) {
         auto ret = new C;
         ret.i = i + src.i;
         return ret;
     }
 }

 int main() {
     auto c1 = new C;
     auto c2 = new C;

     // initialise i by "random" value to prevent compile-time calculation
     c1.i = cast(int)&c1;
     c2.i = 0;

     for(int i = 0; i < 50_000_000; ++i)
         c2 = c1 + c1 + c1;

     return c2.i;
 }
 //========================
   
While nor so orthodox, this improves the situation a bit: template stackAllocator(T) { new(size_t size, void* sp = alloca(T.classinfo.init.length)) { return sp; } delete(void* ptr) { } } final class C { int i; real[5] unused; // to prevent returning this object in registers C opAdd(C src) { auto ret = new C; ret.i = i + src.i; return ret; } mixin stackAllocator!(C); } Radu
Feb 08 2009
parent Weed <resume755 mail.ru> writes:
Radu :

 While nor so orthodox, this improves the situation a bit:
 
 template stackAllocator(T) {
    new(size_t size, void* sp = alloca(T.classinfo.init.length)) {
        return sp;
    }
 
    delete(void* ptr) {
    }
 }
 
 final class C {
    int i;
    real[5] unused; // to prevent returning this object in registers
 
    C opAdd(C src) {
        auto ret = new C;
        ret.i = i + src.i;
        return ret;
    }
 
    mixin stackAllocator!(C);
 
 }
 
 Radu
If the used object it is impossible to change? It is written by other person, for example? And, we all will take for a rule in each object using overload to add stackAllocator?
Feb 08 2009
prev sibling next sibling parent reply Christopher Wright <dhasenan gmail.com> writes:
Weed wrote:
 (Has started here:
 http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=81359)
 
 To me still does not give rest performance of classes (in comparison
 with C++ or with D structs)
On my system, your struct example averaged 0.36 seconds, and your class example averaged 0.38 seconds. Your benchmark is flawed in three ways: 1. You're timing allocations in the class example. Use opAddAssign to avoid it. 2. You're passing large structs in the struct example. Use ref to avoid it. 3. c1 is never assigned to, so c1 + c1 + c1 is moved outside the loop. The assignment has no side effect, so the loop is optimized out. Replace "c1 + c1 + c1" with "c1 + c2 + c1", for instance, and the struct example takes 20 seconds rather than 0.36. The original class example takes 57 seconds to do 50 million allocations. Using those tricks, the class example takes about four seconds on my machine, and the struct example takes two. For reference, the benchmarks I used: // class example ------------------------- scope class C { int i; real[5] unused; // to prevent returning this object in registers final void opAddAssign( C src ) { this.i += src.i; } } int main() { scope c1 = new C; scope c2 = new C; // initialise i by "random" value to prevent compile-time calculation c1.i = cast(int)&c1; c2.i = 0; for(int i = 0; i < 50_000_000; ++i) { c2 += c1; c2 += c1; c2 += c1; } return c2.i; } // struct example -------------------------- struct C { int i; real[5] unused; // to prevent returning this object in registers void opAddAssign( ref C src ) { this.i += src.i; } } int main() { C c1, c2; // initialise i by "random" value to prevent compile-time calculation c1.i = cast(int)&c1; c2.i = 0; for(int i = 0; i < 50_000_000; ++i) { c2 += c1; c2 += c1; c2 += c1; } return c2.i; }
Feb 08 2009
parent reply Weed <resume755 mail.ru> writes:
Christopher Wright :
 Weed wrote:
 (Has started here:
 http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=81359)


 To me still does not give rest performance of classes (in comparison
 with C++ or with D structs)
On my system, your struct example averaged 0.36 seconds, and your class example averaged 0.38 seconds. Your benchmark is flawed in three ways: 1. You're timing allocations in the class example. Use opAddAssign to avoid it.
Earlier I proved that it is impossible. For example here in such expression: ============== space_ship_1.calculatePathTo("Moon").getCheckpoint(3).getCoords; In this example we create a temporary class "path", create temporary class "checkpoint" and we take coords of checkpoint of this path. It is not expedient to us to store all this path and checkpoint because it is vary. ==============
 2. You're passing large structs in the struct example. Use ref to avoid it.
 3. c1 is never assigned to, so c1 + c1 + c1 is moved outside the loop.
 The assignment has no side effect, so the loop is optimized out. Replace
 "c1 + c1 + c1" with "c1 + c2 + c1", for instance, and the struct example
 takes 20 seconds rather than 0.36.
Really, it has a little affected. Thanks!
Feb 08 2009
parent reply Christopher Wright <dhasenan gmail.com> writes:
Weed wrote:
 Christopher Wright :
 Weed wrote:
 (Has started here:
 http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=81359)


 To me still does not give rest performance of classes (in comparison
 with C++ or with D structs)
On my system, your struct example averaged 0.36 seconds, and your class example averaged 0.38 seconds. Your benchmark is flawed in three ways: 1. You're timing allocations in the class example. Use opAddAssign to avoid it.
Earlier I proved that it is impossible. For example here in such expression: ============== space_ship_1.calculatePathTo("Moon").getCheckpoint(3).getCoords; In this example we create a temporary class "path", create temporary class "checkpoint" and we take coords of checkpoint of this path. It is not expedient to us to store all this path and checkpoint because it is vary. ==============
In that example, you can use structs instead of classes. Your response to that is that structs do not participate in polymorphism. There was a suggestion elsewhere like this: interface IPathResolver { Checkpoint getCheckpoint(Path* path, int i); } struct Path { char[] path; // any other info you need.... IPathResolver resolver; Checkpoint getCheckpoint(int value) { return resolver.getCheckpoint(this, value); } } This way, you only allocate once for each type you need, you have polymorphism, and you can put stuff on the stack for quick access.
Feb 08 2009
parent reply Weed <resume755 mail.ru> writes:
Christopher Wright :
 Weed wrote:
 Christopher Wright :
 Weed wrote:
 (Has started here:
 http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=81359)



 To me still does not give rest performance of classes (in comparison
 with C++ or with D structs)
On my system, your struct example averaged 0.36 seconds, and your class example averaged 0.38 seconds. Your benchmark is flawed in three ways: 1. You're timing allocations in the class example. Use opAddAssign to avoid it.
Earlier I proved that it is impossible. For example here in such expression: ============== space_ship_1.calculatePathTo("Moon").getCheckpoint(3).getCoords; In this example we create a temporary class "path", create temporary class "checkpoint" and we take coords of checkpoint of this path. It is not expedient to us to store all this path and checkpoint because it is vary. ==============
In that example, you can use structs instead of classes. Your response to that is that structs do not participate in polymorphism. There was a suggestion elsewhere like this: interface IPathResolver { Checkpoint getCheckpoint(Path* path, int i); } struct Path { char[] path; // any other info you need.... IPathResolver resolver; Checkpoint getCheckpoint(int value) { return resolver.getCheckpoint(this, value); } } This way, you only allocate once for each type you need, you have polymorphism, and you can put stuff on the stack for quick access.
And if I need some different such combinations? For each it is necessary to write such 8-10 lines? This is terrible!
Feb 08 2009
next sibling parent downs <default_357-line yahoo.de> writes:
Weed wrote:
 Christopher Wright :
 Weed wrote:
 Christopher Wright :
 Weed wrote:
 (Has started here:
 http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=81359)



 To me still does not give rest performance of classes (in comparison
 with C++ or with D structs)
On my system, your struct example averaged 0.36 seconds, and your class example averaged 0.38 seconds. Your benchmark is flawed in three ways: 1. You're timing allocations in the class example. Use opAddAssign to avoid it.
Earlier I proved that it is impossible. For example here in such expression: ============== space_ship_1.calculatePathTo("Moon").getCheckpoint(3).getCoords; In this example we create a temporary class "path", create temporary class "checkpoint" and we take coords of checkpoint of this path. It is not expedient to us to store all this path and checkpoint because it is vary. ==============
In that example, you can use structs instead of classes. Your response to that is that structs do not participate in polymorphism. There was a suggestion elsewhere like this: interface IPathResolver { Checkpoint getCheckpoint(Path* path, int i); } struct Path { char[] path; // any other info you need.... IPathResolver resolver; Checkpoint getCheckpoint(int value) { return resolver.getCheckpoint(this, value); } } This way, you only allocate once for each type you need, you have polymorphism, and you can put stuff on the stack for quick access.
And if I need some different such combinations? For each it is necessary to write such 8-10 lines? This is terrible!
I'm sure you can do something with templates. :)
Feb 08 2009
prev sibling parent reply Christopher Wright <dhasenan gmail.com> writes:
Weed wrote:
 And if I need some different such combinations? For each it is necessary
 to write such 8-10 lines? This is terrible!
You need to add those lines for every method you need virtual dispatch with for your value type. It's an overhead of three lines per method, two for the interface (declaration and member), and one extra line where you create the struct. If you're reasonable, your struct constructor will create a default instance. So, it's not that great an overhead.
Feb 09 2009
parent reply Weed <resume755 mail.ru> writes:
Christopher Wright :
 Weed wrote:
 And if I need some different such combinations? For each it is necessary
 to write such 8-10 lines? This is terrible!
You need to add those lines for every method you need virtual dispatch with for your value type. It's an overhead of three lines per method, two for the interface (declaration and member), and one extra line where you create the struct. If you're reasonable, your struct constructor will create a default instance. So, it's not that great an overhead.
Do not be surprised that so many continue to write in C++! :)
Feb 09 2009
parent Yigal Chripun <yigal100 gmail.com> writes:
Weed wrote:
 Christopher Wright :
 Weed wrote:
 And if I need some different such combinations? For each it is necessary
 to write such 8-10 lines? This is terrible!
You need to add those lines for every method you need virtual dispatch with for your value type. It's an overhead of three lines per method, two for the interface (declaration and member), and one extra line where you create the struct. If you're reasonable, your struct constructor will create a default instance. So, it's not that great an overhead.
Do not be surprised that so many continue to write in C++! :)
huh? there are still billions of people that continue smoking even though the problems that causes are well known. people have bad habits - using C++ instead of proper languages (like D) is one of them. Unless a person wants to be cured, nothing can be done to cure him of such a strong addiction. I hope you too will one day be cured of the illness that is C++.
Feb 09 2009
prev sibling next sibling parent reply naryl <cy ngs.ru> writes:
Weed Wrote:
 naryl �����:
 Weed Wrote:
 Denis Koroskin ���������������:

 And here are results (best/average of 3 runs):

 DMD2.023 - 12.492/12.576 ms (-O -inline)
 DMC8.42n - 13.941/14.131 ms (-O -inline)
Try to return from value() a class instance
In this case both C++ and D performance drops almost tenfold.
Hmmm. Can you show code?
Yes. It's in the attachment: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=83523
Feb 08 2009
parent Weed <resume755 mail.ru> writes:
naryl :
 Weed Wrote:
 naryl :
 Weed Wrote:
 Denis Koroskin :

 And here are results (best/average of 3 runs):

 DMD2.023 - 12.492/12.576 ms (-O -inline)
 DMC8.42n - 13.941/14.131 ms (-O -inline)
Try to return from value() a class instance
In this case both C++ and D performance drops almost tenfold.
May be performance do not fall, it become equally high?
Feb 08 2009
prev sibling next sibling parent reply Kagamin <spam here.lot> writes:
Weed Wrote:

 The code on C++ is also approximately in 6 times faster a code with
 classes on D. (I do not give an example on C++ because classes on C++
 work just as structures in D.)
 class C {
     int i;
     real[5] unused; // to prevent returning this object in registers
 
     C opAdd( C src ) {
         auto ret = new C;
         ret.i = i + src.i;
         return ret;
     }
 }
Well, D class code here is not equivalent to C++ class code. D code has more features, namely, it's polymorphic: C.opAdd is able to work with classes, derived from C, while corresponding C++ code is unable to do so. If you can't use polymorphism, why do you use classes?
Feb 09 2009
next sibling parent Weed <resume755 mail.ru> writes:
Kagamin :
 Weed Wrote:
 
 The code on C++ is also approximately in 6 times faster a code with
 classes on D. (I do not give an example on C++ because classes on C++
 work just as structures in D.)
 class C {
     int i;
     real[5] unused; // to prevent returning this object in registers

     C opAdd( C src ) {
         auto ret = new C;
         ret.i = i + src.i;
         return ret;
     }
 }
Well, D class code here is not equivalent to C++ class code. D code has more features, namely, it's polymorphic: C.opAdd is able to work with classes, derived from C, while corresponding C++ code is unable to do so. If you can't use polymorphism, why do you use classes?
There opAdd is only for demonstration. In real life it may be virtual method getSomething()
Feb 09 2009
prev sibling next sibling parent reply Weed <resume755 mail.ru> writes:
Kagamin :
 Weed Wrote:
 
 The code on C++ is also approximately in 6 times faster a code with
 classes on D. (I do not give an example on C++ because classes on C++
 work just as structures in D.)
 class C {
     int i;
     real[5] unused; // to prevent returning this object in registers

     C opAdd( C src ) {
         auto ret = new C;
         ret.i = i + src.i;
         return ret;
     }
 }
Well, D class code here is not equivalent to C++ class code. D code has more features, namely, it's polymorphic: C.opAdd is able to work with classes, derived from C, while corresponding C++ code is unable to do so.
It is really true?
Feb 09 2009
parent reply Kagamin <spam here.lot> writes:
Weed Wrote:

 Well, D class code here is not equivalent to C++ class code. D code has more
features, namely, it's polymorphic: C.opAdd is able to work with classes,
derived from C, while corresponding C++ code is unable to do so.
It is really true?
Of course.
 There opAdd is only for demonstration.
If your example has nothing in common with real-world tasks and needs, it's useless.
Feb 09 2009
parent reply Weed <resume755 mail.ru> writes:
Kagamin :
 Weed Wrote:
 
 Well, D class code here is not equivalent to C++ class code. D code has more
features, namely, it's polymorphic: C.opAdd is able to work with classes,
derived from C, while corresponding C++ code is unable to do so.
It is really true?
Of course.
But I do not understand in what here problem. In C++ is impossible to do overloading with "virtual" keyword? Probably I badly know C ++, sorry.
Feb 09 2009
parent reply Kagamin <spam here.lot> writes:
Weed Wrote:

 Well, D class code here is not equivalent to C++ class code. D code has more
features, namely, it's polymorphic: C.opAdd is able to work with classes,
derived from C, while corresponding C++ code is unable to do so.
But I do not understand in what here problem. In C++ is impossible to do overloading with "virtual" keyword? Probably I badly know C ++, sorry.
In C++ you can't pass object derived from C to opAdd method. In D you can.
Feb 09 2009
parent Weed <resume755 mail.ru> writes:
Kagamin :
 Weed Wrote:
 
 Well, D class code here is not equivalent to C++ class code. D code has more
features, namely, it's polymorphic: C.opAdd is able to work with classes,
derived from C, while corresponding C++ code is unable to do so.
But I do not understand in what here problem. In C++ is impossible to do overloading with "virtual" keyword? Probably I badly know C ++, sorry.
In C++ you can't pass object derived from C to opAdd method. In D you can.
I am do not agree with you: // C++: class C { public: virtual void doSomething( C src ) {} }; class C2 : public C { }; int main( int argc, char* argv[] ) { C c; C2 c2; c.doSomething( c2 ); return 0; }
Feb 09 2009
prev sibling parent bearophile <bearophileHUGS lycos.com> writes:
Kagamin:

Well, D class code here is not equivalent to C++ class code. D code has more
features, namely, it's polymorphic: C.opAdd is able to work with classes,
derived from C, while corresponding C++ code is unable to do so. If you can't
use polymorphism, why do you use classes?<
I'd like to create a more apples-to-apples comparison, so if you have suggestions regarding how to improve the code I am willing to fix things and redo the timings. Maybe adding a 'virtual' to the C++ method? I too have done some benchmarks, see timings, notes and code here: http://leonardo-m.livejournal.com/76547.html Bye, bearophile
Feb 09 2009
prev sibling next sibling parent reply Kagamin <spam here.lot> writes:
Weed Wrote:

 Well, D class code here is not equivalent to C++ class code. D code has more
features, namely, it's polymorphic: C.opAdd is able to work with classes,
derived from C, while corresponding C++ code is unable to do so.
In C++ you can't pass object derived from C to opAdd method. In D you can.
I am do not agree with you: // C++: class C { public: virtual void doSomething( C src ) {} }; class C2 : public C { }; int main( int argc, char* argv[] ) { C c; C2 c2; c.doSomething( c2 ); return 0; }
Well, you can pass descendant objects :) I was surprised by this destructive feature. But code is still not polymorphic. Consider the following code: class C { public: virtual char* doSomething( C src ) { return src.Method(); } virtual char* Method() { return "It's C."; } }; class C2 : public C { public: virtual char* Method() { return "It's C2."; } }; int main(void) { C c; C2 c2; printf("%s\n",c.doSomething(c)); printf("%s\n",c.doSomething(c2)); return 0; } What do you think is its output?
Feb 10 2009
parent Michel Fortin <michel.fortin michelf.com> writes:
On 2009-02-10 08:02:31 -0500, Kagamin <spam here.lot> said:

 Well, you can pass descendant objects :) I was surprised by this 
 destructive feature. But code is still not polymorphic. Consider the 
 following code:
 
 class C
 {
     public:
         virtual char* doSomething( C src )
 		{
 			return src.Method();
 		}
         virtual char* Method()
 		{
 			return "It's C.";
 		}
 };
 
 class C2 : public C
 {
     public:
         virtual char* Method()
 		{
 			return "It's C2.";
 		}
 };
 
 int main(void)
 {
     C c;
     C2 c2;
     printf("%s\n",c.doSomething(c));
     printf("%s\n",c.doSomething(c2));
     return 0;
 }
 
 What do you think is its output?
Since you're passing c2 as a C by value to doSomething, slicing do occur and it prints "It's C." two times. That's why in C++ we generally pass objects by reference. Unfortunately, you often can't do that for return values.. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Feb 10 2009
prev sibling next sibling parent reply Weed <resume755 mail.ru> writes:
What is the result of the discussion?

Will the language change? Not once, could in 6-12 months?..

For me, the answer to that question was tantamount to answering the
question "whether or not to use D for new projects?"


Weed :
 (Has started here:
 http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=81359)
 
 To me still does not give rest performance of classes (in comparison
 with C++ or with D structs)
 
 I still think that it is a serious problem.
 
 Colleagues from our national D forum have asked to show it and I have
 written simple examples on D. I want to share with you too them.
 
 On my computer the code with structure (i.e. object by value) runs in 6
 times faster than a code with a class:
 
 $ time ./struct
 
 real    0m8.515s
 user    0m7.796s
 sys     0m0.016s
 $ time ./class
 
 real    0m52.185s
 user    0m40.543s
 sys     0m0.076s
[...]
Feb 19 2009
parent reply Kagamin <spam here.lot> writes:
Weed Wrote:

 Will the language change?
Hmm... You already has Walter's answer. He's the boss.
Feb 19 2009
parent reply Weed <resume755 mail.ru> writes:
Kagamin :
 Weed Wrote:
 
 Will the language change?
Hmm... You already has Walter's answer. He's the boss.
I want a more specific answer (yes or no) if possible...
Feb 19 2009
parent reply Christopher Wright <dhasenan gmail.com> writes:
Weed wrote:
 Kagamin :
 Weed Wrote:

 Will the language change?
Hmm... You already has Walter's answer. He's the boss.
I want a more specific answer (yes or no) if possible...
It will not. If you come up with some really awesome use case, then it could, but nobody has yet, and the issue comes up every few months.
Feb 19 2009
parent reply Weed <resume755 mail.ru> writes:
Christopher Wright :
 Weed wrote:
 Kagamin :
 Weed Wrote:

 Will the language change?
Hmm... You already has Walter's answer. He's the boss.
I want a more specific answer (yes or no) if possible...
It will not. If you come up with some really awesome use case, then it could, but nobody has yet, and the issue comes up every few months.
Good (I think) use cases have been in this thread
Feb 20 2009
parent reply Don <nospam nospam.com> writes:
Weed wrote:
 Christopher Wright :
 Weed wrote:
 Kagamin :
 Weed Wrote:

 Will the language change?
Hmm... You already has Walter's answer. He's the boss.
I want a more specific answer (yes or no) if possible...
It will not. If you come up with some really awesome use case, then it could, but nobody has yet, and the issue comes up every few months.
Good (I think) use cases have been in this thread
They have not. The examples have been incomplete. You've provided use cases involving classes, but haven't given _any_ details about the contents of those classes. It's possible that you have indeed found use cases, but you haven't actually shown them here.
Feb 20 2009
parent reply Weed <resume755 mail.ru> writes:
Don :
 Weed wrote:
 Christopher Wright :
 Weed wrote:
 Kagamin :
 Weed Wrote:

 Will the language change?
Hmm... You already has Walter's answer. He's the boss.
I want a more specific answer (yes or no) if possible...
It will not. If you come up with some really awesome use case, then it could, but nobody has yet, and the issue comes up every few months.
Good (I think) use cases have been in this thread
They have not. The examples have been incomplete. You've provided use cases involving classes, but haven't given _any_ details about the contents of those classes. It's possible that you have indeed found use cases, but you haven't actually shown them here.
I do not understand the claims. For example, any class that implements the mathematical object (matrix, vector, number, etc.) is suitable for example. I think it is obvious. Yes, the discussion in this thread showed that almost always possible for each case to find a different approach, using additives and other scary code. But what if these "perversions" flaw somewhere in the idea of a "reference-only" type? I understand people who are against the changes of language, as they would at least explore these changes. I myself belong to those people, I do not like changes associated with cosmetic amenities, breaking the old-established solution for years. which is not familiar with the semantics of the class value. But just such a case, when the inertia hinders the development of language and prevents them winning at least a substantial number of positions. (Namely: the replacement of old C++. Yes, I believe, without C++ replacement functionality D will not be needed.) I think the problem is real and requires action. Not sure it will be a value semantic. Maybe we come up with something entirely new? I do not know. But the problem is that one must at least acknowledge it and not come off the common phrases that "your use cases are not serious" etc.
Feb 20 2009
parent reply Don <nospam nospam.com> writes:
Weed wrote:
 Don :
 Weed wrote:
 Christopher Wright :
 Weed wrote:
 Kagamin :
 Weed Wrote:

 Will the language change?
Hmm... You already has Walter's answer. He's the boss.
I want a more specific answer (yes or no) if possible...
It will not. If you come up with some really awesome use case, then it could, but nobody has yet, and the issue comes up every few months.
Good (I think) use cases have been in this thread
They have not. The examples have been incomplete. You've provided use cases involving classes, but haven't given _any_ details about the contents of those classes. It's possible that you have indeed found use cases, but you haven't actually shown them here.
I do not understand the claims. For example, any class that implements the mathematical object (matrix, vector, number, etc.) is suitable for example. I think it is obvious.
Absolutely not! Those cases involve no polymorphism! No virtual function calls.
 Yes, the discussion in this thread showed that almost always possible
 for each case to find a different approach, using additives and other
 scary code. But what if these "perversions" flaw somewhere in the idea
 of a "reference-only" type?
 
 I understand people who are against the changes of language, as they
 would at least explore these changes. I myself belong to those people, I
 do not like changes associated with cosmetic amenities, breaking the
 old-established solution for years.
I don't think the resistance comes from intertia and committment to the "long-established solution". There's plenty of C++ programmers here (including myself).

 which is not familiar with the semantics of the class value.
 
 But just such a case, when the inertia hinders the development of
 language and prevents them winning at least a substantial number of
 positions. (Namely: the replacement of old C++. Yes, I believe, without
 C++ replacement functionality D will not be needed.)
 I think the problem is real and requires action. Not sure it will be a
 value semantic. Maybe we come up with something entirely new? I do not know.
 
 But the problem is that one must at least acknowledge it and not come
 off the common phrases that "your use cases are not serious" etc.
You really MUST start from a solid use case. I'm genuinely surprised that you've had so much trouble coming up with one; it suggests to me that you're not looking at the right problem.
Feb 20 2009
parent reply Weed <resume755 mail.ru> writes:
Don :
 Weed wrote:
 Don :
 Weed wrote:
 Christopher Wright :
 Weed wrote:
 Kagamin :
 Weed Wrote:

 Will the language change?
Hmm... You already has Walter's answer. He's the boss.
I want a more specific answer (yes or no) if possible...
It will not. If you come up with some really awesome use case, then it could, but nobody has yet, and the issue comes up every few months.
Good (I think) use cases have been in this thread
They have not. The examples have been incomplete. You've provided use cases involving classes, but haven't given _any_ details about the contents of those classes. It's possible that you have indeed found use cases, but you haven't actually shown them here.
I do not understand the claims. For example, any class that implements the mathematical object (matrix, vector, number, etc.) is suitable for example. I think it is obvious.
Absolutely not! Those cases involve no polymorphism! No virtual function calls.
I do not understand why. They are not principally to demonstrate the problem, but certainly should be able to use them. It is possible that in the real code these opportunities are not used, but tomorrow they may need it, and a day after we again decide to remove them. This should not affect the syntax or the choice between the structures+mixins and classes, and so on!
 
 Yes, the discussion in this thread showed that almost always possible
 for each case to find a different approach, using additives and other
 scary code. But what if these "perversions" flaw somewhere in the idea
 of a "reference-only" type?

 I understand people who are against the changes of language, as they
 would at least explore these changes. I myself belong to those people, I
 do not like changes associated with cosmetic amenities, breaking the
 old-established solution for years.
I don't think the resistance comes from intertia and committment to the "long-established solution". There's plenty of C++ programmers here (including myself).
All your opinion. I proceed from the assumption that the programmer should be lazy. :) This positively affects the quality of the code and its reuse
 

 which is not familiar with the semantics of the class value.

 But just such a case, when the inertia hinders the development of
 language and prevents them winning at least a substantial number of
 positions. (Namely: the replacement of old C++. Yes, I believe, without
 C++ replacement functionality D will not be needed.)
 I think the problem is real and requires action. Not sure it will be a
 value semantic. Maybe we come up with something entirely new? I do not
 know.

 But the problem is that one must at least acknowledge it and not come
 off the common phrases that "your use cases are not serious" etc.
You really MUST start from a solid use case. I'm genuinely surprised that you've had so much trouble coming up with one; it suggests to me that you're not looking at the right problem.
I design a future project. I can not spend time on his coding in advance knowing that the problem about which we speak will not allow me to achieve the desired properties of the finished product. Thus, one can expect from me detailed use cases from real life. Yes, probably each issue I will be able to circumvent by using tricks, repeatedly described here. But at what cost? There will be an unjustified waste of time, the developer and a serious increase of complexity of the program (compared to C++)
Feb 20 2009
parent Don <nospam nospam.com> writes:
Weed wrote:
 Don :
 Weed wrote:
 Don :
 Weed wrote:
 Christopher Wright :
 Weed wrote:
 Kagamin :
 Weed Wrote:

 Will the language change?
Hmm... You already has Walter's answer. He's the boss.
I want a more specific answer (yes or no) if possible...
It will not. If you come up with some really awesome use case, then it could, but nobody has yet, and the issue comes up every few months.
Good (I think) use cases have been in this thread
They have not. The examples have been incomplete. You've provided use cases involving classes, but haven't given _any_ details about the contents of those classes. It's possible that you have indeed found use cases, but you haven't actually shown them here.
I do not understand the claims. For example, any class that implements the mathematical object (matrix, vector, number, etc.) is suitable for example. I think it is obvious.
Absolutely not! Those cases involve no polymorphism! No virtual function calls.
I do not understand why. They are not principally to demonstrate the problem, but certainly should be able to use them.
AFAIK, OO linear algebra libraries have never been successful. Lots of people have tried.
 It is possible that in the real code these opportunities are not used,
 but tomorrow they may need it, and a day after we again decide to remove
 them.
 
 This should not affect the syntax or the choice between the
 structures+mixins and classes, and so on!
 
 
 Yes, the discussion in this thread showed that almost always possible
 for each case to find a different approach, using additives and other
 scary code. But what if these "perversions" flaw somewhere in the idea
 of a "reference-only" type?

 I understand people who are against the changes of language, as they
 would at least explore these changes. I myself belong to those people, I
 do not like changes associated with cosmetic amenities, breaking the
 old-established solution for years.
I don't think the resistance comes from intertia and committment to the "long-established solution". There's plenty of C++ programmers here (including myself).
All your opinion. I proceed from the assumption that the programmer should be lazy. :) This positively affects the quality of the code and its reuse

 which is not familiar with the semantics of the class value.

 But just such a case, when the inertia hinders the development of
 language and prevents them winning at least a substantial number of
 positions. (Namely: the replacement of old C++. Yes, I believe, without
 C++ replacement functionality D will not be needed.)
 I think the problem is real and requires action. Not sure it will be a
 value semantic. Maybe we come up with something entirely new? I do not
 know.

 But the problem is that one must at least acknowledge it and not come
 off the common phrases that "your use cases are not serious" etc.
You really MUST start from a solid use case. I'm genuinely surprised that you've had so much trouble coming up with one; it suggests to me that you're not looking at the right problem.
I design a future project. I can not spend time on his coding in advance knowing that the problem about which we speak will not allow me to achieve the desired properties of the finished product. Thus, one can expect from me detailed use cases from real life. Yes, probably each issue I will be able to circumvent by using tricks, repeatedly described here. But at what cost? There will be an unjustified waste of time, the developer and a serious increase of complexity of the program (compared to C++)
You are asking for the language to be massively changed, but are not giving any examples of where it is actually required. You're just providing rhetoric that it is necessary. Up to now, it reminds me of the Weapons of Mass Destruction in Iraq. You're telling us they're there, but without any evidence. Give a use case!
Feb 21 2009
prev sibling next sibling parent reply Kagamin <spam here.lot> writes:
Weed Wrote:

 Good (I think) use cases have been in this thread
They may be good, but they don't show what can be done in C++ and can't be done in D. You were advised to use structs for value semantic.
Feb 20 2009
parent reply Bill Baxter <wbaxter gmail.com> writes:
2009/2/21 Weed <resume755 mail.ru>:
 Kagamin =D0=C9=DB=C5=D4:
 Weed Wrote:

 Good (I think) use cases have been in this thread
They may be good, but they don't show what can be done in C++ and can't =
be done in D. You were advised to use structs for value semantic.
 We are beginning to repeat itself. Okay. :)

 On D you may write anything. Even without cycles! With only "if" and
 "goto" keywords. The question of the costs of such a code.  :)

 An example is unnecessarily complex code here:
 http://www.dsource.org/projects/openmeshd/browser/trunk/LinAlg/linalg/Mat=
rixT.d
 See line 227, template MultReturnType(ArgT) {

 This template is necessary to receive by value a structures containing
 the vectors and matrices as mathematical operations results. Receiving
 the vectors and matrices by value in structures needed to increase
 performance.
 Try to add here another 3 or 4 types of the returned object to this
 template?
I think I answered this already, but here goes again: 1) D2 has auto return type deduction, so this whole template probably isn't necessary in D2, you just use typeof(return) instead, IIRC. 2) A better way to manage the case where you are concerned about supporting any kind of user type is to have the caller supply a "traits" template that describes how the type implements the underlying concept, how to access an element in a generic way, etc. I didn't do that in the above code because A) I hadn't figured that out yet, and B) I moved on to the next thing once I had something working, and the above was doing what I needed it to do.
 In C++ vector, matrix, and all other possible objects would have been
 the class derived from common base class and this problem does not occur.
I'm sure if you look you can also find many C++ matrix classes that are not written that way. Probably fewer are written the way you suggest, actually. But as always you're plenty vague about what you mean here. Do you mean the mult function would return a generic Matrix type? That function does a by-value return. You'd have slicing if you did that with polymorphic classes. Actually from what I've seen, most C++ matrix libraries that support generic types do so by heavy use of argument-dependent lookup (ADL) aka Koenig lookup. Basically you just define your own mult<MyType> specialization in your own header (or maybe you use the generic mult template, but have a specialization GetElement<MyType> in your own header. There are various ways to do it). The way C++ works, these will get used by the generic template if they are the best match. D doesn't have ADL, and I griped about it for a while because it makes porting those kinds of C++ code difficult. But in the end I think that style of programming leads to maintenance headaches. You see GetElement being called in some module you're reading and you want to see its definition -- it could be anywhere! With the D/traits approach I mentioned above such code must be injected explicitly into the template via a parameter of some kind, which gives the maintenance programmer a little bit better chance of finding where it comes from. It may not be so much better, but anyway it seems to allow you to do the same kinds of things you could do with ADL. If you want to go the polymorphic route with D you can. As I think has been pointed out plenty. Why don't you just show us the class in the way you would like to write it in C++, and we'll show you how to write it in D, or finally agree with you that it's not possible. But as long as you continue to be hand-wavy about "common base classes" we're at a bit of an impasse. So far everyone thinks D can do what you want it to do based on your vague descriptions. --bb
Feb 20 2009
parent reply Weed <resume755 mail.ru> writes:
Bill Baxter :

 Why don't you just show us the class in the way you would like to
 write it in C++, and we'll show you how to write it in D, or finally
 agree with you that it's not possible.   But as long as you continue
 to be hand-wavy about "common base classes" we're at a bit of an
 impasse.  So far everyone thinks D can do what you want it to do based
 on your vague descriptions.
Yes, it's a good idea
Feb 21 2009
parent reply Weed <resume755 mail.ru> writes:
Weed :
 Bill Baxter :
 
 Why don't you just show us the class in the way you would like to
 write it in C++, and we'll show you how to write it in D, or finally
 agree with you that it's not possible.   But as long as you continue
 to be hand-wavy about "common base classes" we're at a bit of an
 impasse.  So far everyone thinks D can do what you want it to do based
 on your vague descriptions.
As I said, you can write everything using "goto" and "if". ...But why you do not like the original example of this thread?
 Yes, it's a good idea
Feb 21 2009
parent reply Bill Baxter <wbaxter gmail.com> writes:
2009/2/21 Weed <resume755 mail.ru>:
 Weed =D0=C9=DB=C5=D4:
 Bill Baxter =D0=C9=DB=C5=D4:

 Why don't you just show us the class in the way you would like to
 write it in C++, and we'll show you how to write it in D, or finally
 agree with you that it's not possible.   But as long as you continue
 to be hand-wavy about "common base classes" we're at a bit of an
 impasse.  So far everyone thinks D can do what you want it to do based
 on your vague descriptions.
As I said, you can write everything using "goto" and "if". ...But why you do not like the original example of this thread?
Please post again. I don't seem to recall any detailed example. --bb
Feb 21 2009
parent reply Weed <resume755 mail.ru> writes:
Bill Baxter :
 2009/2/21 Weed <resume755 mail.ru>:
 Weed :
 Bill Baxter :

 Why don't you just show us the class in the way you would like to
 write it in C++, and we'll show you how to write it in D, or finally
 agree with you that it's not possible.   But as long as you continue
 to be hand-wavy about "common base classes" we're at a bit of an
 impasse.  So far everyone thinks D can do what you want it to do based
 on your vague descriptions.
As I said, you can write everything using "goto" and "if". ...But why you do not like the original example of this thread?
Please post again. I don't seem to recall any detailed example. --bb
http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=83506
Feb 21 2009
parent reply Bill Baxter <wbaxter gmail.com> writes:
On Sun, Feb 22, 2009 at 1:02 AM, Weed <resume755 mail.ru> wrote:
 Bill Baxter =D0=C9=DB=C5=D4:
 2009/2/21 Weed <resume755 mail.ru>:
 Weed =D0=C9=DB=C5=D4:
 Bill Baxter =D0=C9=DB=C5=D4:

 Why don't you just show us the class in the way you would like to
 write it in C++, and we'll show you how to write it in D, or finally
 agree with you that it's not possible.   But as long as you continue
 to be hand-wavy about "common base classes" we're at a bit of an
 impasse.  So far everyone thinks D can do what you want it to do base=
d
 on your vague descriptions.
As I said, you can write everything using "goto" and "if". ...But why you do not like the original example of this thread?
Please post again. I don't seem to recall any detailed example. --bb
http://www.digitalmars.com/pnews/read.php?server=3Dnews.digitalmars.com&g=
roup=3Ddigitalmars.D&artnum=3D83506 You should use a struct there! Your code does not show you doing anything that would even remotely suggest using a class is worthwhile. You're doing value operations on value types. That's what structs are for. --bb
Feb 21 2009
next sibling parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Sat, 21 Feb 2009 21:49:46 +0300, Bill Baxter <wbaxter gmail.com> wrote:

 On Sun, Feb 22, 2009 at 1:02 AM, Weed <resume755 mail.ru> wrote:
 Bill Baxter пишет:
 2009/2/21 Weed <resume755 mail.ru>:
 Weed пишет:
 Bill Baxter пишет:

 Why don't you just show us the class in the way you would like to
 write it in C++, and we'll show you how to write it in D, or finally
 agree with you that it's not possible.   But as long as you continue
 to be hand-wavy about "common base classes" we're at a bit of an
 impasse.  So far everyone thinks D can do what you want it to do  
 based
 on your vague descriptions.
As I said, you can write everything using "goto" and "if". ...But why you do not like the original example of this thread?
Please post again. I don't seem to recall any detailed example. --bb
http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=83506
You should use a struct there! Your code does not show you doing anything that would even remotely suggest using a class is worthwhile. You're doing value operations on value types. That's what structs are for. --bb
That's what *everyone* tells him!
Feb 21 2009
parent reply Bill Baxter <wbaxter gmail.com> writes:
On Sun, Feb 22, 2009 at 5:10 AM, Denis Koroskin <2korden gmail.com> wrote:
 On Sat, 21 Feb 2009 21:49:46 +0300, Bill Baxter <wbaxter gmail.com> wrote=
:
 On Sun, Feb 22, 2009 at 1:02 AM, Weed <resume755 mail.ru> wrote:
 Bill Baxter =D0=C9=DB=C5=D4:
 2009/2/21 Weed <resume755 mail.ru>:
 Weed =D0=C9=DB=C5=D4:
 Bill Baxter =D0=C9=DB=C5=D4:

 Why don't you just show us the class in the way you would like to
 write it in C++, and we'll show you how to write it in D, or finall=
y
 agree with you that it's not possible.   But as long as you continu=
e
 to be hand-wavy about "common base classes" we're at a bit of an
 impasse.  So far everyone thinks D can do what you want it to do
 based
 on your vague descriptions.
As I said, you can write everything using "goto" and "if". ...But why you do not like the original example of this thread?
Please post again. I don't seem to recall any detailed example. --bb
http://www.digitalmars.com/pnews/read.php?server=3Dnews.digitalmars.com=
&group=3Ddigitalmars.D&artnum=3D83506
 You should use a struct there!   Your code does not show you doing
 anything that would even remotely suggest using a class is worthwhile.
  You're doing value operations on value types.  That's what structs
 are for.

 --bb
That's what *everyone* tells him!
I am vaguely open to the possibility that he has a point. FLENS uses inheritance, for instance. But I don't recall what the intent of that inheritance was in FLENS, exactly. I more or less ported it to D without that, though, so I guess I didn't find it to be essential. See this: http://flens.cvs.sourceforge.net/viewvc/flens/FLENS/matvec/densevector.h?= revision=3D1.36&view=3Dmarkup Versus this: http://www.dsource.org/projects/multiarray/browser/trunk/multiarray/dflat= /DenseVector.d Weed, if you want to make a real argument, that would be a good place to start. Investigate why and how FLENS uses inheritance. --bb
Feb 21 2009
parent Yigal Chripun <yigal100 gmail.com> writes:
Bill Baxter wrote:
 On Sun, Feb 22, 2009 at 5:10 AM, Denis Koroskin<2korden gmail.com>  wrote:
 On Sat, 21 Feb 2009 21:49:46 +0300, Bill Baxter<wbaxter gmail.com>  wrote:

 On Sun, Feb 22, 2009 at 1:02 AM, Weed<resume755 mail.ru>  wrote:
 Bill Baxter :
 2009/2/21 Weed<resume755 mail.ru>:
 Weed :
 Bill Baxter :

 Why don't you just show us the class in the way you would like to
 write it in C++, and we'll show you how to write it in D, or finally
 agree with you that it's not possible.   But as long as you continue
 to be hand-wavy about "common base classes" we're at a bit of an
 impasse.  So far everyone thinks D can do what you want it to do
 based
 on your vague descriptions.
As I said, you can write everything using "goto" and "if". ...But why you do not like the original example of this thread?
Please post again. I don't seem to recall any detailed example. --bb
http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=83506
You should use a struct there! Your code does not show you doing anything that would even remotely suggest using a class is worthwhile. You're doing value operations on value types. That's what structs are for. --bb
That's what *everyone* tells him!
I am vaguely open to the possibility that he has a point. FLENS uses inheritance, for instance. But I don't recall what the intent of that inheritance was in FLENS, exactly. I more or less ported it to D without that, though, so I guess I didn't find it to be essential. See this: http://flens.cvs.sourceforge.net/viewvc/flens/FLENS/matvec/densevector.h?revision=1.36&view=markup Versus this: http://www.dsource.org/projects/multiarray/browser/trunk/multiarray/dflat/DenseVector.d Weed, if you want to make a real argument, that would be a good place to start. Investigate why and how FLENS uses inheritance. --bb
From a quick look at the flens DenseVector class: it inherits from a Vector Interface which only declares the destructor as virtual. My educated guess is that this interface has a similar purpose to the "struct interfaces" feature discussed here before - similar to C++ concepts. I don't see any polymorphism here - the functions aren't virtual.
Feb 22 2009
prev sibling parent reply Weed <resume755 mail.ru> writes:
Bill Baxter :
 On Sun, Feb 22, 2009 at 1:02 AM, Weed <resume755 mail.ru> wrote:
 Bill Baxter :
 2009/2/21 Weed <resume755 mail.ru>:
 Weed :
 Bill Baxter :

 Why don't you just show us the class in the way you would like to
 write it in C++, and we'll show you how to write it in D, or finally
 agree with you that it's not possible.   But as long as you continue
 to be hand-wavy about "common base classes" we're at a bit of an
 impasse.  So far everyone thinks D can do what you want it to do based
 on your vague descriptions.
As I said, you can write everything using "goto" and "if". ...But why you do not like the original example of this thread?
Please post again. I don't seem to recall any detailed example. --bb
http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=83506
You should use a struct there! Your code does not show you doing anything that would even remotely suggest using a class is worthwhile. You're doing value operations on value types. That's what structs are for.
Why? What if I have not substantiated the fact that c1 is a class I should use there a structure? Used in D a model of placement classes only in heap have a rule "if you made the class and trying to pass it by value is somewhere in your code, there is a design error?
Feb 22 2009
parent reply Weed <resume755 mail.ru> writes:
Weed :
 Bill Baxter :
 On Sun, Feb 22, 2009 at 1:02 AM, Weed <resume755 mail.ru> wrote:
 Bill Baxter :
 2009/2/21 Weed <resume755 mail.ru>:
 Weed :
 Bill Baxter :

 Why don't you just show us the class in the way you would like to
 write it in C++, and we'll show you how to write it in D, or finally
 agree with you that it's not possible.   But as long as you continue
 to be hand-wavy about "common base classes" we're at a bit of an
 impasse.  So far everyone thinks D can do what you want it to do based
 on your vague descriptions.
As I said, you can write everything using "goto" and "if". ...But why you do not like the original example of this thread?
Please post again. I don't seem to recall any detailed example. --bb
http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=83506
You should use a struct there! Your code does not show you doing anything that would even remotely suggest using a class is worthwhile. You're doing value operations on value types. That's what structs are for.
Why? What if I have not substantiated the fact that c1 is a class I should use there a structure? Used in D a model of placement classes only in heap have a rule "if you made the class and trying to pass it by value is somewhere in your code, there is a design error?
Explains why the question is given in this form: I am received or wrote a classes. Is it right to overload the operator opAdd and use them? I think yes. But why not allow this operation at the same speed that allows C++?
Feb 23 2009
next sibling parent reply Don <nospam nospam.com> writes:
Weed wrote:
 Weed :
 Bill Baxter :
 On Sun, Feb 22, 2009 at 1:02 AM, Weed <resume755 mail.ru> wrote:
 Bill Baxter :
 2009/2/21 Weed <resume755 mail.ru>:
 Weed :
 Bill Baxter :

 Why don't you just show us the class in the way you would like to
 write it in C++, and we'll show you how to write it in D, or finally
 agree with you that it's not possible.   But as long as you continue
 to be hand-wavy about "common base classes" we're at a bit of an
 impasse.  So far everyone thinks D can do what you want it to do based
 on your vague descriptions.
As I said, you can write everything using "goto" and "if". ...But why you do not like the original example of this thread?
Please post again. I don't seem to recall any detailed example. --bb
http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=83506
You should use a struct there! Your code does not show you doing anything that would even remotely suggest using a class is worthwhile. You're doing value operations on value types. That's what structs are for.
Why? What if I have not substantiated the fact that c1 is a class I should use there a structure? Used in D a model of placement classes only in heap have a rule "if you made the class and trying to pass it by value is somewhere in your code, there is a design error?
Explains why the question is given in this form: I am received or wrote a classes. Is it right to overload the operator opAdd and use them? I think yes. But why not allow this operation at the same speed that allows C++?
Actually, in D, it's really difficult to give a class value semantics. If a, b are members of some class, consider (1) a = a + b; (2) a += b; It is nearly impossible to efficiently make both of these have the same effect!! You can only do it with either copy-on-write, ie, even case (2) always allocates; or by using a proxy class. This is something which I consider to be a serious problem. Much more serious than the speed issue.
Feb 23 2009
parent Weed <resume755 mail.ru> writes:
Don :
 Weed wrote:
 Weed :
 Bill Baxter :
 On Sun, Feb 22, 2009 at 1:02 AM, Weed <resume755 mail.ru> wrote:
 Bill Baxter :
 2009/2/21 Weed <resume755 mail.ru>:
 Weed :
 Bill Baxter :

 Why don't you just show us the class in the way you would like to
 write it in C++, and we'll show you how to write it in D, or
 finally
 agree with you that it's not possible.   But as long as you
 continue
 to be hand-wavy about "common base classes" we're at a bit of an
 impasse.  So far everyone thinks D can do what you want it to
 do based
 on your vague descriptions.
As I said, you can write everything using "goto" and "if". ...But why you do not like the original example of this thread?
Please post again. I don't seem to recall any detailed example. --bb
http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=83506
You should use a struct there! Your code does not show you doing anything that would even remotely suggest using a class is worthwhile. You're doing value operations on value types. That's what structs are for.
Why? What if I have not substantiated the fact that c1 is a class I should use there a structure? Used in D a model of placement classes only in heap have a rule "if you made the class and trying to pass it by value is somewhere in your code, there is a design error?
Explains why the question is given in this form: I am received or wrote a classes. Is it right to overload the operator opAdd and use them? I think yes. But why not allow this operation at the same speed that allows C++?
Actually, in D, it's really difficult to give a class value semantics. If a, b are members of some class, consider (1) a = a + b; (2) a += b; It is nearly impossible to efficiently make both of these have the same effect!! You can only do it with either copy-on-write, ie, even case (2) always allocates; or by using a proxy class. This is something which I consider to be a serious problem. Much more serious than the speed issue.
We already talked about this idea: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=81432 (see text "It is possible to think up other example where there is no overload:")
Feb 24 2009
prev sibling parent reply naryl <cy ngs.ru> writes:
Weed Wrote:

 Weed �����:
 Bill Baxter �����:
 On Sun, Feb 22, 2009 at 1:02 AM, Weed <resume755 mail.ru> wrote:
 Bill Baxter �����:
 2009/2/21 Weed <resume755 mail.ru>:
 Weed �����:
 Bill Baxter �����:

 Why don't you just show us the class in the way you would like to
 write it in C++, and we'll show you how to write it in D, or finally
 agree with you that it's not possible.   But as long as you continue
 to be hand-wavy about "common base classes" we're at a bit of an
 impasse.  So far everyone thinks D can do what you want it to do based
 on your vague descriptions.
As I said, you can write everything using "goto" and "if". ...But why you do not like the original example of this thread?
Please post again. I don't seem to recall any detailed example. --bb
http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=83506
You should use a struct there! Your code does not show you doing anything that would even remotely suggest using a class is worthwhile. You're doing value operations on value types. That's what structs are for.
Why? What if I have not substantiated the fact that c1 is a class I should use there a structure? Used in D a model of placement classes only in heap have a rule "if you made the class and trying to pass it by value is somewhere in your code, there is a design error?
Explains why the question is given in this form: I am received or wrote a classes. Is it right to overload the operator opAdd and use them? I think yes. But why not allow this operation at the same speed that allows C++?
If you pass it by value you'll lose polymorphism. That must mean that you inherit that class only to avoid duplicating code. And that is easily done with template mixins.
Feb 23 2009
parent reply Weed <resume755 mail.ru> writes:
naryl :

 --bb
http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=83506
You should use a struct there! Your code does not show you doing anything that would even remotely suggest using a class is worthwhile. You're doing value operations on value types. That's what structs are for.
Why? What if I have not substantiated the fact that c1 is a class I should use there a structure? Used in D a model of placement classes only in heap have a rule "if you made the class and trying to pass it by value is somewhere in your code, there is a design error?
Explains why the question is given in this form: I am received or wrote a classes. Is it right to overload the operator opAdd and use them? I think yes. But why not allow this operation at the same speed that allows C++?
If you pass it by value you'll lose polymorphism.
Debatable By the way, in my example the transfer class by value is not important(!), it is important to create a temporary class on the stack. Then we can pass a reference without problem (C++ allows this through the "&")
 That must mean that you inherit that class only to avoid duplicating code. And
that is easily done with template mixins.
It is possible that this polymorphism is not needed and should be prohibited for operations by value. The class is ready, why it should not be used and have to redo it? Can not think about changing when the class is ready - he could have enormous complexity and hierarchy.
Feb 23 2009
next sibling parent reply Don <nospam nospam.com> writes:
Weed wrote:
 naryl :
 
 --bb
http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=83506
You should use a struct there! Your code does not show you doing anything that would even remotely suggest using a class is worthwhile. You're doing value operations on value types. That's what structs are for.
Why? What if I have not substantiated the fact that c1 is a class I should use there a structure? Used in D a model of placement classes only in heap have a rule "if you made the class and trying to pass it by value is somewhere in your code, there is a design error?
Explains why the question is given in this form: I am received or wrote a classes. Is it right to overload the operator opAdd and use them? I think yes. But why not allow this operation at the same speed that allows C++?
If you pass it by value you'll lose polymorphism.
Debatable By the way, in my example the transfer class by value is not important(!), it is important to create a temporary class on the stack. Then we can pass a reference without problem (C++ allows this through the "&")
Sure, but you're not using polymorphism.
 
 That must mean that you inherit that class only to avoid duplicating code. And
that is easily done with template mixins.
It is possible that this polymorphism is not needed and should be prohibited for operations by value. The class is ready, why it should not be used and have to redo it? Can not think about changing when the class is ready - he could have enormous complexity and hierarchy.
This is the fundamental tradeoff at the heart of the matter. In D, the choice of whether an object will use polymorphism or not is considered a fundamental design decision. D gets significant benefits from this. C++ allows you to defer the decision, but it doesn't come for free. (Generally speaking, statically typed languages do force you to make more decisions at design time). Notice that you have little gotchas in C++, such as the need to declare a virtual destructor on every struct you think you might "someday" use polymorphically. It sticks around, even if it never gets used. One of the nice things about a D struct, compared to a C++ struct, is that you *know* it's simple, it never has that kind of baggage. D does choose different trade-offs from C++. If it was always the same, it'd be the same language! BTW, if you're concerned about performance, you'd do well to use compile-time polymorphism rather than run-time, when possible. D's metaprogramming support leaves C++ for dead.
Feb 23 2009
parent reply Weed <resume755 mail.ru> writes:
Don :
 Weed wrote:
 naryl :

 --bb
http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=83506
You should use a struct there! Your code does not show you doing anything that would even remotely suggest using a class is worthwhile. You're doing value operations on value types. That's what structs are for.
Why? What if I have not substantiated the fact that c1 is a class I should use there a structure? Used in D a model of placement classes only in heap have a rule "if you made the class and trying to pass it by value is somewhere in your code, there is a design error?
Explains why the question is given in this form: I am received or wrote a classes. Is it right to overload the operator opAdd and use them? I think yes. But why not allow this operation at the same speed that allows C++?
If you pass it by value you'll lose polymorphism.
Debatable By the way, in my example the transfer class by value is not important(!), it is important to create a temporary class on the stack. Then we can pass a reference without problem (C++ allows this through the "&")
Sure, but you're not using polymorphism.
There is no, but the same object can be used in other places, including the polymorphism
 That must mean that you inherit that class only to avoid duplicating
 code. And that is easily done with template mixins.
It is possible that this polymorphism is not needed and should be prohibited for operations by value. The class is ready, why it should not be used and have to redo it? Can not think about changing when the class is ready - he could have enormous complexity and hierarchy.
This is the fundamental tradeoff at the heart of the matter. In D, the choice of whether an object will use polymorphism or not is considered a fundamental design decision.
This is awful! Much easier to give to the application programmer to decide how it will use the derived class somewhere. Such a division should be a basic principle of designing a complex program.
 D gets significant benefits
 from this.
Benefits: 1. Disappeared slicing 2. ?
 C++ allows you to defer the decision, but it doesn't come for
 free.
Clarify what you mean?
 (Generally speaking, statically typed languages do force you to make
 more decisions at design time). Notice that you have little gotchas in
 C++, such as the need to declare a virtual destructor on every struct
 you think you might "someday" use polymorphically. It sticks around,
 even if it never gets used.
 One of the nice things about a D struct, compared to a C++ struct, is
 that you *know* it's simple, it never has that kind of baggage.
 
 D does choose different trade-offs from C++. If it was always the same,
 it'd be the same language!
There is no need to compare the structs from C++ and D. In fact, in C++ classes and structures are the same. I like D's idea of POD structs + without them you can not ensure compatibility with C, but it is very important. Now we are talking about classes. In C++ classes with the same problems, such as what they do not have a common base class (Object in D). Passing classes by value is not a problem - is an advantage. As I said earlier, the presence of pointers is also an advantage, although they are dangerous and can lead to complex bugs.
 
 BTW, if you're concerned about performance, you'd do well to use
 compile-time polymorphism rather than run-time, when possible. D's
 metaprogramming support leaves C++ for dead.
 
I think if there was a language with all the features as in D but with the model objects from C++, he would have won great popularity. Mainly it would have moved C++ developers who are satisfied with the model classes of C++ but not satisfied with the absence of other modern features: metaprogramming, contracts, delegates, closures etc.
Feb 24 2009
parent reply Don <nospam nospam.com> writes:
Weed wrote:
 Don :
 Weed wrote:
 naryl :

 --bb
http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=83506
You should use a struct there! Your code does not show you doing anything that would even remotely suggest using a class is worthwhile. You're doing value operations on value types. That's what structs are for.
Why? What if I have not substantiated the fact that c1 is a class I should use there a structure? Used in D a model of placement classes only in heap have a rule "if you made the class and trying to pass it by value is somewhere in your code, there is a design error?
Explains why the question is given in this form: I am received or wrote a classes. Is it right to overload the operator opAdd and use them? I think yes. But why not allow this operation at the same speed that allows C++?
If you pass it by value you'll lose polymorphism.
Debatable By the way, in my example the transfer class by value is not important(!), it is important to create a temporary class on the stack. Then we can pass a reference without problem (C++ allows this through the "&")
Sure, but you're not using polymorphism.
There is no, but the same object can be used in other places, including the polymorphism
 That must mean that you inherit that class only to avoid duplicating
 code. And that is easily done with template mixins.
It is possible that this polymorphism is not needed and should be prohibited for operations by value. The class is ready, why it should not be used and have to redo it? Can not think about changing when the class is ready - he could have enormous complexity and hierarchy.
This is the fundamental tradeoff at the heart of the matter. In D, the choice of whether an object will use polymorphism or not is considered a fundamental design decision.
This is awful! Much easier to give to the application programmer to decide how it will use the derived class somewhere. Such a division should be a basic principle of designing a complex program.
Even in C++, all of your base classes should be abstract. If you want to move between polymorphism and non-polymorphism in C++, it's a non-trivial refactoring.
 D gets significant benefits
 from this.
Benefits: 1. Disappeared slicing 2. ?
That's not what I had in mind at all. I don't think slicing is such a big deal in itself; it's just a symptom.
 C++ allows you to defer the decision, but it doesn't come for
 free.
Clarify what you mean?
 (Generally speaking, statically typed languages do force you to make
 more decisions at design time). Notice that you have little gotchas in
 C++, such as the need to declare a virtual destructor on every struct
 you think you might "someday" use polymorphically. It sticks around,
 even if it never gets used.
 One of the nice things about a D struct, compared to a C++ struct, is
 that you *know* it's simple, it never has that kind of baggage.

 D does choose different trade-offs from C++. If it was always the same,
 it'd be the same language!
There is no need to compare the structs from C++ and D. In fact, in C++ classes and structures are the same.
Well, although the keywords are identical, there are two different varieties of C++ objects muddied together: PODs, and polymorphic types. You declare a type to be polymorphic by declaring a virtual function inside it. In D, you do it with the 'class' keyword.
 I like D's idea of POD structs + without them you can not ensure
 compatibility with C, but it is very important.
 
 Now we are talking about classes.
 
 In C++ classes with the same problems, such as what they do not have a
 common base class (Object in D). Passing classes by value is not a
 problem - is an advantage.
Passing a polymorphic class by value rarely makes sense. You can't get (runtime) polymorphism unless you go through a pointer.
 As I said earlier, the presence of pointers is also an advantage,
 although they are dangerous and can lead to complex bugs.
I don't think that is analagous. The issue is not primarily about with the 'danger' of passing classes by value. It's about clear separation of concepts.
 BTW, if you're concerned about performance, you'd do well to use
 compile-time polymorphism rather than run-time, when possible. D's
 metaprogramming support leaves C++ for dead.
I think if there was a language with all the features as in D but with the model objects from C++, he would have won great popularity. Mainly it would have moved C++ developers who are satisfied with the model classes of C++ but not satisfied with the absence of other modern features: metaprogramming, contracts, delegates, closures etc.
I think D will get adequate popularity once it has a good library situation. It only needs language changes inasfaras they are necessary for library design.
Feb 24 2009
parent reply Weed <resume755 mail.ru> writes:
Don :

 That must mean that you inherit that class only to avoid duplicating
 code. And that is easily done with template mixins.
It is possible that this polymorphism is not needed and should be prohibited for operations by value. The class is ready, why it should not be used and have to redo it? Can not think about changing when the class is ready - he could have enormous complexity and hierarchy.
This is the fundamental tradeoff at the heart of the matter. In D, the choice of whether an object will use polymorphism or not is considered a fundamental design decision.
This is awful! Much easier to give to the application programmer to decide how it will use the derived class somewhere. Such a division should be a basic principle of designing a complex program.
Even in C++, all of your base classes should be abstract.
Why?
 If you want to move between polymorphism and non-polymorphism in C++,
 it's a non-trivial refactoring.
 
 
 D gets significant benefits
 from this.
Benefits: 1. Disappeared slicing 2. ?
That's not what I had in mind at all. I don't think slicing is such a big deal in itself; it's just a symptom.
What do you mean?
 C++ allows you to defer the decision, but it doesn't come for
 free.
Clarify what you mean?
 (Generally speaking, statically typed languages do force you to make
 more decisions at design time). Notice that you have little gotchas in
 C++, such as the need to declare a virtual destructor on every struct
 you think you might "someday" use polymorphically. It sticks around,
 even if it never gets used.
 One of the nice things about a D struct, compared to a C++ struct, is
 that you *know* it's simple, it never has that kind of baggage.

 D does choose different trade-offs from C++. If it was always the same,
 it'd be the same language!
There is no need to compare the structs from C++ and D. In fact, in C++ classes and structures are the same.
Well, although the keywords are identical, there are two different varieties of C++ objects muddied together: PODs, and polymorphic types. You declare a type to be polymorphic by declaring a virtual function inside it. In D, you do it with the 'class' keyword.
 I like D's idea of POD structs + without them you can not ensure
 compatibility with C, but it is very important.

 Now we are talking about classes.

 In C++ classes with the same problems, such as what they do not have a
 common base class (Object in D). Passing classes by value is not a
 problem - is an advantage.
Passing a polymorphic class by value rarely makes sense. You can't get (runtime) polymorphism unless you go through a pointer.
Or reference (&). Thus, even polymorphic class on stack can be used safely in C++.
 
 As I said earlier, the presence of pointers is also an advantage,
 although they are dangerous and can lead to complex bugs.
I don't think that is analagous. The issue is not primarily about with the 'danger' of passing classes by value. It's about clear separation of concepts.
 BTW, if you're concerned about performance, you'd do well to use
 compile-time polymorphism rather than run-time, when possible. D's
 metaprogramming support leaves C++ for dead.
I think if there was a language with all the features as in D but with the model objects from C++, he would have won great popularity. Mainly it would have moved C++ developers who are satisfied with the model classes of C++ but not satisfied with the absence of other modern features: metaprogramming, contracts, delegates, closures etc.
I think D will get adequate popularity once it has a good library situation. It only needs language changes inasfaras they are necessary for library design.
Feb 24 2009
parent reply Don <nospam nospam.com> writes:
Weed wrote:
 Don :
 
 That must mean that you inherit that class only to avoid duplicating
 code. And that is easily done with template mixins.
It is possible that this polymorphism is not needed and should be prohibited for operations by value. The class is ready, why it should not be used and have to redo it? Can not think about changing when the class is ready - he could have enormous complexity and hierarchy.
This is the fundamental tradeoff at the heart of the matter. In D, the choice of whether an object will use polymorphism or not is considered a fundamental design decision.
This is awful! Much easier to give to the application programmer to decide how it will use the derived class somewhere. Such a division should be a basic principle of designing a complex program.
Even in C++, all of your base classes should be abstract.
Why?
See, for example, http://www.artima.com/intv/modern.html
 
 If you want to move between polymorphism and non-polymorphism in C++,
 it's a non-trivial refactoring.


 D gets significant benefits
 from this.
Benefits: 1. Disappeared slicing 2. ?
That's not what I had in mind at all. I don't think slicing is such a big deal in itself; it's just a symptom.
What do you mean?
Language complexity.
 
 C++ allows you to defer the decision, but it doesn't come for
 free.
Clarify what you mean?
 (Generally speaking, statically typed languages do force you to make
 more decisions at design time). Notice that you have little gotchas in
 C++, such as the need to declare a virtual destructor on every struct
 you think you might "someday" use polymorphically. It sticks around,
 even if it never gets used.
 One of the nice things about a D struct, compared to a C++ struct, is
 that you *know* it's simple, it never has that kind of baggage.

 D does choose different trade-offs from C++. If it was always the same,
 it'd be the same language!
There is no need to compare the structs from C++ and D. In fact, in C++ classes and structures are the same.
Well, although the keywords are identical, there are two different varieties of C++ objects muddied together: PODs, and polymorphic types. You declare a type to be polymorphic by declaring a virtual function inside it. In D, you do it with the 'class' keyword.
 I like D's idea of POD structs + without them you can not ensure
 compatibility with C, but it is very important.

 Now we are talking about classes.

 In C++ classes with the same problems, such as what they do not have a
 common base class (Object in D). Passing classes by value is not a
 problem - is an advantage.
Passing a polymorphic class by value rarely makes sense. You can't get (runtime) polymorphism unless you go through a pointer.
Or reference (&). Thus, even polymorphic class on stack can be used safely in C++.
Same thing. You're either not using value semantics, or not using polymorphism. Not both at once.
 
 As I said earlier, the presence of pointers is also an advantage,
 although they are dangerous and can lead to complex bugs.
I don't think that is analagous. The issue is not primarily about with the 'danger' of passing classes by value. It's about clear separation of concepts.
 BTW, if you're concerned about performance, you'd do well to use
 compile-time polymorphism rather than run-time, when possible. D's
 metaprogramming support leaves C++ for dead.
I think if there was a language with all the features as in D but with the model objects from C++, he would have won great popularity. Mainly it would have moved C++ developers who are satisfied with the model classes of C++ but not satisfied with the absence of other modern features: metaprogramming, contracts, delegates, closures etc.
I think D will get adequate popularity once it has a good library situation. It only needs language changes inasfaras they are necessary for library design.
I'm wasting my time here. I'll not make any further comments on this subject.
Feb 25 2009
parent reply Weed <resume755 mail.ru> writes:
Don :
 Weed wrote:
 Don :

 That must mean that you inherit that class only to avoid duplicating
 code. And that is easily done with template mixins.
It is possible that this polymorphism is not needed and should be prohibited for operations by value. The class is ready, why it should not be used and have to redo it? Can not think about changing when the class is ready - he could have enormous complexity and hierarchy.
This is the fundamental tradeoff at the heart of the matter. In D, the choice of whether an object will use polymorphism or not is considered a fundamental design decision.
This is awful! Much easier to give to the application programmer to decide how it will use the derived class somewhere. Such a division should be a basic principle of designing a complex program.
Even in C++, all of your base classes should be abstract.
Why?
See, for example, http://www.artima.com/intv/modern.html
It did not say how that all base classes should be abstract
 
 If you want to move between polymorphism and non-polymorphism in C++,
 it's a non-trivial refactoring.


 D gets significant benefits
 from this.
Benefits: 1. Disappeared slicing 2. ?
That's not what I had in mind at all. I don't think slicing is such a big deal in itself; it's just a symptom.
What do you mean?
Language complexity.
We do not schoolgirls! :) Who is afraid of the complexity should use BASIC.
 C++ allows you to defer the decision, but it doesn't come for
 free.
Clarify what you mean?
 (Generally speaking, statically typed languages do force you to make
 more decisions at design time). Notice that you have little gotchas in
 C++, such as the need to declare a virtual destructor on every struct
 you think you might "someday" use polymorphically. It sticks around,
 even if it never gets used.
 One of the nice things about a D struct, compared to a C++ struct, is
 that you *know* it's simple, it never has that kind of baggage.

 D does choose different trade-offs from C++. If it was always the
 same,
 it'd be the same language!
There is no need to compare the structs from C++ and D. In fact, in C++ classes and structures are the same.
Well, although the keywords are identical, there are two different varieties of C++ objects muddied together: PODs, and polymorphic types. You declare a type to be polymorphic by declaring a virtual function inside it. In D, you do it with the 'class' keyword.
 I like D's idea of POD structs + without them you can not ensure
 compatibility with C, but it is very important.

 Now we are talking about classes.

 In C++ classes with the same problems, such as what they do not have a
 common base class (Object in D). Passing classes by value is not a
 problem - is an advantage.
Passing a polymorphic class by value rarely makes sense. You can't get (runtime) polymorphism unless you go through a pointer.
Or reference (&). Thus, even polymorphic class on stack can be used safely in C++.
Same thing. You're either not using value semantics, or not using polymorphism. Not both at once.
If you needed polymorphism you should use references or pointers, where necessary performance you use value semantics. C++ allows both options, D - no.
 
 As I said earlier, the presence of pointers is also an advantage,
 although they are dangerous and can lead to complex bugs.
I don't think that is analagous. The issue is not primarily about with the 'danger' of passing classes by value. It's about clear separation of concepts.
 BTW, if you're concerned about performance, you'd do well to use
 compile-time polymorphism rather than run-time, when possible. D's
 metaprogramming support leaves C++ for dead.
I think if there was a language with all the features as in D but with the model objects from C++, he would have won great popularity. Mainly it would have moved C++ developers who are satisfied with the model classes of C++ but not satisfied with the absence of other modern features: metaprogramming, contracts, delegates, closures etc.
I think D will get adequate popularity once it has a good library situation. It only needs language changes inasfaras they are necessary for library design.
I'm wasting my time here. I'll not make any further comments on this subject.
Okay
Feb 25 2009
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Weed:
 We do not schoolgirls! :) Who is afraid of the complexity should use BASIC.
I like D1 mostly because it's quite less complex that C++, that's the first thing I ask to a new language like D. Complexity "kills". You probably don't want D, you want ATS: http://www.ats-lang.org/ Bye, bearophile
Feb 25 2009
next sibling parent reply Weed <resume755 mail.ru> writes:
bearophile :
 Weed:
 We do not schoolgirls! :) Who is afraid of the complexity should use BASIC.
I like D1 mostly because it's quite less complex that C++, that's the first thing I ask to a new language like D. Complexity "kills".
I am cite myself: "That is actually a model of classes D harder than C++."
 You probably don't want D, you want ATS:
 http://www.ats-lang.org/
There uses preprocessor. It is wrong.
Feb 25 2009
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Weed wrote:
 bearophile :
 Weed:
 We do not schoolgirls! :) Who is afraid of the complexity should use BASIC.
I like D1 mostly because it's quite less complex that C++, that's the first thing I ask to a new language like D. Complexity "kills".
I am cite myself: "That is actually a model of classes D harder than C++."
Man, wish I could have done that when writing my thesis...
 You probably don't want D, you want ATS:
 http://www.ats-lang.org/
There uses preprocessor. It is wrong.
Wow. I dare say you're missing the forest for the trees. -- daniel
Feb 25 2009
parent Weed <resume755 mail.ru> writes:
Daniel Keep :
 
 Weed wrote:
 bearophile :
 Weed:
 We do not schoolgirls! :) Who is afraid of the complexity should use BASIC.
I like D1 mostly because it's quite less complex that C++, that's the first thing I ask to a new language like D. Complexity "kills".
I am cite myself: "That is actually a model of classes D harder than C++."
Man, wish I could have done that when writing my thesis...
:) Sorry, this has already been discussed here: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=84842
Feb 25 2009
prev sibling parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
bearophile wrote:
 Weed:
 We do not schoolgirls! :) Who is afraid of the complexity should use BASIC.
I like D1 mostly because it's quite less complex that C++, that's the first thing I ask to a new language like D. Complexity "kills". You probably don't want D, you want ATS: http://www.ats-lang.org/ Bye, bearophile
http://www.ats-lang.org/EXAMPLE/MISC/listquicksort.dats Dear god. I think... I think I'm going to go cry in the corner... -- Daniel
Feb 25 2009
parent reply Bill Baxter <wbaxter gmail.com> writes:
On Wed, Feb 25, 2009 at 11:47 PM, Daniel Keep
<daniel.keep.lists gmail.com> wrote:
 bearophile wrote:
 Weed:
 We do not schoolgirls! :) Who is afraid of the complexity should use BA=
SIC.
 I like D1 mostly because it's quite less complex that C++, that's the fi=
rst thing I ask to a new language like D. Complexity "kills".
 You probably don't want D, you want ATS:
 http://www.ats-lang.org/

 Bye,
 bearophile
http://www.ats-lang.org/EXAMPLE/MISC/listquicksort.dats Dear god. =A0I think... I think I'm going to go cry in the corner...
Even the helpful explanatory comment is baffling. Sounds like the guy is boasting because he not only implemented Quicksort but managed to do it in such a way that the output not only has the same length as the input, but *also* is a permutation of the input! Whoa! Sheer genius! --bb
Feb 25 2009
parent Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
Bill Baxter wrote:
 On Wed, Feb 25, 2009 at 11:47 PM, Daniel Keep
 <daniel.keep.lists gmail.com> wrote:
 bearophile wrote:
 Weed:
 We do not schoolgirls! :) Who is afraid of the complexity should use BASIC.
I like D1 mostly because it's quite less complex that C++, that's the first thing I ask to a new language like D. Complexity "kills". You probably don't want D, you want ATS: http://www.ats-lang.org/ Bye, bearophile
http://www.ats-lang.org/EXAMPLE/MISC/listquicksort.dats Dear god. I think... I think I'm going to go cry in the corner...
Even the helpful explanatory comment is baffling. Sounds like the guy is boasting because he not only implemented Quicksort but managed to do it in such a way that the output not only has the same length as the input, but *also* is a permutation of the input! Whoa! Sheer genius! --bb
Is it one of those deals where he somehow explained to the compiler what he wants his algorithm to do, and then the compiler goes off and proves to itself that the algorithm actually does it or else barfs?
Feb 25 2009
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Weed wrote:
 Don пишет:
 Language complexity.
We do not schoolgirls! :)
I guess superdan might disagree here :o). Andrei
Feb 25 2009
prev sibling parent reply Kagamin <spam here.lot> writes:
Weed Wrote:

 But why not allow this operation at the same speed that allows C++?
If you pass it by value you'll lose polymorphism.
It is possible that this polymorphism is not needed and should be prohibited for operations by value. The class is ready, why it should not be used and have to redo it? Can not think about changing when the class is ready - he could have enormous complexity and hierarchy.
It's probably already designed to be reference-type. I think, you'll have big troubles trying to change its semantic to value-type and effectively you'll have to redo it.
Feb 24 2009
parent reply Christopher Wright <dhasenan gmail.com> writes:
Kagamin wrote:
 Weed Wrote:
 
 But why not allow this operation at the same speed that allows C++?
If you pass it by value you'll lose polymorphism.
It is possible that this polymorphism is not needed and should be prohibited for operations by value. The class is ready, why it should not be used and have to redo it? Can not think about changing when the class is ready - he could have enormous complexity and hierarchy.
It's probably already designed to be reference-type. I think, you'll have big troubles trying to change its semantic to value-type and effectively you'll have to redo it.
In other words, it is not always easy to translate C++ to D. It's probably not worthwhile to translate any large codebase into another programming language, in most cases, and if you do, you will probably need to rewrite large portions of it anyway.
Feb 24 2009
parent reply Weed <resume755 mail.ru> writes:
Christopher Wright :
 Kagamin wrote:
 Weed Wrote:

 But why not allow this operation at the same speed that allows C++?
If you pass it by value you'll lose polymorphism.
It is possible that this polymorphism is not needed and should be prohibited for operations by value. The class is ready, why it should not be used and have to redo it? Can not think about changing when the class is ready - he could have enormous complexity and hierarchy.
It's probably already designed to be reference-type. I think, you'll have big troubles trying to change its semantic to value-type and effectively you'll have to redo it.
In other words, it is not always easy to translate C++ to D. It's probably not worthwhile to translate any large codebase into another programming language, in most cases, and if you do, you will probably need to rewrite large portions of it anyway.
As a result, classes will be slow, or require more code to achieve speeds comparable to C++. That is actually a model of classes D harder than C++.
Feb 24 2009
parent reply Christopher Wright <dhasenan gmail.com> writes:
Weed wrote:
 As a result, classes will be slow, or require more code to achieve
 speeds comparable to C++.
 
 That is actually a model of classes D harder than C++.
Yes, C++ offers more unsafe optimizations than D.
Feb 24 2009
parent reply Weed <resume755 mail.ru> writes:
Christopher Wright :
 Weed wrote:
 As a result, classes will be slow, or require more code to achieve
 speeds comparable to C++.

 That is actually a model of classes D harder than C++.
Yes, C++ offers more unsafe optimizations than D.
Straight to the point! I am choosing unsafe but fast code. Unsafe at so much on how much is unsafe any code on C++. I think the issue is closed. :)
Feb 25 2009
parent Christopher Wright <dhasenan gmail.com> writes:
Weed wrote:
 Christopher Wright :
 Weed wrote:
 As a result, classes will be slow, or require more code to achieve
 speeds comparable to C++.

 That is actually a model of classes D harder than C++.
Yes, C++ offers more unsafe optimizations than D.
Straight to the point! I am choosing unsafe but fast code. Unsafe at so much on how much is unsafe any code on C++. I think the issue is closed. :)
I spoke poorly. C++ enshrines unsafe optimizations as essential language features. D simply provides enough metaprogramming and low-level stuff that you can do it with a library. C++ gives you a revolver pointed at your foot, and you maneuver your target between the revolver and your foot. D gives you a kit to make a gun in 5 easy steps!!! and lets you point it at your foot if you want. For instance, you can come up with templates that give you struct polymorphism. But you yourself said that that isn't a good idea, and that you should not use value types in a polymorphic manner.
Feb 25 2009
prev sibling parent reply Kagamin <spam here.lot> writes:
Daniel Keep Wrote:

 You probably don't want D, you want ATS:
 http://www.ats-lang.org/
 
 Bye,
 bearophile
http://www.ats-lang.org/EXAMPLE/MISC/listquicksort.dats Dear god. I think... I think I'm going to go cry in the corner...
Is it common for functional languages to love 1-letter identifiers, I wonder?
Feb 25 2009
parent reply Christopher Wright <dhasenan gmail.com> writes:
Kagamin wrote:
 Daniel Keep Wrote:
 
 You probably don't want D, you want ATS:
 http://www.ats-lang.org/

 Bye,
 bearophile
http://www.ats-lang.org/EXAMPLE/MISC/listquicksort.dats Dear god. I think... I think I'm going to go cry in the corner...
Is it common for functional languages to love 1-letter identifiers, I wonder?
Probably. Mathematicians use "ab" to mean "a multiplied by b", so they tend toward single-character identifiers with subscripts. And functional languages seem to cater more toward mathematicians. I tend to find most examples of the remarkable efficiency of functional languages entirely unreadable, partly because of this, and partly because they seem fond of using many operators, some in ways that I find bizarre.
Feb 25 2009
parent reply dsimcha <dsimcha yahoo.com> writes:
== Quote from Christopher Wright (dhasenan gmail.com)'s article
 Kagamin wrote:
 Daniel Keep Wrote:

 You probably don't want D, you want ATS:
 http://www.ats-lang.org/

 Bye,
 bearophile
http://www.ats-lang.org/EXAMPLE/MISC/listquicksort.dats Dear god. I think... I think I'm going to go cry in the corner...
Is it common for functional languages to love 1-letter identifiers, I wonder?
Probably. Mathematicians use "ab" to mean "a multiplied by b", so they tend toward single-character identifiers with subscripts. And functional languages seem to cater more toward mathematicians. I tend to find most examples of the remarkable efficiency of functional languages entirely unreadable, partly because of this, and partly because they seem fond of using many operators, some in ways that I find bizarre.
<Rant> True. Conversely, whenever I read something mathy, it always drives me crazy how hard it is to read something expressed in math notation that is actually quite intuitive to express in code in a sane language like D (or Python, etc). If mathematicians applied their unreadable "style" to mainstream code, they'd be shot because people would believe they were obfuscating it on purpose. Single letter variable names drive me crazy because when I read equations I constantly lose track of what the variables represent. Worse yet, when mathematicians run out of good variable names, they use Greek letters that look almost the same as English letters, just to make it easier to confuse variable names. When I do math myself, my programming side kicks in and I often find myself trying to name variables descriptively like I would if coding, rather than using one letter like a mathematician. Similarly, I find linear algebra impossible to grok largely because some genius mathematician decided to overload a bunch of operators to mean completely different things when dealing with matrices than when dealing with scalars. Heck, the multiplication operator isn't even commutative. Frankly, yes, programming/comp sci may arguably be a branch of mathematics, but if it is, programmers have invented better notation than mathematicians. The mathematicians should stay the heck out of all programming notation discussions. </Rant>
Feb 25 2009
next sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
dsimcha <dsimcha yahoo.com> wrote:

 I find linear algebra impossible to grok largely because some  
 genius
 mathematician decided to overload a bunch of operators to mean completely
 different things when dealing with matrices than when dealing with  
 scalars.  Heck, the multiplication operator isn't even commutative.
In the schools I've been to (in Norway), multiplication of scalars has always been indicated by the middle-dot operator (, U+00B7), as has componentwise multiplication of matrices. The multiplication sign (x, , U+00D7) was used for cross-product of vectors, as well as ordinary matrix multiplication. This has given me the impression (which seems to hold true in the Norwegian school system) that middle-dot is commutative, multiplication sign is not. I do however know it does not hold true in all context, which is unfortunate. -- Simen
Feb 25 2009
prev sibling next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
dsimcha wrote:
 == Quote from Christopher Wright (dhasenan gmail.com)'s article
 Kagamin wrote:
 Daniel Keep Wrote:

 You probably don't want D, you want ATS:
 http://www.ats-lang.org/

 Bye,
 bearophile
http://www.ats-lang.org/EXAMPLE/MISC/listquicksort.dats Dear god. I think... I think I'm going to go cry in the corner...
Is it common for functional languages to love 1-letter identifiers, I wonder?
Probably. Mathematicians use "ab" to mean "a multiplied by b", so they tend toward single-character identifiers with subscripts. And functional languages seem to cater more toward mathematicians. I tend to find most examples of the remarkable efficiency of functional languages entirely unreadable, partly because of this, and partly because they seem fond of using many operators, some in ways that I find bizarre.
<Rant> True. Conversely, whenever I read something mathy, it always drives me crazy how hard it is to read something expressed in math notation that is actually quite intuitive to express in code in a sane language like D (or Python, etc). If mathematicians applied their unreadable "style" to mainstream code, they'd be shot because people would believe they were obfuscating it on purpose. Single letter variable names drive me crazy because when I read equations I constantly lose track of what the variables represent. Worse yet, when mathematicians run out of good variable names, they use Greek letters that look almost the same as English letters, just to make it easier to confuse variable names. When I do math myself, my programming side kicks in and I often find myself trying to name variables descriptively like I would if coding, rather than using one letter like a mathematician. Similarly, I find linear algebra impossible to grok largely because some genius mathematician decided to overload a bunch of operators to mean completely different things when dealing with matrices than when dealing with scalars. Heck, the multiplication operator isn't even commutative. Frankly, yes, programming/comp sci may arguably be a branch of mathematics, but if it is, programmers have invented better notation than mathematicians. The mathematicians should stay the heck out of all programming notation discussions. </Rant>
You're in good company. http://www.cs.utexas.edu/~EWD/ewd13xx/EWD1300.PDF Andrei
Feb 25 2009
prev sibling parent "Joel C. Salomon" <joelcsalomon gmail.com> writes:
dsimcha wrote:
 Similarly, I find linear algebra impossible to grok largely because some genius
 mathematician decided to overload a bunch of operators to mean completely
 different things when dealing with matrices than when dealing with scalars. 
Heck,
 the multiplication operator isn't even commutative.
You’ve got W.R. Hamilton to thank for that last; he found it impossible to extend multiplication past 1- and 2-tuples (real and complex numbers) without dropping commutativity for quaternion multiplication. Give mathematicians a new toy… Another part of the trouble is that there’s a perfectly good operator for functional composition, U+2218 RING OPERATOR, i.e.: [f∘g](x) ≡ f(g(x)). Treating matrices as linear operators on vectors, you *could* write [A∘B](v), but that ignores the fact that matrix “composition” and matrix-vector “application” have the same form, so we prefer to use the same operator for both: A⁢B⁢v ≡ A*B*v. (The “⁢”, if you can see them, are U+2062 INVISIBLE TIMES.) I’m playing with Geometric Algebra now, and the problem is *much* worse. At various times, there are at least 7 different “products” defined: • A⁢B: the “geometric product”; • A⋅B: the inner product, defined in two different ways; • A^B: the outer product, related to the vector cross product; • A⨼B & A⨽B: the left- and right-contractions, two more “inner products” (sometimes denoted like A⌋B & A⌊B); and just for extra fun, • A×B: *not* the familiar cross product, but the “commutator product” A×B = ½(A⁢B−B⁢A). (Fortunately, this last is pretty rare in the literature I’ve seen.) There may also be a defined meaning for A*B, but I can’t recall its meaning. Lurking on these lists, I’ve seen requests for user-definable infix operators. This example “forms some sort of argument in that debate, but I’m not sure whether it’s for or against.” —Joel Salomon
Feb 26 2009