digitalmars.D - Old problem with performance
- Weed (63/63) Feb 07 2009 (Has started here:
- Daniel Keep (7/8) Feb 08 2009 If I had to take a guess, I'd say that it's six times slower because
- Weed (3/12) Feb 08 2009 Yes, but problem is that D does not leave way to create a class
- Weed (4/16) Feb 08 2009 I should explain that I compare not only structs and classes in D but
- Walter Bright (3/15) Feb 08 2009 You can allocate a class on the stack with:
- Frits van Bommel (4/21) Feb 08 2009 Which helps (a bit) with the two instances allocated in main(), but is
- Sean Kelly (4/26) Feb 08 2009 It's kind of a lame solution, but if the return value is const then the
- Walter Bright (9/12) Feb 08 2009 The use of classes in this example is like using a screwdriver as a
- Derek Parnell (7/11) Feb 08 2009 In D, what is the recommend technique to derive one user-defined value t...
- Walter Bright (20/30) Feb 08 2009 There isn't one. Deriving types only makes sense when expecting
- Derek Parnell (16/49) Feb 08 2009 Thank you. I was using "derive" in the English language sense rather tha...
- dsimcha (22/28) Feb 08 2009 In D2, you could try aggregation and opDot() w/ ref return. See
- Chad J (26/43) Feb 08 2009 So far I am seeing that the slicing problem arises from the ability to
- Denis Koroskin (11/19) Feb 08 2009 A mixin, perhaps:
- Andrei Alexandrescu (3/14) Feb 08 2009 Go to the future and use the alias this thingie.
- Weed (10/25) Feb 08 2009 But without such types the bulky code turns out
- Adam D. Ruppe (6/9) Feb 08 2009 scope class does just that. You can also put a custom allocator in your
- Weed (4/13) Feb 08 2009 Often you add custom allocator in the classes who uses overload? You
- Yigal Chripun (2/10) Feb 08 2009 I'm curious, What is a heffalump?
- BCS (2/4) Feb 08 2009 http://en.wikipedia.org/wiki/Heffalump
- Denis Koroskin (51/114) Feb 08 2009 Your C objects have value semantics. For value semantics you should use ...
- Weed (13/19) Feb 08 2009 At present in D is not contain support of value types for objects.
- Denis Koroskin (2/23) Feb 08 2009 I believe you should stick with structs for that.
- Weed (2/26) Feb 08 2009 Let's assume, polymorphism is necessary to these objects
- Michel Fortin (9/10) Feb 08 2009 Polymorphism doesn't work very well while passing objects by value,
- Rainer Deyke (6/8) Feb 08 2009 I have heard about the slicing problem. I know what it is. But in all
- Andrei Alexandrescu (9/16) Feb 08 2009 How long have you used C++?
- Rainer Deyke (56/63) Feb 08 2009 Slicing is caused by naive copying of polymorphic types, which is only
- Andrei Alexandrescu (5/26) Feb 08 2009 The slicing problem exists in spades in this example, or better put its
- Rainer Deyke (22/25) Feb 08 2009 You're referring to the automatically generated copy constructor in
- Christopher Wright (3/12) Feb 09 2009 It's also a problem whenever you use avatar by value. It's only by
- Andrei Alexandrescu (4/34) Feb 09 2009 So the problem exists since you are trusting the programmer to avoid it.
- Rainer Deyke (18/19) Feb 09 2009 The slicing problem exists in the sense that it is possible for a bad
- Christopher Wright (28/43) Feb 11 2009 Yes. There are many examples of this: memory leaks, array bounds errors,...
- Rainer Deyke (43/60) Feb 12 2009 struct C {
- Christopher Wright (5/19) Feb 12 2009 Okay, reference types don't have value semantics. That's exactly what I
- Rainer Deyke (21/43) Feb 12 2009 That sounds tautological, but many newcomers to D are surprised by
- Tom S (16/28) Feb 12 2009 Simply because shallow copies are the default. Usually you can't even
- Rainer Deyke (24/38) Feb 12 2009 C++ has a way of specifying how deep you want your copies to be at the
- Christopher Wright (6/10) Feb 13 2009 You can take additional steps to ensure safety with notifyRegister, if
- Tom S (8/25) Feb 12 2009 Like you can't write "typedef X* T;" in C...
- Rainer Deyke (9/19) Feb 12 2009 That's like saying object slicing is an intentional feature. Given the
- Daniel Keep (6/14) Feb 12 2009 It's not a bug. There are differences between value types and reference
- Rainer Deyke (20/23) Feb 12 2009 This is a bug:
- Andrei Alexandrescu (6/31) Feb 12 2009 C++ ctors won't do the right thing if you use pointers, which is the
- Rainer Deyke (9/13) Feb 13 2009 So where's the D equivalent of std::vector? Phobos has nothing. Tango
- Andrei Alexandrescu (5/16) Feb 13 2009 Phobos2 plans to consistently consider T[] a range, not a full-fledged
- Denis Koroskin (7/24) Feb 13 2009 Will T[] get front, back, empty properties, and popFront(), popBack()
- Andrei Alexandrescu (6/37) Feb 13 2009 I agree. Walter said let's get ranges going and then we can look into
- Yigal Chripun (19/48) Feb 13 2009 once upon a time there was a huge discussion about template syntax.
- Weed (5/12) Feb 08 2009 I am absolutely agree with you.
- Weed (3/14) Feb 08 2009 By performance loss
- Michel Fortin (33/48) Feb 09 2009 No. By forbiding the cases that leads to slicing, like returning a
- Weed (4/26) Feb 09 2009 Let's think, can there are other ways to solve problem?
- Michel Fortin (14/22) Feb 09 2009 not sure I'm getting what you mean in that post.
- Michel Fortin (14/17) Feb 09 2009 That said, I'm not against adding struct inheritance if it can be done
- Don (10/34) Feb 09 2009 The one case I could think of was the strategy pattern: no data is added...
- Denis Koroskin (2/33) Feb 09 2009
- Michel Fortin (8/16) Feb 09 2009 Indeed. But that's in C++. It could certainly be possible to make that
- Weed (5/31) Feb 09 2009 Yes
- naryl (6/6) Feb 08 2009 It's a bit offtopic but I'd be grateful if someone can explain why D wit...
- Denis Koroskin (3/12) Feb 08 2009 Well, you don't compare C++ vs D struct speed but rather C++ vs D IO.
- Denis Koroskin (2/17) Feb 08 2009 Nevermind, I didn't understand the benchmark from quick glance.
- Denis Koroskin (3/12) Feb 08 2009 I noticed that you calculate Fib(27) in fibs.cc and Fib(40) in fibs.d
- Denis Koroskin (2/17) Feb 08 2009 They both perform roughly the same when this typo is corrected.
- Andrei Alexandrescu (3/27) Feb 08 2009 It was a ploy! :o)
- naryl (7/30) Feb 08 2009 Sorry. :)
- Denis Koroskin (66/98) Feb 08 2009 Here is code, setting and result I got.
- naryl (2/8) Feb 08 2009 The only explanation I see is gcc does some optimization that dmd backen...
- grauzone (3/12) Feb 08 2009 That's a good explanation. The only positive thing about the dmd backend...
- Denis Koroskin (2/11) Feb 08 2009 Yes, that's why you can't claim D is slow because GCC outperforms DMD.
- Weed (2/8) Feb 08 2009 Try to return from value() a class instance
- Radu (20/84) Feb 08 2009 While nor so orthodox, this improves the situation a bit:
- Weed (5/31) Feb 08 2009 If the used object it is impossible to change? It is written by other
- Christopher Wright (58/63) Feb 08 2009 On my system, your struct example averaged 0.36 seconds, and your class
- Weed (10/29) Feb 08 2009 Earlier I proved that it is impossible. For example here in such express...
- Christopher Wright (20/44) Feb 08 2009 In that example, you can use structs instead of classes. Your response
- Weed (3/53) Feb 08 2009 And if I need some different such combinations? For each it is necessary
- downs (2/54) Feb 08 2009 I'm sure you can do something with templates. :)
- Christopher Wright (7/9) Feb 09 2009 You need to add those lines for every method you need virtual dispatch
- Weed (2/13) Feb 09 2009 Do not be surprised that so many continue to write in C++! :)
- Yigal Chripun (8/20) Feb 09 2009 huh?
- naryl (2/17) Feb 08 2009 Yes. It's in the attachment: http://www.digitalmars.com/webnews/newsgrou...
- Weed (2/15) Feb 08 2009 May be performance do not fall, it become equally high?
- Kagamin (2/15) Feb 09 2009 Well, D class code here is not equivalent to C++ class code. D code has ...
- Weed (3/21) Feb 09 2009 There opAdd is only for demonstration. In real life it may be virtual
- Weed (2/20) Feb 09 2009 It is really true?
- Kagamin (3/7) Feb 09 2009 If your example has nothing in common with real-world tasks and needs, i...
- bearophile (6/7) Feb 09 2009 I'd like to create a more apples-to-apples comparison, so if you have su...
- Kagamin (31/53) Feb 10 2009 Well, you can pass descendant objects :) I was surprised by this destruc...
- Michel Fortin (9/45) Feb 10 2009 Since you're passing c2 as a C by value to doSomething, slicing do
- Weed (6/30) Feb 19 2009 What is the result of the discussion?
- Kagamin (2/3) Feb 19 2009 Hmm... You already has Walter's answer. He's the boss.
- Weed (2/7) Feb 19 2009 I want a more specific answer (yes or no) if possible...
- Christopher Wright (3/10) Feb 19 2009 It will not. If you come up with some really awesome use case, then it
- Kagamin (2/3) Feb 20 2009 They may be good, but they don't show what can be done in C++ and can't ...
- Bill Baxter (45/65) Feb 20 2009 rixT.d
- Weed (2/8) Feb 21 2009 Yes, it's a good idea
- Weed (3/13) Feb 21 2009 As I said, you can write everything using "goto" and "if".
- Bill Baxter (3/15) Feb 21 2009 Please post again. I don't seem to recall any detailed example.
- Weed (2/19) Feb 21 2009 http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&gr...
- Bill Baxter (8/27) Feb 21 2009 roup=3Ddigitalmars.D&artnum=3D83506
- Denis Koroskin (2/29) Feb 21 2009 That's what *everyone* tells him!
- Bill Baxter (18/55) Feb 21 2009 y
- Yigal Chripun (7/49) Feb 22 2009 From a quick look at the flens DenseVector class:
- Weed (8/32) Feb 22 2009
- Weed (5/38) Feb 23 2009 Explains why the question is given in this form:
- Don (11/51) Feb 23 2009 Actually, in D, it's really difficult to give a class value semantics.
- Weed (5/61) Feb 24 2009 We already talked about this idea:
- naryl (2/43) Feb 23 2009 If you pass it by value you'll lose polymorphism. That must mean that yo...
- Weed (11/35) Feb 23 2009 Debatable
- Don (19/59) Feb 23 2009 This is the fundamental tradeoff at the heart of the matter.
- Weed (26/98) Feb 24 2009
- Don (18/120) Feb 24 2009 Even in C++, all of your base classes should be abstract.
- Weed (6/96) Feb 24 2009 What do you mean?
- Don (8/100) Feb 25 2009 See, for example,
- Weed (7/116) Feb 25 2009 We do not schoolgirls! :) Who is afraid of the complexity should use BAS...
- bearophile (6/7) Feb 25 2009 I like D1 mostly because it's quite less complex that C++, that's the fi...
- Weed (4/10) Feb 25 2009 I am cite myself:
- Daniel Keep (4/15) Feb 25 2009 Wow. I dare say you're missing the forest for the trees.
- Weed (4/14) Feb 25 2009 :)
- Daniel Keep (4/13) Feb 25 2009 http://www.ats-lang.org/EXAMPLE/MISC/listquicksort.dats
- Bill Baxter (10/22) Feb 25 2009 SIC.
- Ellery Newcomer (4/27) Feb 25 2009 Is it one of those deals where he somehow explained to the compiler what...
- Andrei Alexandrescu (3/8) Feb 25 2009 I guess superdan might disagree here :o).
- Kagamin (2/12) Feb 24 2009 It's probably already designed to be reference-type. I think, you'll hav...
- Christopher Wright (5/17) Feb 24 2009 In other words, it is not always easy to translate C++ to D. It's
- Weed (4/24) Feb 24 2009 As a result, classes will be slow, or require more code to achieve
- Christopher Wright (2/6) Feb 24 2009 Yes, C++ offers more unsafe optimizations than D.
- Weed (5/12) Feb 25 2009 Straight to the point!
- Christopher Wright (10/24) Feb 25 2009 I spoke poorly. C++ enshrines unsafe optimizations as essential language...
- Kagamin (2/11) Feb 25 2009 Is it common for functional languages to love 1-letter identifiers, I wo...
- Christopher Wright (8/20) Feb 25 2009 Probably. Mathematicians use "ab" to mean "a multiplied by b", so they
-
dsimcha
(22/42)
Feb 25 2009
- Simen Kjaeraas (11/16) Feb 25 2009 In the schools I've been to (in Norway), multiplication of scalars
- Andrei Alexandrescu (3/47) Feb 25 2009 You're in good company. http://www.cs.utexas.edu/~EWD/ewd13xx/EWD1300.PD...
- Joel C. Salomon (30/34) Feb 26 2009 You’ve got W.R. Hamilton to thank for that last; he found it impossibl...
(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
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
Daniel Keep :Weed wrote:Yes, but problem is that D does not leave way to create a class instance without allocation[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.
Feb 08 2009
Weed :Daniel Keep :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.Weed wrote:Yes, but problem is that D does not leave way to create a class instance without allocation[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.
Feb 08 2009
Weed wrote:Daniel Keep :You can allocate a class on the stack with: scope c = new C();Weed wrote:Yes, but problem is that D does not leave way to create a class instance without allocation[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.
Feb 08 2009
Walter Bright wrote:Weed 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)...Daniel Keep пишет:You can allocate a class on the stack with: scope c = new C();Weed wrote:Yes, but problem is that D does not leave way to create a class instance without allocation[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.
Feb 08 2009
Frits van Bommel wrote:Walter Bright wrote: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. SeanWeed 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)...Daniel Keep пишет:You can allocate a class on the stack with: scope c = new C();Weed wrote:Yes, but problem is that D does not leave way to create a class instance without allocation[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.
Feb 08 2009
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
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
Derek Parnell wrote:On Sun, 08 Feb 2009 11:13:00 -0800, Walter Bright wrote: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; }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?
Feb 08 2009
On Sun, 08 Feb 2009 14:37:18 -0800, Walter Bright wrote:Derek Parnell wrote: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.On Sun, 08 Feb 2009 11:13:00 -0800, Walter Bright wrote: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.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 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
== Quote from Derek Parnell (derek psych.ward)'s articleThis 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
Walter Bright wrote:Derek Parnell wrote: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; }On Sun, 08 Feb 2009 11:13:00 -0800, Walter Bright wrote: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.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?
Feb 08 2009
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:A mixin, perhaps: struct Brush { // ... } struct ColoredBrush { mixin Brush; Color color; }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?
Feb 08 2009
Derek Parnell wrote:On Sun, 08 Feb 2009 11:13:00 -0800, Walter Bright wrote:Go to the future and use the alias this thingie. AndreiIn 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?
Feb 08 2009
Walter Bright :Frits van Bommel wrote:But without such types the bulky code turns out (examples in this branch already presented)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.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
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
Adam D. Ruppe :On Mon, Feb 09, 2009 at 09:59:50AM +0700, Weed wrote:No, D do not allow return scope value.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.Often you add custom allocator in the classes who uses overload? You begin to do it after that talk? :)
Feb 08 2009
Daniel Keep wrote:Weed wrote:I'm curious, What is a heffalump?[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
Hello Yigal,I'm curious, What is a heffalump?http://en.wikipedia.org/wiki/Heffalump
Feb 08 2009
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
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
On Sun, 08 Feb 2009 17:07:31 +0300, Weed <resume755 mail.ru> wrote:Denis Koroskin пишет:I believe you should stick with structs for that.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
Denis Koroskin :Let's assume, polymorphism is necessary to these objects[skip]I believe you should stick with structs for that.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
On 2009-02-08 09:30:08 -0500, Weed <resume755 mail.ru> said:Let's assume, polymorphism is necessary to these objectsPolymorphism 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
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
Rainer Deyke wrote:Michel Fortin wrote: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. AndreiPolymorphism 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.
Feb 08 2009
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
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
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
Rainer Deyke wrote:Andrei Alexandrescu wrote:It's also a problem whenever you use avatar by value. It's only by programmer discipline that you avoid the slicing problem.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.
Feb 09 2009
Rainer Deyke wrote:Andrei Alexandrescu wrote:So the problem exists since you are explicitly addressing it.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'.So the problem exists since you are trusting the programmer to avoid it. Andrei
Feb 09 2009
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
Rainer Deyke wrote:Andrei Alexandrescu wrote: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.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.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
Christopher Wright wrote:That's not accidental. You did that on purpose.- 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?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
Rainer Deyke wrote: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?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.
Feb 12 2009
Christopher Wright wrote:Rainer Deyke wrote:That sounds tautological, but many newcomers to D are surprised by reference semantics when they expected value semantics.Okay, reference types don't have value semantics. That's exactly what I would expect.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.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
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
Tom S wrote:Rainer Deyke wrote: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.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.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.Would it remove the need for both classes and structs in the language,It's not a bug, it's a feature.[...] change my scanf calls [...]Are you serious? -- Rainer Deyke - rainerd eldwood.com
Feb 12 2009
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
Rainer Deyke wrote:Christopher Wright wrote:No, they don't. Each instance of C has its own copy of the 't' reference.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.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
Tom S wrote:Rainer Deyke wrote:That's like saying object slicing is an intentional feature. Given the intended semantics of 'C', it's a bug.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.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.comMoreover, 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...
Feb 12 2009
Rainer Deyke wrote:Tom S 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. If you want a distinct copy of something, then copy it. -- DanielRainer Deyke wrote:That's like saying object slicing is an intentional feature. Given the intended semantics of 'C', it's a bug.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.
Feb 12 2009
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
Rainer Deyke wrote:Daniel Keep 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. AndreiIt'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.
Feb 12 2009
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
Rainer Deyke wrote:Andrei Alexandrescu wrote:It will.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.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
On Fri, 13 Feb 2009 17:24:54 +0300, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Rainer Deyke wrote: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..Andrei Alexandrescu wrote:It will.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.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
Denis Koroskin wrote:On Fri, 13 Feb 2009 17:24:54 +0300, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Yes, not as methods, but as free functions.Rainer Deyke wrote:Will T[] get front, back, empty properties, and popFront(), popBack() methods?Andrei Alexandrescu wrote:It will.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.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. AndreiPerhaps, 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
Denis Koroskin wrote:On Fri, 13 Feb 2009 17:24:54 +0300, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote: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.Rainer Deyke wrote: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..Andrei Alexandrescu wrote:It will.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.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
Rainer Deyke :Michel Fortin wrote: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.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.
Feb 08 2009
Michel Fortin :On 2009-02-08 09:30:08 -0500, Weed <resume755 mail.ru> said:By performance loss :(Let's assume, polymorphism is necessary to these objectsPolymorphism 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.
Feb 08 2009
On 2009-02-08 23:43:13 -0500, Weed <resume755 mail.ru> said:Michel Fortin пишет: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/On 2009-02-08 09:30:08 -0500, Weed <resume755 mail.ru> said:By performance loss :(Let's assume, polymorphism is necessary to these objectsPolymorphism 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.
Feb 09 2009
Michel Fortin :On 2009-02-08 23:43:13 -0500, Weed <resume755 mail.ru> said: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=81958Michel Fortin :No. By forbiding the cases that leads to slicing, like returning a polymorphic object by value.On 2009-02-08 09:30:08 -0500, Weed <resume755 mail.ru> said:By performance loss :(Let's assume, polymorphism is necessary to these objectsPolymorphism 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.
Feb 09 2009
On 2009-02-09 07:00:56 -0500, Weed <resume755 mail.ru> said:I'mNo. 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=81958not 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
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
Michel Fortin wrote:On 2009-02-09 07:00:56 -0500, Weed <resume755 mail.ru> 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. 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).I'mNo. 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=81958not 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).
Feb 09 2009
On Mon, 09 Feb 2009 15:53:59 +0300, Don <nospam nospam.com> wrote:Michel Fortin wrote: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.On 2009-02-09 07:00:56 -0500, Weed <resume755 mail.ru> 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.I'mNo. 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=81958not 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).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
On 2009-02-09 16:02:10 -0500, "Denis Koroskin" <2korden gmail.com> said: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/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.
Feb 09 2009
Michel Fortin :On 2009-02-09 07:00:56 -0500, Weed <resume755 mail.ru> said:Yes, this is the easiest way that came to my headI'mNo. 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=81958not 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.YesThe 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 heapThere are other ways to acheive that in D however (mixins come to mind).
Feb 09 2009
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
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
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:Nevermind, I didn't understand the benchmark from quick glance.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
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
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:They both perform roughly the same when this typo is corrected.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
Denis Koroskin wrote:On Sun, 08 Feb 2009 18:40:53 +0300, Denis Koroskin <2korden gmail.com> wrote:It was a ploy! :o) AndreiOn Sun, 08 Feb 2009 18:09:41 +0300, naryl <cy ngs.ru> wrote:They both perform roughly the same when this typo is corrected.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
Denis Koroskin Wrote:On Sun, 08 Feb 2009 18:40:53 +0300, Denis Koroskin <2korden gmail.com> wrote: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.On Sun, 08 Feb 2009 18:09:41 +0300, naryl <cy ngs.ru> wrote:They both perform roughly the same when this typo is corrected.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
On Sun, 08 Feb 2009 20:24:08 +0300, naryl <cy ngs.ru> wrote:Denis Koroskin Wrote: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)On Sun, 08 Feb 2009 18:40:53 +0300, Denis Koroskin <2korden gmail.com> wrote: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.On Sun, 08 Feb 2009 18:09:41 +0300, naryl <cy ngs.ru> wrote:slowlyIt's a bit offtopic but I'd be grateful if someone can explain why D with structs completes this simple benchmark (see attachment) soThey both perform roughly the same when this typo is corrected.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
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
naryl wrote:Denis Koroskin Wrote:That's a good explanation. The only positive thing about the dmd backend (or dmd in general) is its compile speed.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
On Sun, 08 Feb 2009 23:45:41 +0300, naryl <cy ngs.ru> wrote:Denis Koroskin Wrote:Yes, that's why you can't claim D is slow because GCC outperforms DMD.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
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
Weed Wrote:Denis Koroskin �����:In this case both C++ and D performance drops almost tenfold.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
naryl :Weed Wrote:Hmmm. Can you show code?Denis Koroskin :In this case both C++ and D performance drops almost tenfold.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
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
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); } RaduIf 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
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
Christopher Wright :Weed wrote: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. ==============(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.Really, it has a little affected. Thanks!
Feb 08 2009
Weed wrote:Christopher Wright :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.Weed wrote: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. ==============(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.
Feb 08 2009
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!Christopher Wright :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.Weed wrote: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. ==============(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.
Feb 08 2009
Weed wrote:Christopher Wright :I'm sure you can do something with templates. :)Weed wrote:And if I need some different such combinations? For each it is necessary to write such 8-10 lines? This is terrible!Christopher Wright :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.Weed wrote: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. ==============(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.
Feb 08 2009
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
Christopher Wright :Weed wrote:Do not be surprised that so many continue to write in C++! :)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
Weed wrote:Christopher Wright :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++.Weed wrote:Do not be surprised that so many continue to write in C++! :)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
Weed Wrote:naryl �����:Yes. It's in the attachment: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=83523Weed Wrote:Hmmm. Can you show code?Denis Koroskin ���������������:In this case both C++ and D performance drops almost tenfold.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
naryl :Weed Wrote:May be performance do not fall, it become equally high?naryl :Weed Wrote:Denis Koroskin :In this case both C++ and D performance drops almost tenfold.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
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
Kagamin :Weed Wrote:There opAdd is only for demonstration. In real life it may be virtual method getSomething()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
Kagamin :Weed Wrote:It is really true?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.
Feb 09 2009
Weed Wrote:Of course.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?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
Kagamin :Weed Wrote: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.Of course.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
Weed Wrote:In C++ you can't pass object derived from C to opAdd method. In D you can.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.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.
Feb 09 2009
Kagamin :Weed Wrote: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; }In C++ you can't pass object derived from C to opAdd method. In D you can.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.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.
Feb 09 2009
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
Weed Wrote: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?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; }In C++ you can't pass object derived from C to opAdd method. In D you can.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.
Feb 10 2009
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
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
Weed Wrote:Will the language change?Hmm... You already has Walter's answer. He's the boss.
Feb 19 2009
Kagamin :Weed Wrote:I want a more specific answer (yes or no) if possible...Will the language change?Hmm... You already has Walter's answer. He's the boss.
Feb 19 2009
Weed wrote:Kagamin :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.Weed Wrote:I want a more specific answer (yes or no) if possible...Will the language change?Hmm... You already has Walter's answer. He's the boss.
Feb 19 2009
Christopher Wright :Weed wrote:Good (I think) use cases have been in this threadKagamin :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.Weed Wrote:I want a more specific answer (yes or no) if possible...Will the language change?Hmm... You already has Walter's answer. He's the boss.
Feb 20 2009
Weed wrote:Christopher Wright :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.Weed wrote:Good (I think) use cases have been in this threadKagamin :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.Weed Wrote:I want a more specific answer (yes or no) if possible...Will the language change?Hmm... You already has Walter's answer. He's the boss.
Feb 20 2009
Don :Weed wrote: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.Christopher Wright :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.Weed wrote:Good (I think) use cases have been in this threadKagamin :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.Weed Wrote:I want a more specific answer (yes or no) if possible...Will the language change?Hmm... You already has Walter's answer. He's the boss.
Feb 20 2009
Weed wrote:Don :Absolutely not! Those cases involve no polymorphism! No virtual function calls.Weed wrote: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.Christopher Wright :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.Weed wrote:Good (I think) use cases have been in this threadKagamin :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.Weed Wrote:I want a more specific answer (yes or no) if possible...Will the language change?Hmm... You already has Walter's answer. He's the boss.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
Don :Weed wrote: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!Don :Absolutely not! Those cases involve no polymorphism! No virtual function calls.Weed wrote: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.Christopher Wright :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.Weed wrote:Good (I think) use cases have been in this threadKagamin :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.Weed Wrote:I want a more specific answer (yes or no) if possible...Will the language change?Hmm... You already has Walter's answer. He's the boss.All your opinion. I proceed from the assumption that the programmer should be lazy. :) This positively affects the quality of the code and its reuseYes, 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).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++)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
Weed wrote:Don :AFAIK, OO linear algebra libraries have never been successful. Lots of people have tried.Weed wrote:I do not understand why. They are not principally to demonstrate the problem, but certainly should be able to use them.Don :Absolutely not! Those cases involve no polymorphism! No virtual function calls.Weed wrote: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.Christopher Wright :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.Weed wrote:Good (I think) use cases have been in this threadKagamin :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.Weed Wrote:I want a more specific answer (yes or no) if possible...Will the language change?Hmm... You already has Walter's answer. He's the boss.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!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!All your opinion. I proceed from the assumption that the programmer should be lazy. :) This positively affects the quality of the code and its reuseYes, 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).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++)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 21 2009
Weed Wrote:Good (I think) use cases have been in this threadThey 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
2009/2/21 Weed <resume755 mail.ru>:Kagamin =D0=C9=DB=C5=D4:be done in D. You were advised to use structs for value semantic.Weed Wrote:Good (I think) use cases have been in this threadThey may be good, but they don't show what can be done in C++ and can't =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.dSee 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
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
Weed :Bill Baxter :As I said, you can write everything using "goto" and "if". ...But why you do not like the original example of this thread?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
2009/2/21 Weed <resume755 mail.ru>:Weed =D0=C9=DB=C5=D4:Please post again. I don't seem to recall any detailed example. --bbBill Baxter =D0=C9=DB=C5=D4:As I said, you can write everything using "goto" and "if". ...But why you do not like the original example of this thread?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.
Feb 21 2009
Bill Baxter :2009/2/21 Weed <resume755 mail.ru>:http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=83506Weed :Please post again. I don't seem to recall any detailed example. --bbBill Baxter :As I said, you can write everything using "goto" and "if". ...But why you do not like the original example of this thread?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.
Feb 21 2009
On Sun, Feb 22, 2009 at 1:02 AM, Weed <resume755 mail.ru> wrote:Bill Baxter =D0=C9=DB=C5=D4:d2009/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=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. --bbhttp://www.digitalmars.com/pnews/read.php?server=3Dnews.digitalmars.com&g=Please post again. I don't seem to recall any detailed example. --bbAs I said, you can write everything using "goto" and "if". ...But why you do not like the original example of this thread?on your vague descriptions.
Feb 21 2009
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:That's what *everyone* tells him!Bill Baxter пишет: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. --bb2009/2/21 Weed <resume755 mail.ru>:http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=83506Weed пишет:Please post again. I don't seem to recall any detailed example. --bbBill Baxter пишет:As I said, you can write everything using "goto" and "if". ...But why you do not like the original example of this thread?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.
Feb 21 2009
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=:yOn 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=eagree with you that it's not possible. But as long as you continu=&group=3Ddigitalmars.D&artnum=3D83506http://www.digitalmars.com/pnews/read.php?server=3Dnews.digitalmars.com=Please post again. I don't seem to recall any detailed example. --bbAs I said, you can write everything using "goto" and "if". ...But why you do not like the original example of this thread?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.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. --bbYou 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. --bbThat's what *everyone* tells him!
Feb 21 2009
Bill Baxter wrote:On Sun, Feb 22, 2009 at 5:10 AM, Denis Koroskin<2korden gmail.com> wrote: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.On Sat, 21 Feb 2009 21:49:46 +0300, Bill Baxter<wbaxter gmail.com> wrote: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. --bbOn Sun, Feb 22, 2009 at 1:02 AM, Weed<resume755 mail.ru> wrote:That's what *everyone* tells him!Bill Baxter :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. --bb2009/2/21 Weed<resume755 mail.ru>:http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=83506Weed :Please post again. I don't seem to recall any detailed example. --bbBill Baxter :As I said, you can write everything using "goto" and "if". ...But why you do not like the original example of this thread?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.
Feb 22 2009
Bill Baxter :On Sun, Feb 22, 2009 at 1:02 AM, Weed <resume755 mail.ru> wrote: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?Bill Baxter :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.2009/2/21 Weed <resume755 mail.ru>:http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=83506Weed :Please post again. I don't seem to recall any detailed example. --bbBill Baxter :As I said, you can write everything using "goto" and "if". ...But why you do not like the original example of this thread?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.
Feb 22 2009
Weed :Bill Baxter :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++?On Sun, Feb 22, 2009 at 1:02 AM, Weed <resume755 mail.ru> wrote: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?Bill Baxter :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.2009/2/21 Weed <resume755 mail.ru>:http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=83506Weed :Please post again. I don't seem to recall any detailed example. --bbBill Baxter :As I said, you can write everything using "goto" and "if". ...But why you do not like the original example of this thread?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.
Feb 23 2009
Weed wrote:Weed :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.Bill Baxter :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++?On Sun, Feb 22, 2009 at 1:02 AM, Weed <resume755 mail.ru> wrote: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?Bill Baxter :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.2009/2/21 Weed <resume755 mail.ru>:http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=83506Weed :Please post again. I don't seem to recall any detailed example. --bbBill Baxter :As I said, you can write everything using "goto" and "if". ...But why you do not like the original example of this thread?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.
Feb 23 2009
Don :Weed wrote: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:")Weed :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.Bill Baxter :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++?On Sun, Feb 22, 2009 at 1:02 AM, Weed <resume755 mail.ru> wrote: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?Bill Baxter :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.2009/2/21 Weed <resume755 mail.ru>:http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=83506Weed :Please post again. I don't seem to recall any detailed example. --bbBill Baxter :As I said, you can write everything using "goto" and "if". ...But why you do not like the original example of this thread?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.
Feb 24 2009
Weed Wrote:Weed �����: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.Bill Baxter �����: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++?On Sun, Feb 22, 2009 at 1:02 AM, Weed <resume755 mail.ru> wrote: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?Bill Baxter �����: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.2009/2/21 Weed <resume755 mail.ru>:http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=83506Weed �����:Please post again. I don't seem to recall any detailed example. --bbBill Baxter �����:As I said, you can write everything using "goto" and "if". ...But why you do not like the original example of this thread?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.
Feb 23 2009
naryl :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 "&")If you pass it by value you'll lose polymorphism.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++?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?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.--bbhttp://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=83506That 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
Weed wrote:naryl :Sure, but you're not using 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 "&")If you pass it by value you'll lose polymorphism.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++?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?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.--bbhttp://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=83506This 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.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
Don :Weed wrote:There is no, but the same object can be used in other places, including the polymorphismnaryl :Sure, but you're not using 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 "&")If you pass it by value you'll lose polymorphism.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++?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?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.--bbhttp://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=83506This 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.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.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.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
Weed wrote:Don :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.Weed wrote:There is no, but the same object can be used in other places, including the polymorphismnaryl :Sure, but you're not using 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 "&")If you pass it by value you'll lose polymorphism.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++?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?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.--bbhttp://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=83506This 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.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.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.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.D gets significant benefits from this.Benefits: 1. Disappeared slicing 2. ?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.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.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.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.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
Don :Why?Even in C++, all of your base classes should be abstract.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.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.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.If you want to move between polymorphism and non-polymorphism in C++, it's a non-trivial refactoring.What do you mean?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.D gets significant benefits from this.Benefits: 1. Disappeared slicing 2. ?Or reference (&). Thus, even polymorphic class on stack can be used safely in C++.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.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.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.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.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
Weed wrote:Don :See, for example, http://www.artima.com/intv/modern.htmlWhy?Even in C++, all of your base classes should be abstract.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.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.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.Language complexity.If you want to move between polymorphism and non-polymorphism in C++, it's a non-trivial refactoring.What do you mean?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.D gets significant benefits from this.Benefits: 1. Disappeared slicing 2. ?Same thing. You're either not using value semantics, or not using polymorphism. Not both at once.Or reference (&). Thus, even polymorphic class on stack can be used safely in C++.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.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.Passing a polymorphic class by value rarely makes sense. You can't get (runtime) polymorphism unless you go through a pointer.I'm wasting my time here. I'll not make any further comments on this subject.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.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.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 25 2009
Don :Weed wrote:It did not say how that all base classes should be abstractDon :See, for example, http://www.artima.com/intv/modern.htmlWhy?Even in C++, all of your base classes should be abstract.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.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.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.We do not schoolgirls! :) Who is afraid of the complexity should use BASIC.Language complexity.If you want to move between polymorphism and non-polymorphism in C++, it's a non-trivial refactoring.What do you mean?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.D gets significant benefits from this.Benefits: 1. Disappeared slicing 2. ?If you needed polymorphism you should use references or pointers, where necessary performance you use value semantics. C++ allows both options, D - no.Same thing. You're either not using value semantics, or not using polymorphism. Not both at once.Or reference (&). Thus, even polymorphic class on stack can be used safely in C++.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.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.Passing a polymorphic class by value rarely makes sense. You can't get (runtime) polymorphism unless you go through a pointer.OkayI'm wasting my time here. I'll not make any further comments on this subject.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.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.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 25 2009
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
bearophile :Weed:I am cite myself: "That is actually a model of classes D harder than C++."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/There uses preprocessor. It is wrong.
Feb 25 2009
Weed wrote:bearophile :Man, wish I could have done that when writing my thesis...Weed:I am cite myself: "That is actually a model of classes D harder than C++."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".Wow. I dare say you're missing the forest for the trees. -- danielYou probably don't want D, you want ATS: http://www.ats-lang.org/There uses preprocessor. It is wrong.
Feb 25 2009
Daniel Keep :Weed wrote::) Sorry, this has already been discussed here: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=84842bearophile :Man, wish I could have done that when writing my thesis...Weed:I am cite myself: "That is actually a model of classes D harder than C++."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".
Feb 25 2009
bearophile wrote:Weed:http://www.ats-lang.org/EXAMPLE/MISC/listquicksort.dats Dear god. I think... I think I'm going to go cry in the corner... -- DanielWe 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
On Wed, Feb 25, 2009 at 11:47 PM, Daniel Keep <daniel.keep.lists gmail.com> wrote:bearophile wrote:SIC.Weed:We do not schoolgirls! :) Who is afraid of the complexity should use BA=rst thing I ask to a new language like D. Complexity "kills".I like D1 mostly because it's quite less complex that C++, that's the fi=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! --bbYou probably don't want D, you want ATS: http://www.ats-lang.org/ Bye, bearophilehttp://www.ats-lang.org/EXAMPLE/MISC/listquicksort.dats Dear god. =A0I think... I think I'm going to go cry in the corner...
Feb 25 2009
Bill Baxter wrote:On Wed, Feb 25, 2009 at 11:47 PM, Daniel Keep <daniel.keep.lists gmail.com> wrote: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?bearophile wrote: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! --bbWeed:http://www.ats-lang.org/EXAMPLE/MISC/listquicksort.dats Dear god. I think... I think I'm going to go cry in the corner...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
Weed wrote:Don пишет:I guess superdan might disagree here :o). AndreiLanguage complexity.We do not schoolgirls! :)
Feb 25 2009
Weed Wrote: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.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.But why not allow this operation at the same speed that allows C++?If you pass it by value you'll lose polymorphism.
Feb 24 2009
Kagamin wrote:Weed Wrote: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.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.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.But why not allow this operation at the same speed that allows C++?If you pass it by value you'll lose polymorphism.
Feb 24 2009
Christopher Wright :Kagamin 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++.Weed Wrote: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.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.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.But why not allow this operation at the same speed that allows C++?If you pass it by value you'll lose polymorphism.
Feb 24 2009
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
Christopher Wright :Weed wrote: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. :)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 25 2009
Weed wrote:Christopher Wright :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.Weed wrote: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. :)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 25 2009
Daniel Keep Wrote:Is it common for functional languages to love 1-letter identifiers, I wonder?You probably don't want D, you want ATS: http://www.ats-lang.org/ Bye, bearophilehttp://www.ats-lang.org/EXAMPLE/MISC/listquicksort.dats Dear god. I think... I think I'm going to go cry in the corner...
Feb 25 2009
Kagamin wrote:Daniel Keep Wrote: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.Is it common for functional languages to love 1-letter identifiers, I wonder?You probably don't want D, you want ATS: http://www.ats-lang.org/ Bye, bearophilehttp://www.ats-lang.org/EXAMPLE/MISC/listquicksort.dats Dear god. I think... I think I'm going to go cry in the corner...
Feb 25 2009
== Quote from Christopher Wright (dhasenan gmail.com)'s articleKagamin wrote:<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>Daniel Keep Wrote: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.Is it common for functional languages to love 1-letter identifiers, I wonder?You probably don't want D, you want ATS: http://www.ats-lang.org/ Bye, bearophilehttp://www.ats-lang.org/EXAMPLE/MISC/listquicksort.dats Dear god. I think... I think I'm going to go cry in the corner...
Feb 25 2009
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
dsimcha wrote:== Quote from Christopher Wright (dhasenan gmail.com)'s articleYou're in good company. http://www.cs.utexas.edu/~EWD/ewd13xx/EWD1300.PDF AndreiKagamin wrote:<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>Daniel Keep Wrote: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.Is it common for functional languages to love 1-letter identifiers, I wonder?You probably don't want D, you want ATS: http://www.ats-lang.org/ Bye, bearophilehttp://www.ats-lang.org/EXAMPLE/MISC/listquicksort.dats Dear god. I think... I think I'm going to go cry in the corner...
Feb 25 2009
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: ABv ≡ 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: • AB: 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 = ½(AB−BA). (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