www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - What are the prominent downsides of the D programming language?

reply Tomcruisesmart <tomcruisesmart3 gmail.com> writes:
Hi,
I'm looking for healthy conversation.
What are the prominent downsides of the D programming language?
Sep 21 2020
next sibling parent reply Ruby The Roobster <michaeleverestc79 gmail.com> writes:
On Monday, 21 September 2020 at 09:29:21 UTC, Tomcruisesmart 
wrote:
 Hi,
 I'm looking for healthy conversation.
 What are the prominent downsides of the D programming language?
One downside is that classes can't inherit from multiple classes. I know that there is a thing called an interface which a class can inherit more that one of those. Thing is, functions in interfaces have to be abstract. Also, member variables declared in an interface have to be static, and the only member functions that are defined have to be static. Why can't we just inherit from multiple classes?
Sep 21 2020
next sibling parent claptrap <clap trap.com> writes:
On Monday, 21 September 2020 at 09:35:10 UTC, Ruby The Roobster 
wrote:
 On Monday, 21 September 2020 at 09:29:21 UTC, Tomcruisesmart 
 wrote:
 Hi,
 I'm looking for healthy conversation.
 What are the prominent downsides of the D programming language?
One downside is that classes can't inherit from multiple classes. I know that there is a thing called an interface which a class can inherit more that one of those. Thing is, functions in interfaces have to be abstract. Also, member variables declared in an interface have to be static, and the only member functions that are defined have to be static. Why can't we just inherit from multiple classes?
I hate that it compiles so fast. I used to be able to watch a lot more youtube videos when I used C++.
Sep 21 2020
prev sibling next sibling parent Abdulhaq <alynch4047 gmail.com> writes:
On Monday, 21 September 2020 at 09:35:10 UTC, Ruby The Roobster 
wrote:
 On Monday, 21 September 2020 at 09:29:21 UTC, Tomcruisesmart 
 wrote:
 Hi,
 I'm looking for healthy conversation.
 What are the prominent downsides of the D programming language?
One downside is that classes can't inherit from multiple classes. I know that there is a thing called an interface which a class can inherit more that one of those. Thing is, functions in interfaces have to be abstract. Also, member variables declared in an interface have to be static, and the only member functions that are defined have to be static. Why can't we just inherit from multiple classes?
Multiple inheritance would really complicate the language, and it's benefits are held not to be sufficient to outweigh the downside of that. Another very important thing to bear in mind is to prefer composition over inheritance - a simple maxim but very very true (IMO). Google it for more details. In the seventies and eighties oject orientation was very fashionable and books like "Learn C++ in 24 hrs" were mainly filled with the complexities of inheritance. This made us think that inheritance was the preferred way to share functionality between classes of objects. As it turns out, it's not (IMO).
Sep 21 2020
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 9/21/2020 2:35 AM, Ruby The Roobster wrote:
 One downside is that classes can't inherit from multiple classes.
That's a feature, not a downside. I'm not joking. Multiple inheritance is a horrible abstraction, all it does is confuse people.
Sep 21 2020
parent reply mw <mingwu gmail.com> writes:
On Monday, 21 September 2020 at 10:42:55 UTC, Walter Bright wrote:
 On 9/21/2020 2:35 AM, Ruby The Roobster wrote:
 One downside is that classes can't inherit from multiple 
 classes.
That's a feature, not a downside. I'm not joking.
As you admitted some time earlier, the other mechanisms such as sub-typing, mixin has effectively introduced multiple inheritance into D already.
 Multiple inheritance is a horrible abstraction, all it does is 
 confuse people.
Well, if it's designed or implemented poorly in the language. https://forum.dlang.org/post/iajvjzaskzwlhcuztiiz forum.dlang.org I think this deserved to be more widely known: The diamond problem is a *solved* problem by Eiffel language, which won the 2006 ACM Software System Award: https://en.wikipedia.org/wiki/ACM_Software_System_Award And I showed the concrete example here: https://forum.dlang.org/thread/obqthozmxwzhvrafothw forum.dlang.org
Sep 28 2020
next sibling parent jmh530 <john.michael.hall gmail.com> writes:
On Monday, 28 September 2020 at 18:12:16 UTC, mw wrote:
  [snip]

 Well, if it's designed or implemented poorly in the language.


 https://forum.dlang.org/post/iajvjzaskzwlhcuztiiz forum.dlang.org

 I think this deserved to be more widely known:

 The diamond problem is a *solved* problem by Eiffel language, 
 which won the 2006 ACM Software System Award:

 https://en.wikipedia.org/wiki/ACM_Software_System_Award

 And I showed the concrete example here:

 https://forum.dlang.org/thread/obqthozmxwzhvrafothw forum.dlang.org
I remember that thread. It was interesting.
Sep 28 2020
prev sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Sep 28, 2020 at 06:12:16PM +0000, mw via Digitalmars-d wrote:
 On Monday, 21 September 2020 at 10:42:55 UTC, Walter Bright wrote:
 On 9/21/2020 2:35 AM, Ruby The Roobster wrote:
 One downside is that classes can't inherit from multiple classes.
That's a feature, not a downside. I'm not joking.
As you admitted some time earlier, the other mechanisms such as sub-typing, mixin has effectively introduced multiple inheritance into D already.
Yes, and we're already regretting it. As it turns out, alias this (one of the ways to do multiple inheritance in D) has quite a few nasty corner cases that cannot be (easily) reconciled, and now we're starting to discourage its use. How to resolve identifier lookups when there are conflicts, etc.. There's always a way to rationalize your way out of it; but at the end of the day, it leads to confusing, hard-to-remember, arbitrary rules that have counterintuitive corner cases.
 Multiple inheritance is a horrible abstraction, all it does is
 confuse people.
Well, if it's designed or implemented poorly in the language.
If you have a *workable* idea of how to do it *in D*, we'd love to hear it. I'm not holding my breath, though. Don't get me wrong; I love alias this and use it a lot myself. But over the years, I'm gradually beginning to see where it leads to problems. It's useful as a quick hack or shunt to bridge two subsystems that are kinda but not quite compatible, or to shoehorn implicit conversions into a user-defined type, but in the long term, it leads to code smells. (Implicit conversions are another of those things that sounds like a good idea, is convenient to use, but in the long term leads to poor maintainability.) T -- Your inconsistency is the only consistent thing about you! -- KD
Sep 28 2020
parent reply Petar Kirov [ZombineDev] <petar.p.kirov gmail.com> writes:
On Monday, 28 September 2020 at 18:42:36 UTC, H. S. Teoh wrote:
 On Mon, Sep 28, 2020 at 06:12:16PM +0000, mw via Digitalmars-d 
 wrote:
 On Monday, 21 September 2020 at 10:42:55 UTC, Walter Bright 
 wrote:
 On 9/21/2020 2:35 AM, Ruby The Roobster wrote:
 One downside is that classes can't inherit from multiple 
 classes.
That's a feature, not a downside. I'm not joking.
As you admitted some time earlier, the other mechanisms such as sub-typing, mixin has effectively introduced multiple inheritance into D already.
Yes, and we're already regretting it. As it turns out, alias this (one of the ways to do multiple inheritance in D) has quite a few nasty corner cases that cannot be (easily) reconciled, and now we're starting to discourage its use. How to resolve identifier lookups when there are conflicts, etc.. There's always a way to rationalize your way out of it; but at the end of the day, it leads to confusing, hard-to-remember, arbitrary rules that have counterintuitive corner cases.
I'd say the main reason we may be "regretting" `alias this` (though I wouldn't go as far as say "regretting") is that it wasn't designed systematically enough (with consideration of it's interaction with other features) and also at time the language was very free floating (some parts of the language were still being changed and tweaked quite often). I suggest you re-read the old posts from the DIP66 thread. I think principled solutions to quite a few of the issues with multiple alias this were found.
 Multiple inheritance is a horrible abstraction, all it does 
 is confuse people.
Well, if it's designed or implemented poorly in the language.
If you have a *workable* idea of how to do it *in D*, we'd love to hear it. I'm not holding my breath, though. Don't get me wrong; I love alias this and use it a lot myself. But over the years, I'm gradually beginning to see where it leads to problems. It's useful as a quick hack or shunt to bridge two subsystems that are kinda but not quite compatible, or to shoehorn implicit conversions into a user-defined type, but in the long term, it leads to code smells. (Implicit conversions are another of those things that sounds like a good idea, is convenient to use, but in the long term leads to poor maintainability.) T
I don't have experience with multiple inheritance in Eiffel, but it would be shame that in a language with `static if`, `mixin template`s, `static foreach`, etc. we can't figure out a way to make it work. I think one extravagant, but definetely workable solution would be create a template DSL (ofc it could also be string mixin-based) in D to prototype a multiple inheritance system (with e.g. the Eiffel features `rename`, `export`, `undefine`, `redefine` / `override`, and `select`). Being just a prototype, it should be acceptable to go with custom functions like `isSubTypeOf`, `asBaseType`, etc., instead of using the built-in language syntax and semantics. (Sort of like https://code.dlang.org/packages/openmethods adds multiple dispatch.)
Sep 29 2020
next sibling parent reply mw <mingwu gmail.com> writes:
On Tuesday, 29 September 2020 at 09:56:47 UTC, Petar Kirov 
[ZombineDev] wrote:
 I think one extravagant, but definetely workable solution would 
 be create a template DSL (ofc it could also be string 
 mixin-based) in D to prototype a multiple
 inheritance system (with e.g. the Eiffel features `rename`, 
 `export`, `undefine`, `redefine` / `override`, and `select`). 
 Being just a prototype, it should be acceptable to go with 
 custom functions like `isSubTypeOf`, `asBaseType`, etc., 
 instead of using the built-in language syntax and semantics. 
 (Sort of like https://code.dlang.org/packages/openmethods adds 
 multiple dispatch.)
This is an interesting idea, basically implement the Eiffel compiler (the OO part) as a D library, and perhaps also use openmethods, then we will have a Lisp's multi-methods + Eiffel OO inheritance. I'm not sure how complex this implementation is going to look like. Hey, as I mentioned here: https://forum.dlang.org/post/ufypgxzckjdstifhlrtk forum.dlang.org many (if not all) Eiffel compilers actually compile Eiffel program to C (as target language). I just uploaded SmartEiffel (open source) 1.1 compiler, and my previous visitor example to: https://github.com/mingwugmail/dlang_tour/tree/master/eiffel e.g. the generated C code of my example is: https://github.com/mingwugmail/dlang_tour/blob/master/eiffel/visitor/app1.c We can use D compiler's `-betterC` option to build it, the we are done :-)
Sep 29 2020
parent reply Jean-Louis Leroy <jl leroy.nyc> writes:
On Tuesday, 29 September 2020 at 17:33:47 UTC, mw wrote:
 On Tuesday, 29 September 2020 at 09:56:47 UTC, Petar Kirov 
 [ZombineDev] wrote:
 I think one extravagant, but definetely workable solution 
 would be create a template DSL (ofc it could also be string 
 mixin-based) in D to prototype a multiple
 inheritance system (with e.g. the Eiffel features `rename`, 
 `export`, `undefine`, `redefine` / `override`, and `select`). 
 Being just a prototype, it should be acceptable to go with 
 custom functions like `isSubTypeOf`, `asBaseType`, etc., 
 instead of using the built-in language syntax and semantics. 
 (Sort of like https://code.dlang.org/packages/openmethods adds 
 multiple dispatch.)
This is an interesting idea, basically implement the Eiffel compiler (the OO part) as a D library, and perhaps also use openmethods, then we will have a Lisp's multi-methods + Eiffel OO inheritance. I'm not sure how complex this implementation is going to look like.
There are precedents to this approach. One is fairly well known: CLOS, which is an object system that supports open multi-methods and multiple inheritance (and method combination, which I don't find very convincing). CLOS is written entirely in Common Lisp. Another example is COS: the C Object System (https://github.com/CObjectSystem/COS). COS is pretty much CLOS written in C and CPP macros. D is a great language for experimenting with language features. Maybe not as good as Lisp (at least currently) but certainly much better than C. I know at least two examples: Atila's tardy (golang-style interfaces) and my own openmethods. Regarding mutliple inheritance, I have always been convinced that it was a good feature. Or rather, that restricting inheritance to single is completely unnatural. My very first open source project was a modified version of Microsoft's MFC library that supported multiple inheritance. I think that C++ got something right: sometimes we need shared inheritance, and sometimes repeated inheritance. Although, in my experience, I rarely needed repeated inheritance. CLOS, in contrast, gives you only one option, namely, shared inheritance. On the other hand, C++ makes the sharing of a base a property of the inheritance relationship (virtual inheritance), not of the base. So, if a base is inherited non-virtually in an inheritance lattice, it becomes impossible to request only one copy when merging hierarchies. Perhaps it should be up to the deriving class to specify the inheritance lattice, including which sub-objects are shared and which are repeated. Anyway, back to mw's post, I am pretty sure that it is possible to write a fairly good CLOS in D.
Sep 29 2020
parent reply mw <mingwu gmail.com> writes:
On Tuesday, 29 September 2020 at 18:26:42 UTC, Jean-Louis Leroy 
wrote:
 This is an interesting idea, basically implement the Eiffel 
 compiler (the OO part) as a D library, and perhaps also use 
 openmethods, then we will have a Lisp's multi-methods + Eiffel 
 OO inheritance.

 I'm not sure how complex this implementation is going to look 
 like.
...
 Anyway, back to mw's post, I am pretty sure that it is possible 
 to write a fairly good CLOS in D.
Good to hear, I opened an discussion issue here: https://github.com/jll63/openmethods.d/issues/19 Anyone who's interested in the implementation, let's continue the brain storming there.
Sep 29 2020
parent reply jmh530 <john.michael.hall gmail.com> writes:
On Tuesday, 29 September 2020 at 18:38:29 UTC, mw wrote:
 [snip]

 Good to hear, I opened an discussion issue here:

 https://github.com/jll63/openmethods.d/issues/19

 Anyone who's interested in the implementation, let's continue 
 the brain storming there.
You might recall that back in June I wrote [1] that D does not have the ability to properly disable base members and member functions, which would make implementing Eiffel-like semantics significantly easier as part of the base language. [1] https://forum.dlang.org/post/tpwwzkvcarqquqslspul forum.dlang.org
Sep 29 2020
parent reply mw <mingwu gmail.com> writes:
On Tuesday, 29 September 2020 at 20:29:49 UTC, jmh530 wrote:
 On Tuesday, 29 September 2020 at 18:38:29 UTC, mw wrote:
 [snip]

 Good to hear, I opened an discussion issue here:

 https://github.com/jll63/openmethods.d/issues/19

 Anyone who's interested in the implementation, let's continue 
 the brain storming there.
You might recall that back in June I wrote [1] that D does not have the ability to properly disable base members and member functions, which would make implementing Eiffel-like semantics significantly easier as part of the base language. [1] https://forum.dlang.org/post/tpwwzkvcarqquqslspul forum.dlang.org
Yes, I remember that. That approach is still trying to somehow trick / patch (e.g. via some form of opDispath) the current D object system. The LISP (CLOS) multi-methods approach is different: basically, you build the dispatch mechanism yourself; so everything is under the libraries' control. This is essentially how openmethods.d Multiple Dispatch is done.
Sep 29 2020
parent reply Jean-Louis Leroy <jl leroy.nyc> writes:
In reply to mw and jmh530:

I looked a bit at Eiffel circa 2000 and, to be frank, I didn't 
like it. I think that it belongs to the category of Object 
Obsessed languages, where everything is (has to be) an object, 
and every function has to be a member. This contradicts the 
philosophy behind openmethods and CLOS: methods live outside of 
classes, and polymorphic behavior can be added without modifying 
existing classes. Functionality found inside classes tend to be 
minimal - what Luís Marques describes as the "anemic domain 
models".

On the other hand, I like it that Eiffel has multiple 
inheritance. I did a bit of reading today and it seems to offer 
flexibility regarding shared and repeated inheritance. In 
particular, it is not decided by the direct subclasses (like with 
C++'s virtual inheritance) So there may be some good ideas to 
steal there.
Sep 29 2020
parent reply mw <mingwu gmail.com> writes:
On Tuesday, 29 September 2020 at 21:19:35 UTC, Jean-Louis Leroy 
wrote:
 In reply to mw and jmh530:

 I looked a bit at Eiffel circa 2000 and, to be frank, I didn't 
 like it. I think that it belongs to the category of Object 
 Obsessed languages, where everything is (has to be) an object, 
 and every function has to be a member. This contradicts the
I don't like the Eiffel's pure OO treatment either: everything in the world has to be modeled as object, which does not always make sense.
 On the other hand, I like it that Eiffel has multiple 
 inheritance. I did a bit of reading today and it seems to offer 
 flexibility regarding shared and repeated inheritance. In 
 particular, it is not decided by the direct subclasses (like 
 with C++'s virtual inheritance) So there may be some good ideas 
 to steal there.
The key idea is to treat each parent's class attributes individually (via rename/undefine/redefine/select) instead of as in other multiple inheritance languages, e.g. C++'s all-or-none approach, i.e. either all the parents' attributes are shared or separated, and even when separated, there is no proper renaming mechanism to handle it. I still think the idea of combine Eiffel's multiple inheritance with CLOS like multi-methods is interesting: this basically is to use D as a target language, and completely build a new OO system on top of it.
Sep 29 2020
parent reply Jean-Louis Leroy <jl leroy.nyc> writes:
On Tuesday, 29 September 2020 at 21:43:03 UTC, mw wrote:
 The key idea is to treat each parent's class attributes 
 individually (via rename/undefine/redefine/select) instead of 
 as in other multiple inheritance languages, e.g. C++'s 
 all-or-none approach, i.e. either all the parents' attributes 
 are shared or separated, and even when separated, there is no 
 proper renaming mechanism to handle it.
If Base has features f and g, and Derived inherits from Base but undefines g, I assume that a Derived object cannot be substituted for a Base. Correct?
Sep 29 2020
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Sep 29, 2020 at 10:02:28PM +0000, Jean-Louis Leroy via Digitalmars-d
wrote:
 On Tuesday, 29 September 2020 at 21:43:03 UTC, mw wrote:
 The key idea is to treat each parent's class attributes individually
 (via rename/undefine/redefine/select) instead of as in other
 multiple inheritance languages, e.g. C++'s all-or-none approach,
 i.e. either all the parents' attributes are shared or separated, and
 even when separated, there is no proper renaming mechanism to handle
 it.
If Base has features f and g, and Derived inherits from Base but undefines g, I assume that a Derived object cannot be substituted for a Base. Correct?
This would break Liskov Substitution, wouldn't it? In any case, Eiffel-style multiple inheritance with undefine/redefine sounds to me more and more like a case of composition rather than inheritance. IOW you're not really dealing with subclasses that can be treated as instances of the base class anymore; you're dealing with pulling in {methods,fields,etc.} from the base class and arbitrarily modifying them to produce a new object that may or may not even substitute for the base class anymore in the Liskov sense. Frankly, whenever I'm faced with this sort of free-for-all Lego-style object composition, I throw inheritance out the window and instead write my own infrastructure for object composition. Like an entity-component architecture or some such, that confers much more flexibility (and has cleaner implementation / saner semantics) than a free-for-all inheritance system. I mean, sure, being able to undefine/redefine base class members is all nice and everything, but it's very hard to reason about. (Systems with erasure semantics are generally hard to reason about.) I'd rather make it explicit by representing it with an entity-component storage system than trying to shoehorn it into some kind of inheritance hierarchy with an arbitrarily-imposed hierarchical system. IME, objects that need arbitrary composition operations to define generally also fit poorly into a hierarchical system; I prefer using a true compositional system like ECS where (1) it's explicit what exactly you're trying to do, and (2) it's actually maximally flexible, in that you can add/remove arbitrary combinations of components to your entities, and (3) this can be done even at runtime, no lock-in to a specific memory layout. T -- Creativity is not an excuse for sloppiness.
Sep 29 2020
parent reply mw <mingwu gmail.com> writes:
On Tuesday, 29 September 2020 at 22:18:52 UTC, H. S. Teoh wrote:
 On Tue, Sep 29, 2020 at 10:02:28PM +0000, Jean-Louis Leroy via 
 Digitalmars-d wrote:
 On Tuesday, 29 September 2020 at 21:43:03 UTC, mw wrote:
 The key idea is to treat each parent's class attributes 
 individually (via rename/undefine/redefine/select) instead 
 of as in other multiple inheritance languages, e.g. C++'s 
 all-or-none approach, i.e. either all the parents' 
 attributes are shared or separated, and even when separated, 
 there is no proper renaming mechanism to handle it.
If Base has features f and g, and Derived inherits from Base but undefines g, I assume that a Derived object cannot be substituted for a Base. Correct?
This would break Liskov Substitution, wouldn't it?
No, it just become abstract method, and class.
 {methods,fields,etc.} from the base class and arbitrarily 
 modifying them to produce a new object that may or may not even 
 substitute for the base class anymore in the Liskov sense.
Can you study the language behavior before making such comments? This language won the ACM system software award!
 I mean, sure, being able to undefine/redefine base class 
 members is all nice and everything, but it's very hard to 
 reason about.
It's very easy, and nature to reason about it: undefine a method Derived.foo() ==> Derived.foo() now becomes an abstract method. Please see my previous reply. And try it yourself: https://github.com/mingwugmail/dlang_tour/tree/master/eiffel/mi
Sep 29 2020
parent mw <mingwu gmail.com> writes:
On Tuesday, 29 September 2020 at 22:45:02 UTC, mw wrote:
 It's very easy, and nature to reason about it:
s/nature/natural
Sep 29 2020
prev sibling parent reply mw <mingwu gmail.com> writes:
On Tuesday, 29 September 2020 at 22:02:28 UTC, Jean-Louis Leroy 
wrote:
 On Tuesday, 29 September 2020 at 21:43:03 UTC, mw wrote:
 The key idea is to treat each parent's class attributes 
 individually (via rename/undefine/redefine/select) instead of 
 as in other multiple inheritance languages, e.g. C++'s 
 all-or-none approach, i.e. either all the parents' attributes 
 are shared or separated, and even when separated, there is no 
 proper renaming mechanism to handle it.
If Base has features f and g, and Derived inherits from Base but undefines g, I assume that a Derived object cannot be substituted for a Base. Correct?
It still can; but the Derived now becomes a deferred- (in D's term abstract-) class. because Derived.g becomes a deferred- (in D's term abstract-) method. This is the demo: https://github.com/mingwugmail/dlang_tour/tree/master/eiffel/mi https://github.com/mingwugmail/dlang_tour/blob/master/eiffel/mi/us_resident.e#L3 undefine addr https://github.com/mingwugmail/dlang_tour/blob/master/eiffel/mi/app.e#L17 create usr.make -- ****** Warning: addr is a deferred feature in US_RESIDENT. https://github.com/mingwugmail/dlang_tour/blob/master/eiffel/mi/app.e#L11 print_addr(p: PERSON) is do io.put_string(p.addr + "%N") end NOTE: I'm not sure if the SmartEiffel compiler is implemented correctly, it generate warning instead of error, during compilation: $ make compile app.e -o app ****** Warning: addr is a deferred feature in US_RESIDENT. And if you run it, it error out: $ ./app *** Error at Run Time ***: Deferred routine called. 4 frames in current stack. Ideally, this program shouldn't compile; since it detected that we are trying to create an object of a abstract (deferred) class. Hey, just download the SmartEiffel compiler, and try the demo :-) it's all in the same repo: https://github.com/mingwugmail/dlang_tour/tree/master/eiffel
Sep 29 2020
parent reply Jean-Louis Leroy <jl leroy.nyc> writes:
On Tuesday, 29 September 2020 at 22:36:39 UTC, mw wrote:
 On Tuesday, 29 September 2020 at 22:02:28 UTC, Jean-Louis Leroy 
 wrote:
 On Tuesday, 29 September 2020 at 21:43:03 UTC, mw wrote:
 The key idea is to treat each parent's class attributes 
 individually (via rename/undefine/redefine/select) instead of 
 as in other multiple inheritance languages, e.g. C++'s 
 all-or-none approach, i.e. either all the parents' attributes 
 are shared or separated, and even when separated, there is no 
 proper renaming mechanism to handle it.
If Base has features f and g, and Derived inherits from Base but undefines g, I assume that a Derived object cannot be substituted for a Base. Correct?
It still can; but the Derived now becomes a deferred- (in D's term abstract-) class. because Derived.g becomes a deferred- (in D's term abstract-) method.
Looking at your example, I have the impression that the `addr` "feature" is actually a function. If so, `undefine` in this example is simply the equivalent of tacking a `= 0` after an overridden virtual function in C++ (yes you can inherit an implemented virtual function and make it pure again). But, does this also work on attributes?
 This is the demo:

 https://github.com/mingwugmail/dlang_tour/tree/master/eiffel/mi

 https://github.com/mingwugmail/dlang_tour/blob/master/eiffel/mi/us_resident.e#L3
   undefine addr

 https://github.com/mingwugmail/dlang_tour/blob/master/eiffel/mi/app.e#L17
   create usr.make  -- ****** Warning: addr is a deferred 
 feature in US_RESIDENT.

 https://github.com/mingwugmail/dlang_tour/blob/master/eiffel/mi/app.e#L11
    print_addr(p: PERSON) is do
       io.put_string(p.addr + "%N")
    end



 NOTE: I'm not sure if the SmartEiffel compiler is implemented 
 correctly, it generate warning instead of error, during 
 compilation:

 $ make
 compile  app.e -o app
 ****** Warning: addr is a deferred feature in US_RESIDENT.

 And if you run it, it error out:

 $ ./app
 *** Error at Run Time ***: Deferred routine called.
 4 frames in current stack.


 Ideally, this program shouldn't compile; since it detected that 
 we are trying to create an object of a abstract (deferred) 
 class.


 Hey, just download the SmartEiffel compiler, and try the demo 
 :-) it's all in the same repo:

 https://github.com/mingwugmail/dlang_tour/tree/master/eiffel
Sep 29 2020
next sibling parent Jean-Louis Leroy <jl leroy.nyc> writes:
Aw, sorry for the spurious quoting in my previous message...
Sep 29 2020
prev sibling parent mw <mingwu gmail.com> writes:
On Tuesday, 29 September 2020 at 23:21:19 UTC, Jean-Louis Leroy 
wrote:

 Looking at your example, I have the impression that the `addr` 
 "feature" is actually a function. If so, `undefine` in this 
 example is simply the equivalent of tacking a `= 0` after an 
 overridden virtual function in C++ (yes you can inherit an 
 implemented virtual function and make it pure again). But, does 
 this also work on attributes?
One cannot undefine attributes, but can rename it, so the programmer can specify individually whether each attribute should be either shared or separated. I created a 2nd example on how to handle attributes here: https://github.com/mingwugmail/dlang_tour/blob/master/eiffel/visitor2/visitor.e class VISITOR inherit UK_RESIDENT rename addr as uk_addr make as uk_make end US_RESIDENT rename addr as us_addr make as us_make end PERSON redefine make select make end The generated C-struct is here: https://github.com/mingwugmail/dlang_tour/blob/master/eiffel/visitor2/app.h#L513 struct S30{Tid id;T0* _name;T0* _addr;T0* _us_addr;T0* _uk_addr;}; As you can see after 3-branch-dimond multiple inheritance, the `name` is shared (there is only 1 copy); while there are 3 address attributes in VISITOR.
Sep 29 2020
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 9/29/2020 2:56 AM, Petar Kirov [ZombineDev] wrote:
 I don't have experience with multiple inheritance in Eiffel, but it would be 
 shame that in a language with `static if`, `mixin template`s, `static
foreach`, 
 etc. we can't figure out a way to make it work.
The more interesting question is "is it worthwhile to make it work?" No. Too many paths to implicit conversions (and that's really what MI is) leads to nothing but confusion. (Besides, if we did, we'd break existing code that uses alias this.)
Sep 29 2020
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Sep 29, 2020 at 05:13:31PM -0700, Walter Bright via Digitalmars-d wrote:
 On 9/29/2020 2:56 AM, Petar Kirov [ZombineDev] wrote:
 I don't have experience with multiple inheritance in Eiffel, but it
 would be shame that in a language with `static if`, `mixin
 template`s, `static foreach`, etc. we can't figure out a way to make
 it work.
I betcha you could do it as a library. ;-)
 The more interesting question is "is it worthwhile to make it work?"
 No.
 
 Too many paths to implicit conversions (and that's really what MI is)
 leads to nothing but confusion.
[...] Yeah, after many years of loving to sprinkle alias this everywhere, I'm starting to realize that it's not such a good idea after all. It leads to code that looks like it's correct, but actually it does something else. Give it a few more iterations of refactoring, bugfixes, and feature additions, and the code quickly becomes totally opaque and hard to reason about. Or just plain ugly because the data structures have turned into a Frankenstein monster where sometimes it's type A, sometimes it's type B, and you have to insert random shunts everywhere to interconvert between them where implicit conversion didn't happen automatically. Same thing with C++'s implicit constructions and Koenig lookup. It's clever, it's cool, and super-convenient to use... until you have to debug the code, then all of a sudden you're scratching your head, where on earth is that implicit intermediate type that my argument got silently converted to, and which overload did this call end up in?! Sometimes even the debugger won't help you (the implicit conversion got inlined, so you don't even see the intermediate type, just the wrong result in the target function). Pretty soon, the code becomes write-only, and maintenance costs (time to debug, time to integrate new features, etc.) skyrocket. T -- Winners never quit, quitters never win. But those who never quit AND never win are idiots.
Sep 29 2020
parent reply Jean-Louis Leroy <jl leroy.nyc> writes:
On Wednesday, 30 September 2020 at 00:28:34 UTC, H. S. Teoh wrote:
 On Tue, Sep 29, 2020 at 05:13:31PM -0700, Walter Bright via 
 Digitalmars-d wrote:
 On 9/29/2020 2:56 AM, Petar Kirov [ZombineDev] wrote:
 I don't have experience with multiple inheritance in Eiffel, 
 but it would be shame that in a language with `static if`, 
 `mixin template`s, `static foreach`, etc. we can't figure 
 out a way to make it work.
I betcha you could do it as a library. ;-)
 The more interesting question is "is it worthwhile to make it 
 work?" No.
 
 Too many paths to implicit conversions (and that's really what 
 MI is)
 leads to nothing but confusion.
[...] Yeah, after many years of loving to sprinkle alias this everywhere, I'm starting to realize that it's not such a good idea after all. It leads to code that looks like it's correct, but actually it does something else. Give it a few more iterations of refactoring, bugfixes, and feature additions, and the code quickly becomes totally opaque and hard to reason about. Or just plain ugly because the data structures have turned into a Frankenstein monster where sometimes it's type A, sometimes it's type B, and you have to insert random shunts everywhere to interconvert between them where implicit conversion didn't happen automatically.
Well...at work my team uses C++ multiple inheritance in our main product, which is massively event-oriented and multi-threaded. Not tons of it but where we use it, the alternatives would be more verbose, less readable, slower, more complicated. The couple of cases I have in mind right now involve hierarchies that are orthogonal. There are no diamonds, because they would make no sense at all. So, better code and no headaches. Who could object to this? There is a pattern that I have observed in my 30+ year career, it's not easy to phrase it, but it goes something like this: when I found MI handy, it was usually for mixing independent technical aspects, not so much "modeling the real world". I think that someone mentioned a Button that is both a Drawable and a Clickable. This is the sort of things I have in mind. And if you don't use MI you quickly get a god class that declares dozens of facets, only a few of which are actually implemented in classes scattered across the inheritance tree (think the Microsoft Foundation Classes with its CObject god class). I also have had success with CLOS-like mixins: small bits of implementation that could be combined easily (of course this is in cases where the combination does not change at runtime), resorting in C++ virtual inheritance and the dominance rule. And this time, diamonds were at the core of the design. Again MI felt like a handy way of organizing my code on a local scale, rather than some ground shaking, mind-opening big statement about "the world" that would open the path to magically cost-free endlessly reusable code.
Sep 29 2020
parent reply Mike Parker <aldacron gmail.com> writes:
On Wednesday, 30 September 2020 at 00:57:52 UTC, Jean-Louis Leroy 
wrote:

 There is a pattern that I have observed in my 30+ year career, 
 it's not easy to phrase it, but it goes something like this: 
 when I found MI handy, it was usually for mixing independent 
 technical aspects, not so much "modeling the real world". I 
 think that someone mentioned a Button that is both a Drawable 
 and a Clickable. This is the sort of things I have in mind. And 
 if you don't use MI you quickly get a god class that declares 
 dozens of facets, only a few of which are actually implemented 
 in classes scattered across the inheritance tree (think the 
 Microsoft Foundation Classes with its CObject god class).
I read a game development book[1] years ago where the author was pushing this approach quite strongly, saying he had published several games where it was used. He referred to it as "mixin inheritance". As long as you reserve MI for introducing behaviors into classes and constrain derived "is-a" relationships to a single (preferably shallow) line in the hierarchy, you are less likely to run into problems. [1] https://www.amazon.com/Object-Oriented-Game-Development-Julian-Gold/dp/032117660X
Sep 30 2020
parent reply Abdulhaq <alynch4047 gmail.com> writes:
On Wednesday, 30 September 2020 at 08:44:26 UTC, Mike Parker 
wrote:
 On Wednesday, 30 September 2020 at 00:57:52 UTC, Jean-Louis 
 Leroy wrote:

 I read a game development book[1] years ago where the author 
 was pushing this approach quite strongly, saying he had 
 published several games where it was used. He referred to it as 
 "mixin inheritance". As long as you reserve MI for introducing 
 behaviors into classes and constrain derived "is-a" 
 relationships to a single (preferably shallow) line in the 
 hierarchy, you are less likely to run into problems.

 [1] 
 https://www.amazon.com/Object-Oriented-Game-Development-Julian-Gold/dp/032117660X
Yes this is a well known pattern usually called a mixin class: https://en.wikipedia.org/wiki/Mixin It's a valid use case, but can easily be achieved in other ways.
Sep 30 2020
parent Abdulhaq <alynch4047 gmail.com> writes:
On Wednesday, 30 September 2020 at 10:15:57 UTC, Abdulhaq wrote:
 On Wednesday, 30 September 2020 at 08:44:26 UTC, Mike Parker 
 wrote:
 On Wednesday, 30 September 2020 at 00:57:52 UTC, Jean-Louis 
 Leroy wrote:
Yes this is a well known pattern usually called a mixin class: https://en.wikipedia.org/wiki/Mixin It's a valid use case, but can easily be achieved in other ways.
I just realised, the prevalence of a concept can be measured by the shortness of its wikipedia URL :-) sort of.... Kolmogorov sends his regards
Sep 30 2020
prev sibling next sibling parent 12345swordy <alexanderheistermann gmail.com> writes:
On Wednesday, 30 September 2020 at 00:13:31 UTC, Walter Bright 
wrote:
 On 9/29/2020 2:56 AM, Petar Kirov [ZombineDev] wrote:
 I don't have experience with multiple inheritance in Eiffel, 
 but it would be shame that in a language with `static if`, 
 `mixin template`s, `static foreach`, etc. we can't figure out 
 a way to make it work.
The more interesting question is "is it worthwhile to make it work?" No.
If you want to deprecate/replace alias this, then that is the way to go. Otherwise you find alternatives to implicit conversion. Such as implicit copy constructors that was mention a while back. -Alex
Sep 29 2020
prev sibling parent reply mw <mingwu gmail.com> writes:
On Wednesday, 30 September 2020 at 00:13:31 UTC, Walter Bright 
wrote:
 On 9/29/2020 2:56 AM, Petar Kirov [ZombineDev] wrote:
 I don't have experience with multiple inheritance in Eiffel, 
 but it would be shame that in a language with `static if`, 
 `mixin template`s, `static foreach`, etc. we can't figure out 
 a way to make it work.
The more interesting question is "is it worthwhile to make it work?" No. Too many paths to implicit conversions (and that's really what MI is) leads to nothing but confusion. (Besides, if we did, we'd break existing code that uses alias this.)
I'm fine, if D just stick with single inheritance, just as Java did. But the problem here is (as we discussed many times): currently with multiple interface, (multiple) mixin, (multiple) subtyping, multiple inheritance *has* crept into D *already*, and in a broken way. If we have a *broken* effective multiple inheritance already, why not have a *proper* multiple inheritance instead.
Sep 29 2020
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Wed, Sep 30, 2020 at 01:26:09AM +0000, mw via Digitalmars-d wrote:
[...]
 I'm fine, if D just stick with single inheritance, just as Java did.
 
 But the problem here is (as we discussed many times): currently with
 multiple interface, (multiple) mixin, (multiple) subtyping, multiple
 inheritance *has* crept into D *already*, and in a broken way.
How is multiple interface broken? Java has multiple interfaces. Are you saying that Java is broken? (I wouldn't disagree, but just want to clarify what exactly you mean.) Mixins are not the same thing. They are a way to inject code into an aggregate, but are not directly recognized as subtyping in the sense of inheritance (i.e., it doesn't implicitly convert).
 If we have a *broken* effective multiple inheritance already, why not
 have a *proper* multiple inheritance instead.
This is fallacious. If we have broken feature X, it does not necessarily follow that we must replace it with a non-broken X. Removing X altogether is also a possible solution. T -- The problem with the world is that everybody else is stupid.
Sep 29 2020
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Wednesday, 30 September 2020 at 02:17:37 UTC, H. S. Teoh wrote:
 How is multiple interface broken?
interface A { void foo(); } interface B { void foo(); } class C : A, B { void foo() {} } If there's two interfaces with the same method signature, D merges them by the time you get to the implementation class. You could argue this is irrelevant and not actually broken but like... idk I see the point.
 Java has multiple interfaces. Are you saying that Java is 
 broken?
Yes, Java does it this way too. to implement.
Sep 30 2020
parent reply Paulo Pinto <pjmlp progtools.org> writes:
On Wednesday, 30 September 2020 at 12:34:48 UTC, Adam D. Ruppe 
wrote:
 On Wednesday, 30 September 2020 at 02:17:37 UTC, H. S. Teoh 
 wrote:
 How is multiple interface broken?
interface A { void foo(); } interface B { void foo(); } class C : A, B { void foo() {} } If there's two interfaces with the same method signature, D merges them by the time you get to the implementation class. You could argue this is irrelevant and not actually broken but like... idk I see the point.
 Java has multiple interfaces. Are you saying that Java is 
 broken?
Yes, Java does it this way too. want to implement.
interface Gun { void fire(); } interface Rocket { void fire(); } class Weapon : Gun, Rocket { void fire() {} } void protectMyself(Gun g) { g.fire(); // what did I actually do here? } void defence(Weapon w) { protectMyself(w); } The name might be merged, but semantics aren't the same and sometimes the unexpected happens, that is why Eiffel and .NET languages approach to explicitly state the interface implementations are much better.
Sep 30 2020
parent reply Arafel <er.krali gmail.com> writes:
On 30/9/20 15:37, Paulo Pinto wrote:
 
 interface Gun { void fire(); }
 interface Rocket { void fire(); }
 
 class Weapon : Gun, Rocket { void fire() {} }
 
 void protectMyself(Gun g) {
    g.fire(); // what did I actually do here?
 }
 
 void defence(Weapon w) {
    protectMyself(w);
 }
 
 The name might be merged, but semantics aren't the same and sometimes 
 the unexpected happens, that is why Eiffel and .NET languages approach 
 to explicitly state the interface implementations are much better.
I would say that this design, at least in the example you proposed, is a bit backwards? I think the following looks better: ``` interface Weapon { void fire(); } class Gun : Weapon { void fire() {} } class Rocket : Weapon { void fire() {} } ``` This matches much more the is-a paradigm: a gun is a weapon, a rocket is a weapon, but a weapon is not both a rocket and a gun (well, some weapon might bit, but that most likely would be composition, i.e. a weapon would consist-of a gun and a rocket). That said, this of course doesn't mean that there are cases where a function with the same name might be defined in two interfaces with different semantics: ``` interface I1 { int fun () out (r; r < 0); } interface I2 { int fun () out (r; r > 0); } class C : I1,I2 { int fun () {return /* ??? */;} } ``` Of course, the fact that functions with the same name have different usage is also a bit suspicious, because interfaces should be orthogonal to each other, so I'm not too unhappy that it makes you think twice about it. That's also why I don't care too much about the extra verbosity that Java promotes (in the method names), it makes this much less likely. A.
Sep 30 2020
parent mw <mingwu gmail.com> writes:
On Wednesday, 30 September 2020 at 14:31:56 UTC, Arafel wrote:
 On 30/9/20 15:37, Paulo Pinto wrote:
 
 interface Gun { void fire(); }
 interface Rocket { void fire(); }
 
 class Weapon : Gun, Rocket { void fire() {} }
 
 void protectMyself(Gun g) {
    g.fire(); // what did I actually do here?
 }
 
 void defence(Weapon w) {
    protectMyself(w);
 }
 
 The name might be merged, but semantics aren't the same and 
 sometimes the unexpected happens, that is why Eiffel and .NET 
 languages approach to explicitly state the interface 
 implementations are much better.
I would say that this design, at least in the example you proposed, is a bit backwards? I think the following looks better:
I always hear arguments like this, or something like "I personally never used such language feature and I don't think it should be used like in this scenario ..." In that line of argument (of blaming user for mis-use), C++ could also be a perfect language: you as a user just need to use it in the "right" way. (well, as to the definition of "right", who knows). I think the point is: we are talking about language feature here. If the language provide a feature, then it should anticipate the user will *abuse* it, and still being correct. It's the compiler's job to disallow illegal usage: as long as it's not marked by the compiler as illegal, the language should give programmers freedom to *abuse* any language features, and the compiled program still being correct. This is the case of Eiffel's multiple inheritance (MI). As a side notes: as mentioned, it's a pure OO language, there are occations OO inheritance hierarchy doesn't not make sense conceptually at all, and MI was used there just to bring in some needed functionalities/utilities, you can call that is abusing MI; BUT the compiled program always behave the correct semantics the user wanted. That's a huge achievement. They've set bar so high, I hope and encourage any language designer try to meet this bar as close as possible: (let me repeat) """ It's the compiler's job to disallow illegal usage: as long as it's not marked by the compiler as illegal, the language should give programmers freedom to *abuse* any language features, and the compiled program still being correct. Do NOT blame the user for mis-usage / abuse, as long as executable generated, blame the compiler. """
 That said, this of course doesn't mean that there are cases 
 where a function with the same name might be defined in two 
 interfaces with different semantics:

 ```
 interface I1 {
     int fun () out (r; r < 0);
 }

 interface I2 {
     int fun () out (r; r > 0);
 }

 class C : I1,I2 {
     int fun () {return /* ??? */;}
 }
 ```
Actually, this is a good example of how design-by-contract also need Eiffel-style MI's naming resolution technique, otherwise, you can not even make design-by-contract right.
 Of course, the fact that functions with the same name have 
 different usage is also a bit suspicious, because interfaces
As just said, the user should never be blamed or feel sorry for this. It's the language that should detect such problem and also provide mechanism to allow user resolve the problem.
 should be orthogonal to each other, so I'm not too unhappy that 
 it makes you think twice about it.
Sep 30 2020
prev sibling parent Paulo Pinto <pjmlp progtools.org> writes:
On Monday, 21 September 2020 at 09:35:10 UTC, Ruby The Roobster 
wrote:
 On Monday, 21 September 2020 at 09:29:21 UTC, Tomcruisesmart 
 wrote:
 Hi,
 I'm looking for healthy conversation.
 What are the prominent downsides of the D programming language?
One downside is that classes can't inherit from multiple classes. I know that there is a thing called an interface which a class can inherit more that one of those. Thing is, functions in interfaces have to be abstract. Also, member variables declared in an interface have to be static, and the only member functions that are defined have to be static. Why can't we just inherit from multiple classes?
This is known as Protocol oriented programming and goes back to Objective-C protocols, CLU and Standard ML modules. It is also the basis of ECS heavily used alongside data oriented programming in all major game engines. Ah, and COM/UWP, which have been the main way Windows APIs are made available since Vista, building on top of Longhorn's OOP ABI ideas. Maybe there is a learning path there.
Sep 21 2020
prev sibling next sibling parent IGotD- <nise nise.com> writes:
On Monday, 21 September 2020 at 09:29:21 UTC, Tomcruisesmart 
wrote:
 Hi,
 I'm looking for healthy conversation.
 What are the prominent downsides of the D programming language?
It doesn't distinguish raw and managed pointers which prevents the D language from changing GC algorithms to for example reference counting.
Sep 21 2020
prev sibling next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 9/21/2020 2:29 AM, Tomcruisesmart wrote:
 What are the prominent downsides of the D programming language?
It makes you sad when your employer makes you use another language.
Sep 21 2020
prev sibling next sibling parent reply FeepingCreature <feepingcreature gmail.com> writes:
On Monday, 21 September 2020 at 09:29:21 UTC, Tomcruisesmart 
wrote:
 Hi,
 I'm looking for healthy conversation.
 What are the prominent downsides of the D programming language?
Okay, real talk. D is *incredibly* uneven. When it works well, it works great. When it breaks, it can break in really horrible ways that I can't accurately describe except by referencing Mickens' seminal article on systems programming [1] - that is what it is like, except replace pointers with templates. Parts of the language are outright broken, everyone knows they're broken, this is not documented *anywhere*. Parts of the standard library are not meant to be used. There's replacements that got proposed years ago and are languishing. Key projects that replace Phobos are written by individuals who may or may not reachable for issues. And there *will* be issues - templates can't be unittested completely at the site of definition, because you don't know all the cases you will encounter, so you can't even predict the types of your own variables sensibly. immutable is broken with a good fraction of language and runtime features. shared is broken with another fraction. Synchronized has a hole the size of a truck that is unfixable without pulling in all of shared for no benefit. Incredibly useful DIPs like formatting string literals or named parameters are decided not by any kind of vote system, but by "let's see if anyone says in the thread that they don't like it, and then we won't do it." This leads to horrible DIPs that try to placate those people, which then leads to other people complaining that the DIP doesn't go far enough. There is no winning there, which is why language improvements are either trivial or depend on Walter deciding to just go for it. Dub is the official build manager. Dub is included with the D distro. Dub has an open bug where it simply ignores the selected version when you try to run a binary with dub. Look at the unit-threaded prebuild line. [2] Just ... look at it. Dub has 424 open bugs. Let's not talk about how many open bugs DMD has. You can learn the core of D in an afternoon. You can get a good understanding of D in a month. Coming from C, D really is an incredible logically-designed language, and it's a joy to use. That's not the bad part of learning D. The bad part is the years of picking up the problematic parts, the features to avoid, and the parts that are just silently broken. The bad part is the hours spent exploring "maybe I can do X", getting incredibly close, then failing due to a bug reported in 2012. There's a reason so many D devs run off to develop their own language. D shows you what is possible with C-like languages, then falls short. It ruins you for other languages, but it's too frustrating to really love. Still the best language I know. At least for now, until my current compiler project is off the ground... [1] https://www.usenix.org/system/files/1311_05-08_mickens.pdf [2] https://github.com/atilaneves/unit-threaded search for preBuildCommands
Sep 21 2020
next sibling parent Abdulhaq <alynch4047 gmail.com> writes:
On Monday, 21 September 2020 at 10:55:22 UTC, FeepingCreature 
wrote:
 On Monday, 21 September 2020 at 09:29:21 UTC, Tomcruisesmart 
 wrote:
 Hi,
 I'm looking for healthy conversation.
 What are the prominent downsides of the D programming language?
Okay, real talk. D is *incredibly* uneven. When it works well, it works great. When it breaks, it can break in really horrible ways that I can't accurately describe except by referencing Mickens' seminal article on systems programming [1] - that is what it is like, except replace pointers with templates. Parts of the language are outright broken, everyone knows they're broken, this is not documented *anywhere*. Parts of the standard library are not meant to be used. There's replacements that got proposed years ago and are languishing. Key projects that replace Phobos are written by individuals who may or may not reachable for issues. And there *will* be issues - templates can't be unittested completely at the site of definition, because you don't know all the cases you will encounter, so you can't even predict the types of your own variables sensibly. immutable is broken with a good fraction of language and runtime features. shared is broken with another fraction. Synchronized has a hole the size of a truck that is unfixable without pulling in all of shared for no benefit. Incredibly useful DIPs like formatting string literals or named parameters are decided not by any kind of vote system, but by "let's see if anyone says in the thread that they don't like it, and then we won't do it." This leads to horrible DIPs that try to placate those people, which then leads to other people complaining that the DIP doesn't go far enough. There is no winning there, which is why language improvements are either trivial or depend on Walter deciding to just go for it. Dub is the official build manager. Dub is included with the D distro. Dub has an open bug where it simply ignores the selected version when you try to run a binary with dub. Look at the unit-threaded prebuild line. [2] Just ... look at it. Dub has 424 open bugs. Let's not talk about how many open bugs DMD has. You can learn the core of D in an afternoon. You can get a good understanding of D in a month. Coming from C, D really is an incredible logically-designed language, and it's a joy to use. That's not the bad part of learning D. The bad part is the years of picking up the problematic parts, the features to avoid, and the parts that are just silently broken. The bad part is the hours spent exploring "maybe I can do X", getting incredibly close, then failing due to a bug reported in 2012. There's a reason so many D devs run off to develop their own language. D shows you what is possible with C-like languages, then falls short. It ruins you for other languages, but it's too frustrating to really love. Still the best language I know. At least for now, until my current compiler project is off the ground... [1] https://www.usenix.org/system/files/1311_05-08_mickens.pdf [2] https://github.com/atilaneves/unit-threaded search for preBuildCommands
Head, meet nail. Nail, meet head.
Sep 21 2020
prev sibling next sibling parent reply ag0aep6g <anonymous example.com> writes:
On 21.09.20 12:55, FeepingCreature wrote:
 Okay, real talk.
 
 D is *incredibly* uneven.
 
[... more good stuff ... ]
 
 The bad part is the years of picking up the problematic parts, the 
 features to avoid, and the parts that are just silently broken. The bad 
 part is the hours spent exploring "maybe I can do X", getting incredibly 
 close, then failing due to a bug reported in 2012.
 
 There's a reason so many D devs run off to develop their own language. D 
 shows you what is possible with C-like languages, then falls short. It 
 ruins you for other languages, but it's too frustrating to really love.
 
 Still the best language I know. At least for now, until my current 
 compiler project is off the ground...
So say we all.
Sep 21 2020
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 9/23/20 9:53 AM, FeepingCreature wrote:

 Is ... is this a bot??
I flagged the post. I unfortunately have to flag yours too, because it included the advertisement link. -Steve
Sep 23 2020
prev sibling next sibling parent reply aberba <karabutaworld gmail.com> writes:
On Monday, 21 September 2020 at 10:55:22 UTC, FeepingCreature 
wrote:
 On Monday, 21 September 2020 at 09:29:21 UTC, Tomcruisesmart 
 wrote:
 
 Incredibly useful DIPs like formatting string literals or named 
 parameters are decided not by any kind of vote system, but by 
 "let's see if anyone says in the thread that they don't like 
 it, and then we won't do it." This leads to horrible DIPs that 
 try to placate those people, which then leads to other people 
 complaining that the DIP doesn't go far enough. There is no 
 winning there, which is why language improvements are either 
 trivial or depend on Walter deciding to just go for it.
I'll rather have knowledgeable people make the wrong decision and be responsible for fixing it than a majority of ignorant people vote for a mess no one likes to fix. That's that's a very common situation out there. Even then D is a great language due to the experience and thought that went into it by the initiator and contributors...not by majority vote. .... The rest are ecosystem problems which is not a D specific issue so I'll let go.
Sep 21 2020
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Monday, 21 September 2020 at 11:37:37 UTC, aberba wrote:
 I'll rather have knowledgeable people make the wrong decision 
 and be responsible for fixing it than a majority of ignorant 
 people vote for a mess no one likes to fix.

  That's that's a very common situation out there.
Actually, it isn't. Most languages keep the core language small. The advantage of separating designers from implementors is that you are more likely to overcome the inertia (unwillingness to restructure compiler internals). So overall, you are better off having a well stuctured modular reference compiler and leave the production compiler to someone else ( not involved with language design ).
Sep 22 2020
prev sibling next sibling parent reply Abdulhaq <alynch4047 gmail.com> writes:
On Monday, 21 September 2020 at 10:55:22 UTC, FeepingCreature 
wrote:

 [1] https://www.usenix.org/system/files/1311_05-08_mickens.pdf
Great article I urge people to read it, for somewhat off-topic reasons.
Sep 21 2020
parent visitor <pierredavant gmail.com> writes:
On Monday, 21 September 2020 at 11:58:44 UTC, Abdulhaq wrote:
 On Monday, 21 September 2020 at 10:55:22 UTC, FeepingCreature 
 wrote:

 [1] https://www.usenix.org/system/files/1311_05-08_mickens.pdf
Great article I urge people to read it, for somewhat off-topic reasons.
Delicious !!!
Sep 21 2020
prev sibling next sibling parent Andy Balba <pwplus7 gmail.com> writes:
On Monday, 21 September 2020 at 10:55:22 UTC, FeepingCreature 
wrote:
 On Monday, 21 September 2020 at 09:29:21 UTC, Tomcruisesmart 
 wrote:
 [...]
Okay, real talk. [...]
 [2] https://github.com/atilaneves/unit-threaded search for 
 preBuildCommands
IMO this is D in a nutshell... " D shows you what is possible with C-like languages, then falls short. It ruins you for other languages,.. it's too frustrating (..and time consuming...) to really love."
Sep 21 2020
prev sibling next sibling parent reply Mathias LANG <geod24 gmail.com> writes:
On Monday, 21 September 2020 at 10:55:22 UTC, FeepingCreature 
wrote:
 Dub is the official build manager. Dub is included with the D 
 distro. Dub has an open bug where it simply ignores the 
 selected version when you try to run a binary with dub. Look at 
 the unit-threaded prebuild line. [2] Just ... look at it. Dub 
 has 424 open bugs. Let's not talk about how many open bugs DMD 
 has.

 [...]

 [2] https://github.com/atilaneves/unit-threaded search for 
 preBuildCommands
There's no denying dub needs some love. But for reference, this particular bug has been fixed a couple release ago. And from the upcoming release, all commands support the syntax `packagename[ <version-spec>]`.
Sep 21 2020
parent FeepingCreature <feepingcreature gmail.com> writes:
On Tuesday, 22 September 2020 at 00:05:50 UTC, Mathias LANG wrote:
 On Monday, 21 September 2020 at 10:55:22 UTC, FeepingCreature 
 wrote:
 Dub is the official build manager. Dub is included with the D 
 distro. Dub has an open bug where it simply ignores the 
 selected version when you try to run a binary with dub. Look 
 at the unit-threaded prebuild line. [2] Just ... look at it. 
 Dub has 424 open bugs. Let's not talk about how many open bugs 
 DMD has.

 [...]

 [2] https://github.com/atilaneves/unit-threaded search for 
 preBuildCommands
There's no denying dub needs some love. But for reference, this particular bug has been fixed a couple release ago. And from the upcoming release, all commands support the syntax `packagename[ <version-spec>]`.
Ah, thank you, my apologies.
Sep 21 2020
prev sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Monday, 21 September 2020 at 10:55:22 UTC, FeepingCreature 
wrote:
 Still the best language I know. At least for now, until my 
 current compiler project is off the ground...
What are the key features of your language and what kind of memory management?
Sep 21 2020
parent reply FeepingCreature <feepingcreature gmail.com> writes:
On Tuesday, 22 September 2020 at 06:13:30 UTC, Ola Fosheim 
Grøstad wrote:
 On Monday, 21 September 2020 at 10:55:22 UTC, FeepingCreature 
 wrote:
 Still the best language I know. At least for now, until my 
 current compiler project is off the ground...
What are the key features of your language and what kind of memory management?
Hahaha... Cx (rename pending) is pre-0.0.1. It's self-hosting, but barely. I'm probably still a year out from *having* memory management to speak of. I'm aiming for a sort of "D1 with macros" feature level right now to start. At the moment, the compiler massively leaks memory because I have neither GC nor managed memory; every array append reallocates the entire array. And I'm not even worrying about it, because I have about 66 other TODOs to handle first. Give it time. :) I'll definitely post about it once it's more presentable. Repo is at https://github.com/FeepingCreature/Cx/ in case you want to take a look at it- though note that you can't even build it rn because I don't have a clean solution for the bootstrapping problem, so at the moment the process is just "build the new binary with the old binary" and I'm not sure that all of my commits are even cleanly buildable with the previous commit's binary. If you want to play with it, ping me on irc (feep in #d on freenode) for a C backend dump to bootstrap from. (But to answer your question, I'm vaguely hoping for something semi-rusty with a clean separation of owning and reading references.)
Sep 22 2020
next sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Tuesday, 22 September 2020 at 07:02:15 UTC, FeepingCreature 
wrote:
 management to speak of. I'm aiming for a sort of "D1 with 
 macros" feature level right now to start. At the moment, the 
 compiler massively leaks memory because I have neither GC nor 
 managed memory; every array append reallocates the entire 
 array. And I'm not even worrying about it, because I have about 
 66 other TODOs to handle first.
*nods* I've been pondering about using Python as an (AST-)macro language for a test-bed for language design. There are some upsides (and downsides) to using a well established scripting language for meta-programming.
 I'll definitely post about it once it's more presentable. Repo 
 is at https://github.com/FeepingCreature/Cx/ in case you want 
 to take a look at it- though note that you can't even build it
Thanks! At a glance it looks very similar to D. You seem to keep the class/struct distinction? (I'll look at it more closely when I get more time.)
 (But to answer your question, I'm vaguely hoping for something 
 semi-rusty with a clean separation of owning and reading 
 references.)
Good choice, by «semi-rusty» I hope your intent is to allow low level programming with back pointers can be done in a clean-looking fashion as well.
Sep 22 2020
prev sibling parent reply IGotD- <nise nise.com> writes:
On Tuesday, 22 September 2020 at 07:02:15 UTC, FeepingCreature 
wrote:
 (But to answer your question, I'm vaguely hoping for something 
 semi-rusty with a clean separation of owning and reading 
 references.)
People who ask for required ownership often don't know what they are asking for. If ownership (single of course) is introduced, many data structures will no longer work. Right now one of D's benefits is that many data structures just work out of the box and even with GC. I want a sea of objects, single ownership is way too limiting.
Sep 22 2020
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Tuesday, 22 September 2020 at 09:47:44 UTC, IGotD- wrote:
 People who ask for required ownership often don't know what 
 they are asking for. If ownership (single of course) is 
 introduced, many data structures will no longer work. Right now 
 one of D's benefits is that many data structures just work out 
 of the box and even with GC.

 I want a sea of objects, single ownership is way too limiting.
I believe Microsoft has a research language where ownership is tied to a group of objects. I actually think C++'s model works out ok, when you add custom allocators to the mix. But it would be better if the compiler could ellide allocations or simply avoid calling side-effect-free destructors if the entire (local) allocator pool was released. I also want compiler support for embedded refcounts (shared_ptr is costly). There is no certain way to establish how memory is allocated and released in C++, so that does prevent (analytical) optimization opportunities. The key challenge is really providing some mechanisms that makes memory management, initialization and finalization analytically tractable and providing more optimization opportunities. (I think "provably memory safe" is too expensive in terms of development freedom and time, so ignore that aspect. "Safer" is good enough. "Safe" isn't really needed or realistic.)
Sep 22 2020
next sibling parent reply FeepingCreature <feepingcreature gmail.com> writes:
On Tuesday, 22 September 2020 at 10:00:46 UTC, Ola Fosheim 
Grøstad wrote:
 On Tuesday, 22 September 2020 at 09:47:44 UTC, IGotD- wrote:
 People who ask for required ownership often don't know what 
 they are asking for. If ownership (single of course) is 
 introduced, many data structures will no longer work. Right 
 now one of D's benefits is that many data structures just work 
 out of the box and even with GC.

 I want a sea of objects, single ownership is way too limiting.
... (I think "provably memory safe" is too expensive in terms of development freedom and time, so ignore that aspect. "Safer" is good enough. "Safe" isn't really needed or realistic.)
I concur with this. The point is to make it possible to write good code, not to force you into what I think the way to write good code is. In my experience, 90% of memory allocations are owned by one declaration and only visible inside its lifetime. My dream goal is to have references be "well-behaved" by default - scoped, nonnullable, immutable, nonreferentiable - where each of those can be opted out of as desired. Given such references, it's usually easy to do correct memory management automatically.
Sep 22 2020
parent drug <drug2004 bk.ru> writes:
On 9/22/20 1:23 PM, FeepingCreature wrote:
 (I think "provably memory safe" is too expensive in terms of 
 development freedom and time, so ignore that aspect. "Safer" is good 
 enough. "Safe" isn't really needed or realistic.)
I concur with this. The point is to make it possible to write good code, not to force you into what I think the way to write good code is. In my experience, 90% of memory allocations are owned by one declaration and only visible inside its lifetime. My dream goal is to have references be "well-behaved" by default - scoped, nonnullable, immutable, nonreferentiable - where each of those can be opted out of as desired. Given such references, it's usually easy to do correct memory management automatically.
For example in GUI code widgets reference each other all over the place. Cyclic dependencies are the reason that Rust has no GUI even like dlangui despite Rust community has much more resources. So I totally agree to IGotD: "People who ask for required ownership often don't know what they are asking for."
Sep 22 2020
prev sibling parent reply IGotD- <nise nise.com> writes:
On Tuesday, 22 September 2020 at 10:00:46 UTC, Ola Fosheim 
Grøstad wrote:
 I believe Microsoft has a research language where ownership is 
 tied to a group of objects.

 I actually think C++'s model works out ok, when you add custom 
 allocators to the mix. But it would be better if the compiler 
 could ellide allocations or simply avoid calling 
 side-effect-free destructors if the entire (local) allocator 
 pool was released. I also want compiler support for embedded 
 refcounts (shared_ptr is costly).

 There is no certain way to establish how memory is allocated 
 and released in C++, so that does prevent (analytical) 
 optimization opportunities.

 The key challenge is really providing some mechanisms that 
 makes memory management, initialization and finalization 
 analytically tractable and providing more optimization 
 opportunities.

 (I think "provably memory safe" is too expensive in terms of 
 development freedom and time, so ignore that aspect. "Safer" is 
 good enough. "Safe" isn't really needed or realistic.)
Pony is another language that allows objects cross referencing but just like the Microsoft research language they have something called "regions" in which the objects are allowed to cross reference. In Rust you pretty much are required to use Rc (reference count) + RefCell (runtime bottow checker) for cross references or when there isn't a single ownership. That means that Rust suddenly becomes a garbage collected language + it must track borrow checker in runtime because the compiler cannot know that during compile time. This of course adds overhead code which I would consider in many cases unnecessary.
Sep 22 2020
next sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Tuesday, 22 September 2020 at 10:30:38 UTC, IGotD- wrote:
 Pony is another language that allows objects cross referencing 
 but just like the Microsoft research language they have 
 something called "regions" in which the objects are allowed to 
 cross reference.
Yes, certainly. If an actor is no longer live then all isolated (non-shared memory) objects could be released in one go, like just freeing up the entire pool if that actor did all the local allocations from a single local pool. (I believe Pony to have global garbage collection though.) So the challenge is coming up with protocols that allow library metaprogramming code to communicate to the static analysis what actually is going on. And some very specific requirements that makes behaviour undefined if the protocols are broken has to be established by the language spec in very clear terms. I am not sure how this can be done in detail, but it probably is a research topic that is active (or overlap with current PL research). So one probably should aim low, or at least very focused on known issues, like establishing a protocol that allow swift-like reference counting with optimization, or arena-like allocators where you can just dump the entire arena-pool if all objects allocated from that pool have no destructors that have side-effects outside the pool. Just as an example: a set of graphs where each graph has a separate pool and the compiler can prove that all nodes in a graph is only comping from that graph-local pool. Then destroying that graph should not have to involve destructing nodes in the graph if they don't have side-effects outside the graph. Coming up with a protocol to give the compiler those facts in the best way is a significant challenge and it should also be possible for the library author to aid the static analysis so that the static analysis become more efficient (keep the search more limited). Lots of challenges here, and application authors should ideally not have to deal with this in the main "business" logic of the program. Hopefully it can be contained in libraries.
Sep 22 2020
prev sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Tuesday, 22 September 2020 at 10:30:38 UTC, IGotD- wrote:
 On Tuesday, 22 September 2020 at 10:00:46 UTC, Ola Fosheim 
 Grøstad wrote:
 I believe Microsoft has a research language where ownership is 
 tied to a group of objects.
[...]
 Pony is another language that allows objects cross referencing 
 but just like the Microsoft research language they have 
 something called "regions" in which the objects are allowed to 
 cross reference.
I guess looking at Verona could be useful, they also reference Cyclone, Pony and Rust: https://github.com/microsoft/verona/blob/master/docs/faq.md
Sep 22 2020
prev sibling next sibling parent aberba <karabutaworld gmail.com> writes:
On Monday, 21 September 2020 at 09:29:21 UTC, Tomcruisesmart 
wrote:
 Hi,
 I'm looking for healthy conversation.
 What are the prominent downsides of the D programming language?
Varies from person to person. And that's a real thing. After a while, I tend to see them as trade-offs one has to make to design the language in one way or another. I'm not sure if the questions is strictly related to the language itself or the ecosystem. About the language, I mostly see trade-offs and the rest are yet to be polished out or a work in progress. None of which is a blocker for my use case.
Sep 21 2020
prev sibling next sibling parent reply Paulo Pinto <pjmlp progtools.org> writes:
On Monday, 21 September 2020 at 09:29:21 UTC, Tomcruisesmart 
wrote:
 Hi,
 I'm looking for healthy conversation.
 What are the prominent downsides of the D programming language?
First of all let me say that the community is great, so this is probably what I would state on the upsides thread. On the downsides, getting a clear roadmap actually done, instead of falling to the fallacy of paying to much attention what other languages are doing. Also stating that D did it first hardly helps adoption. Yes there are plenty of language features that D did it first, but now 10 years later since I bought Andrei's book, I have most the richness of their tooling, libraries and eco-systems. And what is still missing from them, happens to be on their roadmaps anyway. Also while everyone keeps arguing about the sense of having a GC or not in a systems language, and in what form, we have languages like Java managing TB heaps with 1ms pauses, and on Android it is even possible to write drivers with their Java flavour if one so wishes (post Treble). While other companies ship devices running bare metal Go, .NET Core and had Unity chosen something like D, they wouldn't be doing Burst compiler nowadays and contributing back some of it into .NET tooling. They managed to achieve this by just keep going at it regardless of the opposition against it. So this is the biggest downside, not having one main pillar to which to create a strong statement of direction where others can gather around, while at the same time stabilizing the features that are still half-way there.
Sep 22 2020
next sibling parent Paolo Invernizzi <paolo.invernizzi gmail.com> writes:
On Tuesday, 22 September 2020 at 07:10:34 UTC, Paulo Pinto wrote:
 On Monday, 21 September 2020 at 09:29:21 UTC, Tomcruisesmart 
 wrote:
 [...]
First of all let me say that the community is great, so this is probably what I would state on the upsides thread. [...]
As usual, +1 on that kind of arguments
Sep 22 2020
prev sibling parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Tuesday, 22 September 2020 at 07:10:34 UTC, Paulo Pinto wrote:
 So this is the biggest downside, not having one main pillar to 
 which to create a strong statement of direction where others 
 can gather around, while at the same time stabilizing the 
 features that are still half-way there.
Yes, but in all fairness, there are just too many general purpose languages today that you need to look at to use specific frameworks. E.g. Typescript/angular, Dart/flutter, Go/Python/Java/google cloud, c++/physics engines, swift/ios... It is becoming difficult to justify investing time into a specific language with no framework attached to it. E.g. the main reason for me spending time with Go is Cloud Functions. If you want to write a game with custom physics you basically cannot avoid C++ (on the same budget). To stand out you might have to target something specific like wasm or arduino. Basically be the best option for something narrow.
Sep 22 2020
prev sibling next sibling parent James Lu <jamtlu gmail.com> writes:
On Monday, 21 September 2020 at 09:29:21 UTC, Tomcruisesmart 
wrote:
 Hi,
 I'm looking for healthy conversation.
 What are the prominent downsides of the D programming language?
The compiler error messages are sometimes cryptic The compilers sometimes crash You spend more time to start using APIs intended for C++ It doesn't compile to machine code as fast as JavaScript
Sep 22 2020
prev sibling next sibling parent JN <666total wp.pl> writes:
On Monday, 21 September 2020 at 09:29:21 UTC, Tomcruisesmart 
wrote:
 Hi,
 I'm looking for healthy conversation.
 What are the prominent downsides of the D programming language?
- templates, meaning a lot of code is generated only at compile time, meaning D will never have the IDE support and refactoring messages when things go wrong. - multiple personality disorder memory management - one day D is a GC language, then it's actually going away from GC towards ref counting, then it's actually towards a borrow checker, hard to keep up and the ecosystem suffers - many features interact with each other in weird ways. Just look at any recent language improvement DIP, those are always postponed because the code in some obscure scenario breaks
Sep 22 2020
prev sibling next sibling parent reply ddcovery <antoniocabreraperez gmail.com> writes:
On Monday, 21 September 2020 at 09:29:21 UTC, Tomcruisesmart 
wrote:
 Hi,
 I'm looking for healthy conversation.
 What are the prominent downsides of the D programming language?
As a not D experienced developer (I use rdmd, small game projects and I tried to use as REST service instead play/scala or node/javascript) Not directly related with DLang but with Development tools: * Intelligence / autocomplete lack: The use of meta-programming makes it very difficult and really represents a barrier for its incorporation in productive mainstream development (it's funny: we have GC, not good for system/video game developers, but then it makes autocomplete impossible, not good for web services mainstream developers ). * Inspecting vars while debugging: Why it is so difficult to inspect not trivial vars?. I'm using dlangide, simple and very powerful, but it is hell to inspect variables (especially objects): I have to be defining local variables and assigning object properties to them in order to see their values ​​in the debugger. * The "auto" Swiss knife: Yes, I know, "auto" is a powerful tool, but DLang libraries tends to force you to use auto because metaprogramming... it is really difficult to a newcomers to understand the Type returned by a template... and templates are everywhere. i.e.: If you read about Tasks (https://dlang.org/phobos/std_parallelism.html), for me is not obvious how to define an empty array of tasks. Imagine I have a "4 in a line" game and I want to evaluate with a thread each column of the game (a minimax algorithm)
 ??? tasks = [];
 for( int ixTask=0; ix<COLUMNS; ixTask++){
   tasks ~= task!evalColumn(board.clone(), columns[ixTask], 
 maxRecursion - 1);
   tasks[ixTask].executeInNewThread();
 }
 ...
What do you have to place instead "???"
Sep 29 2020
next sibling parent ddcovery <antoniocabreraperez gmail.com> writes:
On Tuesday, 29 September 2020 at 11:10:42 UTC, ddcovery wrote:
 On Monday, 21 September 2020 at 09:29:21 UTC, Tomcruisesmart 
 wrote:
 Hi,
 I'm looking for healthy conversation.
 What are the prominent downsides of the D programming language?
As a not D experienced developer (I use rdmd, small game projects and I tried to use as REST service instead play/scala or node/javascript) Not directly related with DLang but with Development tools: * Intelligence / autocomplete lack: The use of meta-programming makes it very difficult and really represents a barrier for its incorporation in productive mainstream development (it's funny: we have GC, not good for system/video game developers, but then it makes autocomplete impossible, not good for web services mainstream developers ). * Inspecting vars while debugging: Why it is so difficult to inspect not trivial vars?. I'm using dlangide, simple and very powerful, but it is hell to inspect variables (especially objects): I have to be defining local variables and assigning object properties to them in order to see their values ​​in the debugger. * The "auto" Swiss knife: Yes, I know, "auto" is a powerful tool, but DLang libraries tends to force you to use auto because metaprogramming... it is really difficult to a newcomers to understand the Type returned by a template... and templates are everywhere. i.e.: If you read about Tasks (https://dlang.org/phobos/std_parallelism.html), for me is not obvious how to define an empty array of tasks. Imagine I have a "4 in a line" game and I want to evaluate with a thread each column of the game (a minimax algorithm)
 ??? tasks = [];
 for( int ixTask=0; ix<COLUMNS; ixTask++){
   tasks ~= task!evalColumn(board.clone(), columns[ixTask], 
 maxRecursion - 1);
   tasks[ixTask].executeInNewThread();
 }
 ...
What do you have to place instead "???"
Basically, the most powerful features of the language (templates/metaprograming/compile time execution) are the barrier to be introduced in the ecosystem of mainstream programming (easy debugging, autocomplete/intelligence, simple typing system), and the only feature mainstream development embraces (GC) is hated by the people that comes from C/C++ (system/game developers). That said, I like D ... I love it's plasticity, it's versatility ... and it's GC :D
Sep 29 2020
prev sibling parent reply FeepingCreature <feepingcreature gmail.com> writes:
On Tuesday, 29 September 2020 at 11:10:42 UTC, ddcovery wrote:
 * The "auto" Swiss knife:  Yes, I know, "auto" is a powerful 
 tool, but DLang libraries tends to force you to use auto 
 because metaprogramming... it is really difficult to a 
 newcomers to understand the Type returned by a template... and 
 templates are everywhere.

 i.e.:  If you read about Tasks 
 (https://dlang.org/phobos/std_parallelism.html), for me is not 
 obvious how to define an empty array of tasks.

 Imagine I have a "4 in a line" game and I want to evaluate with 
 a thread each column of the game (a minimax algorithm)

 ??? tasks = [];
 for( int ixTask=0; ix<COLUMNS; ixTask++){
   tasks ~= task!evalColumn(board.clone(), columns[ixTask], 
 maxRecursion - 1);
   tasks[ixTask].executeInNewThread();
 }
 ...
What do you have to place instead "???"
I mean, you could do this: auto tasks = COLUMNS.iota.map!(ixTask => task!evalColumn(board.clone(), columns[ixTask], maxRecursion - 1)).array; tasks.each!"a.executeInNewThread";
Sep 29 2020
parent reply ddcovery <antoniocabreraperez gmail.com> writes:
On Tuesday, 29 September 2020 at 11:35:02 UTC, FeepingCreature 
wrote:
 On Tuesday, 29 September 2020 at 11:10:42 UTC, ddcovery wrote:
 * The "auto" Swiss knife:  Yes, I know, "auto" is a powerful 
 tool, but DLang libraries tends to force you to use auto 
 because metaprogramming... it is really difficult to a 
 newcomers to understand the Type returned by a template... and 
 templates are everywhere.

 i.e.:  If you read about Tasks 
 (https://dlang.org/phobos/std_parallelism.html), for me is not 
 obvious how to define an empty array of tasks.

 Imagine I have a "4 in a line" game and I want to evaluate 
 with a thread each column of the game (a minimax algorithm)

 ??? tasks = [];
 for( int ixTask=0; ix<COLUMNS; ixTask++){
   tasks ~= task!evalColumn(board.clone(), columns[ixTask], 
 maxRecursion - 1);
   tasks[ixTask].executeInNewThread();
 }
 ...
What do you have to place instead "???"
I mean, you could do this: auto tasks = COLUMNS.iota.map!(ixTask => task!evalColumn(board.clone(), columns[ixTask], maxRecursion - 1)).array; tasks.each!"a.executeInNewThread";
Hi FeepingCreature, But "auto" remains :-D.
Sep 29 2020
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 9/29/20 8:39 AM, ddcovery wrote:
 On Tuesday, 29 September 2020 at 11:35:02 UTC, FeepingCreature wrote:
 On Tuesday, 29 September 2020 at 11:10:42 UTC, ddcovery wrote:
 * The "auto" Swiss knife:  Yes, I know, "auto" is a powerful tool, 
 but DLang libraries tends to force you to use auto because 
 metaprogramming... it is really difficult to a newcomers to 
 understand the Type returned by a template... and templates are 
 everywhere.

 i.e.:  If you read about Tasks 
 (https://dlang.org/phobos/std_parallelism.html), for me is not 
 obvious how to define an empty array of tasks.

 Imagine I have a "4 in a line" game and I want to evaluate with a 
 thread each column of the game (a minimax algorithm)

 ??? tasks = [];
 for( int ixTask=0; ix<COLUMNS; ixTask++){
   tasks ~= task!evalColumn(board.clone(), columns[ixTask], 
 maxRecursion - 1);
   tasks[ixTask].executeInNewThread();
 }
 ...
What do you have to place instead "???"
I mean, you could do this: auto tasks = COLUMNS.iota.map!(ixTask => task!evalColumn(board.clone(), columns[ixTask], maxRecursion - 1)).array; tasks.each!"a.executeInNewThread";
Hi FeepingCreature, But "auto" remains :-D.
You don't like auto? pragma(msg, typeof(tasks[]); now, go back in and replace tasks[] type with whatever that says. Swift is 99% type inference. It's strongly typed, and you almost never see a type declaration. You *can* type it, but there's no need. People get along swimmingly without having to specify types. It also makes your code much more robust. -Steve
Sep 29 2020
next sibling parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Tuesday, 29 September 2020 at 13:01:54 UTC, Steven 
Schveighoffer wrote:
 there's no need. People get along swimmingly without having to 
 specify types. It also makes your code much more robust.
I like type inference and flow typing, but it does not make code more robust. Specifying twice makes code more robust. This is basically the principle in verifiable computing, you provide two descriptions of what your code should do and then the check that they line up statically.
Sep 29 2020
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 9/29/20 9:07 AM, Ola Fosheim Grøstad wrote:
 On Tuesday, 29 September 2020 at 13:01:54 UTC, Steven Schveighoffer wrote:
 there's no need. People get along swimmingly without having to specify 
 types. It also makes your code much more robust.
I like type inference and flow typing, but it does not make code more robust. Specifying twice makes code more robust.
If you decide to change your type from e.g. int to long, then you don't need to go edit all the places you declared things. Just works. I supposed I should have said more generic. -Steve
Sep 29 2020
parent Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Tuesday, 29 September 2020 at 14:14:34 UTC, Steven 
Schveighoffer wrote:
 If you decide to change your type from e.g. int to long, then 
 you don't need to go edit all the places you declared things.
Yes, when are certain you understand the code, but it can sometimes prevent understanding. E.g. if th hidden type is some form of ownership then it is very helpful to see the explicit type. Of course an IDE can help here... Depends on the setup/project I guess.
Sep 29 2020
prev sibling parent reply ddcovery <antoniocabreraperez gmail.com> writes:
On Tuesday, 29 September 2020 at 13:01:54 UTC, Steven 
Schveighoffer wrote:

 You don't like auto?

 pragma(msg, typeof(tasks[]);

 now, go back in and replace tasks[] type with whatever that 
 says.

 Swift is 99% type inference. It's strongly typed, and you 
 almost never see a type declaration. You *can* type it, but 
 there's no need. People get along swimmingly without having to 
 specify types. It also makes your code much more robust.

 -Steve
Hi Steve, I agree, I really appreciate your point and I understand it is difficult to an experienced D developer to understand my point. My "difficulty" (I assume it is my problem) is when reading documentation about methods returning "auto"... it's hard, at the beginning, to transform this mentally in something I can understand (trying not to hide mentally the information)... D plasticity differs to other simplest "generics" type systems (like Scala) and you need double effort to understand it. An added difficulty (that I don't know if the "swift developers" will suffer with xcode) is the missing of a good "autocomplete" or "type inference" that helps developers to understand the type that an "auto" function is really returning in the context of an evocation (i.e.: Right now, I am working with flutter/dart and vscode shows me the inferred type of a variable when hovering with the mouse).
Sep 29 2020
next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Sep 29, 2020 at 03:35:42PM +0000, ddcovery via Digitalmars-d wrote:
[...]
 My "difficulty" (I assume it is my problem) is when reading
 documentation about methods returning "auto"... it's hard, at the
 beginning, to transform this mentally in something I can understand
 (trying not to hide mentally the information)... D plasticity differs
 to other simplest "generics" type systems (like Scala) and you need
 double effort to understand it.
IMO, this is more a problem with the documentation than with `auto` itself. The documentation really should be stating exactly what you can / cannot do with the returned object. But beyond that, a function that returns `auto` really means "the return type is not important to be able to use this function", and by extension, "you really shouldn't need to know what the concrete type is; if you do, you're probably using this function wrong". This is where it's extremely important for the docs to be as clear as possible about what you can do with the opaque return value.
 An added difficulty  (that I don't know if the "swift developers" will
 suffer with xcode) is the missing of a good "autocomplete" or "type
 inference" that helps developers to understand the type that an "auto"
 function is really returning in the context of an evocation (i.e.:
 Right now, I am working with flutter/dart and vscode shows me the
 inferred type of a variable when hovering with the mouse).
[...] This is a tooling problem; if an issue hasn't been filed already, it should be filed so that this can be improved. Technically speaking, it's just a matter of inserting `pragma(msg, typeof(return));` into the function; but of course if this were automated by an IDE plugin that would be ideal. Note that knowing the concrete type may or may not help you always; sometimes the concrete type may be a complex internal implementation type that may be even harder to understand than reading properly-written docs. :-P Or sometimes it's a Voldemort type with a generic name like `Result` that doesn't really give you very much information (the point being, if the function was designed properly and used properly, you should not need to care what the actual type is). T -- Ignorance is bliss... until you suffer the consequences!
Sep 29 2020
prev sibling parent reply James Blachly <james.blachly gmail.com> writes:
On 9/29/20 11:35 AM, ddcovery wrote:
 Hi Steve,
 
 I agree, I really appreciate your point and I understand it is difficult 
 to an experienced D developer to understand my point.
 
 My "difficulty" (I assume it is my problem) is when reading 
 documentation about methods returning "auto"... it's hard, at the 
 beginning, to transform this mentally in something I can understand 
 (trying not to hide mentally the information)... D plasticity differs to 
 other simplest "generics" type systems (like Scala) and you need double 
 effort to understand it.
 
 An added difficulty  (that I don't know if the "swift developers" will 
 suffer with xcode) is the missing of a good "autocomplete" or "type 
 inference" that helps developers to understand the type that an "auto" 
 function is really returning in the context of an evocation (i.e.: Right 
 now, I am working with flutter/dart and vscode shows me the inferred 
 type of a variable when hovering with the mouse).
 
I am not NEW NEW, but new enough that I remember precisely the feeling you are describing; you are right on with respect to one of the hardest mental barriers in the D learning curve. This [`auto` being used to simplify complex return types; and the notion of potentially very complex template-generated return types in general, especially as a componetn of the stdlib] is something that I think would improve visibility and adoption if it were explicitly addressed in tutorials, documentation, books, etc.
Sep 29 2020
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Sep 29, 2020 at 12:52:30PM -0400, James Blachly via Digitalmars-d wrote:
[...]
 This [`auto` being used to simplify complex return types; and the
 notion of potentially very complex template-generated return types in
 general, especially as a componetn of the stdlib] is something that I
 think would improve visibility and adoption if it were explicitly
 addressed in tutorials, documentation, books, etc.
Yeah, this needs to be addressed head-on, rather than skirted around or deferred to the reference docs. I think a lot of newcomers to D wouldn't have the concept of opaque types that they don't need to know explicitly yet can use effectively. That's a pretty advanced concept rarely found in other languages; it would do a lot of good to explain this concept right from the get-go. T -- The most powerful one-line C program: #include "/dev/tty" -- IOCCC
Sep 29 2020
parent Arafel <er.krali gmail.com> writes:
On 29/9/20 19:20, H. S. Teoh wrote:
 On Tue, Sep 29, 2020 at 12:52:30PM -0400, James Blachly via Digitalmars-d
wrote:
 [...]
 This [`auto` being used to simplify complex return types; and the
 notion of potentially very complex template-generated return types in
 general, especially as a componetn of the stdlib] is something that I
 think would improve visibility and adoption if it were explicitly
 addressed in tutorials, documentation, books, etc.
Yeah, this needs to be addressed head-on, rather than skirted around or deferred to the reference docs. I think a lot of newcomers to D wouldn't have the concept of opaque types that they don't need to know explicitly yet can use effectively. That's a pretty advanced concept rarely found in other languages; it would do a lot of good to explain this concept right from the get-go. T
I think this is an area were "concepts" [1] would shine. It would be cool if there were some kind of "statically typed interface" that you would declare as a type, exposing the needed functionality, and that would hide the implementation details. Something like this (AIUI the UDA makes possible even to leave out `auto`): ``` models!(isInputRange) foo = ....; // Very long UCFS chain. ``` This would tell you all that you should reasonably need to know about the type, while still allowing lower level access if needed, because the actual type would remain unchanged. Also, it would statically check that the guarantees are kept, i.e. that if a template is supposed to return an input range, it actually does without some corner case silently breaking `empty`, for instance. It would be great then if the IDE tools could make use of this, and even more to have a more compact syntax built-in into the language. A. [1]: https://code.dlang.org/packages/concepts
Sep 29 2020
prev sibling parent reply Dukc <ajieskola gmail.com> writes:
On Monday, 21 September 2020 at 09:29:21 UTC, Tomcruisesmart 
wrote:
 Hi,
 I'm looking for healthy conversation.
 What are the prominent downsides of the D programming language?
-There tends to be a need to switch between compiler versions. Sometimes one may even have to use two different versions for the same project. -Typical D projects tend to require compiling everything at once. The main reason this is a problem is that you can't use different compiler flags for different parts. It's no worse than on the mainstream object oriented languages, though. -Heavy use of templates still worsens error messages. They are clear enough that an average programmer won't, in general, hit the wall. But it tends to require several attempts and/or reading the docs to fix template-related errors, as opposed to untemplated error messages like: "function call `serialize` not found, did you mean `serialise`?". -Using templates and defining simple ones is easy and tidy. But defining really good templates tends to get difficult. Look at Phobos source code: complex template constraints. The most recent D blog entry give a good taste of what it's like. On the other hand, in other languages you'd have to resort to macros to do similar stuff at all... -Expressing complex data, especially if it's dynamically typed (at least out of the box, without third party libraries). D tends to be good at processing data but not so good in initializing it. Unit tests tend to get longer than I'd imagine them being in Lua or JavaScript.
Sep 29 2020
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Sep 29, 2020 at 04:11:29PM +0000, Dukc via Digitalmars-d wrote:
[...]
 -Using templates and defining simple ones is easy and tidy. But
 defining really good templates tends to get difficult. Look at Phobos
 source code: complex template constraints.
[...] IMO, overly-complex and opaque sig constraints is a sign that the template was not properly designed. A lot of the complex constraints in Phobos leak implementation details and really should belong in static ifs inside the function body. This malady is often accompanied by an excessive number of overloads of the template function, many of which have no obvious reason why they are separate overloads, the reason having to do with implementation details that the user really shouldn't need to see or know about. Properly-written sig constraints should be very straightforward and simple to understand -- it should accept all types in the class of logically-acceptable types. Any types in that class that cannot be accepted due to implementation details or case-specific reasons really should be handled by static asserts in the function body, accompanied by a message explaining why that type cannot be used -- rather than obscure, unreadably complex sig constraints that, when they fail, generate equally obscure, unreadably-long template-not-matched error messages. T -- Those who've learned LaTeX swear by it. Those who are learning LaTeX swear at it. -- Pete Bleackley
Sep 29 2020
parent reply Per =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Tuesday, 29 September 2020 at 16:57:52 UTC, H. S. Teoh wrote:
 Look at Phobos source code: complex template constraints.
[.> IMO, overly-complex and opaque sig constraints is a sign that the template was not properly designed. A lot of the complex constraints in Phobos leak
Agreed. This will benefit compile times aswell.
Sep 29 2020
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Sep 29, 2020 at 05:08:17PM +0000, Per Nordlöw via Digitalmars-d wrote:
 On Tuesday, 29 September 2020 at 16:57:52 UTC, H. S. Teoh wrote:
 Look at Phobos source code: complex template constraints.
[.> IMO, overly-complex and opaque sig constraints is a sign that the template was not properly designed. A lot of the complex constraints in Phobos leak
Agreed. This will benefit compile times aswell.
I doubt it will benefit compile times (evaluating sig constraints vs static ifs pretty much make no difference to the compiler), but at least it will make Phobos templates more user-friendly! T -- The fact that anyone still uses AOL shows that even the presence of options doesn't stop some people from picking the pessimal one. - Mike Ellis
Sep 29 2020