digitalmars.D - new DIP47: Outlining member functions of aggregates
- Walter Bright (4/4) Sep 07 2013 Outlining of member functions is the practice of placing the declaration...
- Jos van Uden (6/8) Sep 07 2013 The problem is that it is optional, so when you're reading other people'...
- Iain Buclaw (11/23) Sep 07 2013 There's no problem here then!
- Adam D. Ruppe (2/3) Sep 07 2013 Or just run dmd -H over it.
- Paolo Invernizzi (4/20) Sep 07 2013 No pun intended, but having it as _mandatory_ would be a little
- Walter Bright (2/4) Sep 07 2013 There's no way it would be mandatory.
- Jos van Uden (4/18) Sep 07 2013 Exactly, so we're adding a lot of code noise, while you still have to us...
- deadalnix (5/21) Sep 07 2013 So the problem is that you need a *basic* editor to make other
- H. S. Teoh (31/45) Sep 07 2013 This in itself is a pretty strong argument against this DIP. It
- Dmitry Olshansky (21/25) Sep 07 2013 7. Outlined member function return types, parameter types, and function
- Dmitry Olshansky (9/15) Sep 07 2013 Not to mention poor motivation. A huge paragraph that basically states
- Timon Gehr (22/35) Sep 07 2013 I don't think that the official rationale should include 'readability',
- Jonas Drewsen (4/5) Sep 07 2013 I think we should be conservative and require that parameter
- Iain Buclaw (14/18) Sep 07 2013 What about the absence of parameter names in the declaration?
- Andrej Mitrovic (40/41) Sep 07 2013 Am I correct to say that such member definitions will have the same
- Walter Bright (3/5) Sep 07 2013 Yes. This proposal does not add the outlined function name to any other ...
- Andrej Mitrovic (27/30) Sep 07 2013 I disagree with this, because it will practically guarantee that
- Walter Bright (11/41) Sep 07 2013 How a function is to be *used* should be all there in the *declaration*....
- Andrej Mitrovic (23/26) Sep 07 2013 I mean the *header* part of the function's definition (everything up
- Andrej Mitrovic (3/4) Sep 07 2013 I meant if 'val' in the parameter list in the outlined function always
- Andrej Mitrovic (3/5) Sep 07 2013 This is an unnecessary restriction. You haven't provided any reason in
- Andrej Mitrovic (22/23) Sep 07 2013 Your example code:
- Walter Bright (6/29) Sep 07 2013 Because I wanted to point out that you didn't need to put the 'static' i...
- Meta (6/8) Sep 08 2013 Let me be the first, then, to formally lodge my complaint.
- Maxim Fomin (9/14) Sep 07 2013 Many details were ommited. Just some of them, others were raised.
- Walter Bright (4/17) Sep 07 2013 No.
- Maxim Fomin (7/12) Sep 07 2013 By the way, what is the ratio implemented DIPS/total DIPS? I
- Walter Bright (3/7) Sep 07 2013 Even if they are unimplemented, the same ideas crop up repeatedly. The D...
- Adam D. Ruppe (16/16) Sep 07 2013 Like I said in Manu's thread, we can actually do this already,
- Andrej Mitrovic (7/9) Sep 07 2013 It's cute, but it it doesn't allow you to e.g. implement constructors
- Daniel Murphy (15/19) Sep 07 2013 I am strongly opposed to this DIP. I think it brings a little slice of ...
- Joakim (3/33) Sep 07 2013 This generated documentation solution seems like the best
- Brian Schott (5/10) Sep 07 2013 It's this post again:
- Jonathan M Davis (29/34) Sep 07 2013 I confess that I really don't like this idea. I think that the separatio...
- Walter Bright (5/8) Sep 07 2013 I'll point out that C++ has equivalent behavior, and it has not resulted...
- Peter Williams (9/19) Sep 07 2013 Here's one. It's one of the things that I don't like about C/C++ as it
- Walter Bright (2/4) Sep 07 2013 I believe that is covered in the "Rationale" section of the dip.
- Paolo Invernizzi (24/29) Sep 08 2013 IMHO the rationale of the proposal il pretty weak:
- Peter Williams (6/11) Sep 08 2013 Couldn't see a rational answer to my question in the rationale.
- Volcz (5/33) Sep 09 2013 I completely agree with Jonathan!
- dennis luehring (7/11) Sep 07 2013 "Parameter names need not match."
- Iain Buclaw (17/26) Sep 07 2013 it at
- dennis luehring (7/35) Sep 07 2013 im talking about "Parameter names need not match."
- Iain Buclaw (10/59) Sep 07 2013 I was talking about "Parameter names need not match" too... I disagree
- dennis luehring (6/17) Sep 08 2013 i work as a independed refactorig/bug hunter developer on big team (30+
- Jonathan M Davis (5/13) Sep 07 2013 Agreed. If we're going to do this, let's not allow the possibility of
- Jonathan M Davis (6/11) Sep 07 2013 Actually, for those who really want this sort of thing, why don't they j...
- Dmitry Olshansky (6/17) Sep 08 2013 And speaking of IDEs, they easily grow a simple feature - press some
- Martin Nowak (4/6) Sep 09 2013 Because this is a prerequisite to do so.
- Lionello Lunesu (6/10) Sep 07 2013 I would restrict it to a single module for the time being.
- Ramon (21/26) Sep 07 2013 I'm against that.
- Brian Schott (13/18) Sep 07 2013 "Parameter names need not match."
- Namespace (3/3) Sep 08 2013 I'm against it. More important than such a gimmick are the many
- Michael (2/5) Sep 08 2013 +1
- Tove (17/22) Sep 08 2013 I strongly dislike DIP47, I found many unintended discrepancies
- Tove (19/19) Sep 08 2013 Wouldn't this style be an acceptable compromise instead? with
- Simen Kjaeraas (6/25) Sep 08 2013 The problem here is the compiler does not enforce that all
- Robert Schadek (2/4) Sep 08 2013 +1
- nazriel (15/20) Sep 08 2013 +1
- Michel Fortin (54/60) Sep 08 2013 About placing the definition in another module, you say that the
- Andrej Mitrovic (2/4) Sep 08 2013 This is actually what Andrei proposed as well.
- deadalnix (3/8) Sep 08 2013 +42
- Dicebot (2/11) Sep 08 2013 That is why I had a feeling I have already seen it somewhere :)
- Andrei Alexandrescu (59/63) Sep 08 2013 I have to say I was a lot more in favor of the proposal before this thre...
- Paulo Pinto (5/70) Sep 09 2013 The approach should be like in Modula-2 family, only public stuff is
- Walter Bright (5/10) Sep 09 2013 One solution that has been proposed here (by Manu and perhaps others) is...
- Andrei Alexandrescu (4/19) Sep 09 2013 It also reduces the motivation for the thing as it becomes a minor
- Walter Bright (2/5) Sep 09 2013 Yup.
- Michel Fortin (17/21) Sep 09 2013 Is the D module system file-granular or module-granular? I always
- H. S. Teoh (8/28) Sep 09 2013 [...]
- Joseph Rushton Wakeling (5/14) Sep 10 2013 Is it possible to manually craft some parts of the .di file, while being...
- Dmitry Olshansky (6/45) Sep 08 2013 Same here. This was the ugliest point.
- Ettienne Gilbert (4/24) Sep 08 2013 [Snip]
- Gary Willoughby (32/37) Sep 08 2013 I'm absolutely against this DIP.
- Dicebot (12/18) Sep 08 2013 It has nothing to do with header files. Or real header file
- Dicebot (3/3) Sep 08 2013 P.S. In general I'd love to have feature feature proposed in
- Gary Willoughby (25/37) Sep 08 2013 Well you've just argued against your first paragraph there. The
- Paulo Pinto (9/46) Sep 08 2013 Not only Java and C#, but any other language with module support, even
- Dicebot (40/67) Sep 08 2013 Not really. Issue is cognitive load of matching definition and
- Gary Willoughby (6/13) Sep 08 2013 This is a job for the *documentation* and if documentation is
- Dicebot (17/22) Sep 08 2013 Documentation is tool to help with cross-project learning. I have
- H. S. Teoh (27/37) Sep 08 2013 [...]
- Dicebot (14/19) Sep 09 2013 Yes, that should be superior approach in general though exact
- PauloPinto (6/26) Sep 09 2013 In languages like Modula-2, it is a compile error if there are
- H. S. Teoh (21/50) Sep 09 2013 I'd propose to make it such that you *don't* have to tweak the .di
- Paulo Pinto (7/55) Sep 09 2013 I should have read your earlier post better.
- QAston (4/35) Sep 08 2013 I totally agree (stating this just in case number of votes
- Peter Williams (3/38) Sep 08 2013 Well said.
- Simen Kjaeraas (63/67) Sep 08 2013 I like the idea, but I feel the DIP is missing some info:
- Jesse Phillips (41/46) Sep 08 2013 I am against this proposal. The rationale does not convince me we
- Andrej Mitrovic (3/6) Sep 08 2013 FWIW I don't think this has anything to do with Remedy (afaik Manu
- Jesse Phillips (8/15) Sep 09 2013 I did not realize he had left, but I did realize he was speaking
- Manu (12/18) Sep 08 2013 Indeed. These opinions are my own, and I raised it on the merit of our
- PauloPinto (3/34) Sep 08 2013 Game developers embracing Erlang, C#, Java and ActionScript don't
- Paolo Invernizzi (16/35) Sep 08 2013 I don't believe that typical. We are working with some very big
- w0rp (3/3) Sep 08 2013 I'm opposed to this DIP. It's aimed solely at aiding readability,
- Manu (73/77) Sep 08 2013 Missed the action...
- deadalnix (18/25) Sep 08 2013 I think that you guys being experienced C++ devs makes it worse.
- FrogLegs (2/2) Sep 08 2013 This seems like a waste of time compared to the other complaints
- Ramon (35/35) Sep 08 2013 Manu has pointed to some issue behind the obvious issue that will
- Ramon (6/6) Sep 08 2013 Correction (3rd paragraph)
- Joseph Rushton Wakeling (5/9) Sep 09 2013 Correct me if I'm wrong, but isn't the problem of using
- Jacob Carlborg (17/23) Sep 09 2013 So what's wrong with this approach, that's already working today:
- deadalnix (3/29) Sep 09 2013 This is super useful to generate boilerplate from compile time
- Manu (2/35) Sep 09 2013 Which is what I requested it for, and use it very extensively.
- Jacob Carlborg (4/5) Sep 09 2013 Doesn't this already solve what this DIP47 is trying to solve?
- Joseph Rushton Wakeling (2/3) Sep 09 2013 See the objection given in my reply to Daniel Murphy.
- Daniel Murphy (5/29) Sep 09 2013 Whoa, I didn't think of applying that to member functions. This seems l...
- Joseph Rushton Wakeling (17/45) Sep 09 2013 Problem -- what about:
- Ettienne Gilbert (21/45) Sep 09 2013 [snip]
- Joseph Rushton Wakeling (51/66) Sep 09 2013 AFAICS the request is for separation of declaration and definition, so y...
- Ettienne Gilbert (26/114) Sep 09 2013 Ahh, ok. I see where you are coming from - you were evaluating
- Joseph Rushton Wakeling (36/55) Sep 09 2013 The code that Jacob proposed is currently legit D code and that isn't go...
- Jacob Carlborg (5/10) Sep 10 2013 That shouldn't be necessary, see my reply to Andrej:
- Jacob Carlborg (4/10) Sep 10 2013 Yes, my suggestion would be an alternative to DIP47.
- Jonathan M Davis (6/62) Sep 09 2013 Walter's proposal would be no different on that count. All that the DIP ...
- Joseph Rushton Wakeling (9/13) Sep 09 2013 Sure. The thing is that if you can only declare and define within the c...
- Andrej Mitrovic (14/17) Sep 09 2013 You could use compile-time introspection where the API would look like:
- Jacob Carlborg (7/20) Sep 10 2013 A mixin should not be necessary. RTInfo can be used for that:
- Joseph Rushton Wakeling (11/15) Sep 10 2013 Can you explain a bit more about how that works?
- Jacob Carlborg (33/43) Sep 10 2013 The "object" module, part of druntime defines a template with the name
- Joseph Rushton Wakeling (10/24) Sep 10 2013 But the problem that I identified wasn't the possibility of members that...
- Andrej Mitrovic (3/5) Sep 10 2013 The mixin was demonstrated for convenience so you don't have to
- Joseph Rushton Wakeling (2/15) Sep 09 2013 Fair enough. In that case I guess my objections don't really hold water...
- Jesse Phillips (6/15) Sep 09 2013 I think DDOC should be improved to handle this scenario. Being
- Joseph Rushton Wakeling (8/12) Sep 09 2013 Better DDoc is always going to be nice, but come on -- that doesn't addr...
- Gary Willoughby (6/11) Sep 09 2013 This is such a poor argument for changing and further
- Joseph Rushton Wakeling (8/11) Sep 09 2013 I can understand anyone feeling that the costs aren't worth it, but I do...
- Jesse Phillips (11/27) Sep 10 2013 I hope you realize you've restated what I said? Include
- H. S. Teoh (6/20) Sep 09 2013 Auto-generation of .di files solves this problem. (Provided we fix the
- Andrei Alexandrescu (3/5) Sep 09 2013 OK, so what's the trouble with .di generation today?
- Brian Schott (4/11) Sep 09 2013 Related to this: Is semantic information necessary for .di
- H. S. Teoh (61/66) Sep 09 2013 [...]
- Andrei Alexandrescu (4/13) Sep 09 2013 [more good stuff]
- H. S. Teoh (6/21) Sep 09 2013 [...]
- Dicebot (22/22) Sep 10 2013 Main issue of .di files that make them useless for anything but
- Andrej Mitrovic (5/8) Sep 10 2013 Yeah, I think we could attempt to provide an alternative to DIP47 by
- Dicebot (4/15) Sep 10 2013 Please, no compiler flags. It should be default behavior. We are
- Joseph Rushton Wakeling (7/9) Sep 09 2013 Maybe you'll think I'm being too picky, but I don't think that generated...
- Bruno Medeiros (25/109) Sep 16 2013 Ok, basically you are trying to add some language complexity just to
- Jacob Carlborg (17/21) Sep 09 2013 What's wrong with the code below, that works today:
- sclytrack (58/63) Sep 09 2013 ---------------------------------------
- Joseph Rushton Wakeling (23/33) Sep 09 2013 For what it's worth, I think this kind of baptism-by-fire practical expe...
- Dicebot (3/11) Sep 09 2013 Very well spoken, this is exactly how I see it.
- Joseph Rushton Wakeling (2/12) Sep 10 2013 Thank you! :-)
- jostly (31/37) Sep 09 2013 As a long-time Java developer, my answer would be that it's dealt
- Martin Nowak (10/16) Sep 09 2013 I'm really happy to see this discussed.
- Walter Bright (4/9) Sep 09 2013 The trouble with eschewing private access for member functions is then a...
- Timon Gehr (2/5) Sep 10 2013 Functions are placed inside classes for convenient scoping and vtables.
- bearophile (30/42) Sep 10 2013 I was away and very busy, I have read only part of the answers in
- Craig Dillabaugh (14/23) Sep 10 2013 I am sure there is a good reason for having no parameter names
- bearophile (9/11) Sep 10 2013 There are rare situations when you need to add a certain argument
- Craig Dillabaugh (3/15) Sep 10 2013 I think using calling the variable 'dummy' would likely do the
- Dicebot (4/16) Sep 10 2013 It is never the case in the declaration though. You always want
Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47
Sep 07 2013
On 7-9-2013 19:00, Walter Bright wrote:Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47The problem is that it is optional, so when you're reading other people's code you'll still have to deal with inline definitions, and you'll need a decent editor (doesn't have to be an IDE, even basic editors like notepad++ and editpad pro support code folding and function lists) to easily read it.
Sep 07 2013
On 7 September 2013 18:28, Jos van Uden <usenet fwend.com> wrote:On 7-9-2013 19:00, Walter Bright wrote:There's no problem here then! Only two points I'd add to that list are that outlined member functions declared in external modules: - Will error if the aggregate or member declaration is not found (eg: member doesn't exist in aggregate or external module is not imported). - Are mangled as if from the module where the aggregate member is declared. Just clarifies some implementation detail. -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47The problem is that it is optional, so when you're reading other people's code you'll still have to deal with inline definitions, and you'll need a decent editor (doesn't have to be an IDE, even basic editors like notepad++ and editpad pro support code folding and function lists) to easily read it.
Sep 07 2013
On Saturday, 7 September 2013 at 17:28:42 UTC, Jos van Uden wrote:and you'll need a decent editorOr just run dmd -H over it.
Sep 07 2013
On Saturday, 7 September 2013 at 17:28:42 UTC, Jos van Uden wrote:On 7-9-2013 19:00, Walter Bright wrote:No pun intended, but having it as _mandatory_ would be a little to much for people like me that don't like this proposal at all. - Paolo InvernizziOutlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47The problem is that it is optional, so when you're reading other people's code you'll still have to deal with inline definitions, and you'll need a decent editor (doesn't have to be an IDE, even basic editors like notepad++ and editpad pro support code folding and function lists) to easily read it.
Sep 07 2013
On 9/7/2013 11:39 AM, Paolo Invernizzi wrote:No pun intended, but having it as _mandatory_ would be a little to much for people like me that don't like this proposal at all.There's no way it would be mandatory.
Sep 07 2013
On 7-9-2013 20:39, Paolo Invernizzi wrote:On Saturday, 7 September 2013 at 17:28:42 UTC, Jos van Uden wrote:Exactly, so we're adding a lot of code noise, while you still have to use an editor for codes that don't outline, so you might as well just use an smart editor in the first place.On 7-9-2013 19:00, Walter Bright wrote:No pun intended, but having it as _mandatory_ would be a little to much for people like me that don't like this proposal at all. - Paolo InvernizziOutlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47The problem is that it is optional, so when you're reading other people's code you'll still have to deal with inline definitions, and you'll need a decent editor (doesn't have to be an IDE, even basic editors like notepad++ and editpad pro support code folding and function lists) to easily read it.
Sep 07 2013
On Saturday, 7 September 2013 at 17:28:42 UTC, Jos van Uden wrote:On 7-9-2013 19:00, Walter Bright wrote:So the problem is that you need a *basic* editor to make other people's code look like the way you like ? I'd say this is awesome, and most of the time, you won't achieve that. Don't try to impose your religion to the world.Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47The problem is that it is optional, so when you're reading other people's code you'll still have to deal with inline definitions, and you'll need a decent editor (doesn't have to be an IDE, even basic editors like notepad++ and editpad pro support code folding and function lists) to easily read it.
Sep 07 2013
On Sat, Sep 07, 2013 at 07:28:39PM +0200, Jos van Uden wrote:On 7-9-2013 19:00, Walter Bright wrote:This in itself is a pretty strong argument against this DIP. It introduces additional cognitive overload (now we have to learn a second syntax for defining class members), and *still* doesn't help the people who want this feature in the first place when they have to read others' code. Not to mention, this will add additional complexity to the parser, and probably introduce more bugs related to function attributes -- for example: - Should function attributes be repeated verbatim across the in-class declaration and the out-of-class definition? If not, where can they be omitted? - What about attribute inference? What if the definition has attributes that conflict with the in-class declaration? - How will this interact with the current DI generation code? - How will it affect forward references (which are currently already rather wonky in certain areas)? - What about nested classes? Will they be allowed to have outlining member functions too? Where should their member definitions be, and what should their syntax be? How will attribute inference work for them? I vote against this DIP. I feel like it's adding a lot of complexity to the language (and probably many more bugs to the compiler) for only a small gain. We already have enough wrinkles yet to be ironed out (scope, shared, auto ref, AA's, inout ambiguities, postblit, tail-const, emplace, the combinatorial explosion of all the different interactions between the foregoing, just to name a few), why are we introducing yet another level of complexity into the mix? T -- Tech-savvy: euphemism for nerdy.Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47The problem is that it is optional, so when you're reading other people's code you'll still have to deal with inline definitions, and you'll need a decent editor (doesn't have to be an IDE, even basic editors like notepad++ and editpad pro support code folding and function lists) to easily read it.
Sep 07 2013
07-Sep-2013 21:00, Walter Bright пишет:Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP477. Outlined member function return types, parameter types, and function bodies have private access to the module where the aggregate is declared. I understand why you may want this hack but it starts to smells real bad. Not only we haven't fixed bugs in our module system yet we introduce another kludge into it to support the C++ header + unknown set of files with implementations. Another twist in visibility/accessiblity lookup rules. I expect another wave of bugs regarding safe/pure/etc. silently accepted for outlined functions and so on. Now you can't know if a module implements all of stuff it declares or not. Or where it is implemented at all. I would rather restrict this feature w.r.t. where outlined methods can be defined - e.g. same module or in the same sub-package. Accessibility rules should stay the same as they are now. In that setting if one wants to split methods across multiple file - fine, just declare them 'package' and put implementations deeper down the package tree. TL;DR: DROP point 7, and describe how to use 'package' to split implementation across multiple files. -- Dmitry Olshansky
Sep 07 2013
07-Sep-2013 22:01, Dmitry Olshansky пишет:07-Sep-2013 21:00, Walter Bright пишет:Not to mention poor motivation. A huge paragraph that basically states that some folks prefer IDEs to automatically fixup *this* kind of stuff and not *that* kind of stuff. I could understand this feature can be very convenient in e.g. DDMD that is being converted from C++. Then this and other examples should be provided. -- Dmitry OlshanskyOutlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47
Sep 07 2013
On 09/07/2013 07:00 PM, Walter Bright wrote:Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47Rationale:I don't think that the official rationale should include 'readability', giving clear preference to one declaration style over the other.Semantics:First of all, the DIP should address the following additional points: - CTFE (under which circumstances is an outlined member function CTFE-able?) - UDA's - DDOC - Auto return functions1. Only member functions of aggregates at module scope can be outlined.Why module scope? Why just member functions?2. Types, parameter types, and pure/const/immutable/shared/nothrow attributes must match. This is necessary as they affect overloading and so are needed for correct selection of which declaration is being outlined.Why would nothrow/pure affect overloading but safe/static not?3. Parameter names need not match.OK. (But maybe it is better to require them to match if given in both places.)4. If there is a default parameter value, it may only appear in the member function declaration.Probably this is not too bad, but can't you just require the AST to match?5. safe/ trusted/ system, private/package/public/export access, linkage and storage classes are as set in the declaration, overriding any in effect for the definition.Isn't the overriding just confusing for no reason?6. Template member functions may not be outlined.(This is included in point 1.)7. Outlined member function return types, parameter types, and function bodies have private access to the module where the aggregate is declared.The function names themselves are missing, and maybe you want the type-declaring module to have access to its private function bodies as well if it imports the implementing module. In any case, this is rather ugly. Why not use 'package' for this purpose and keep visibility rather simple? [1] ([1] Well, IMO 'protected' is quite hard to implement in a non-restrictive way in presence of compile-time reflection.)
Sep 07 2013
3. Parameter names need not match.I think we should be conservative and require that parameter names match. This will ensure that code will not break in the future if named parameter functionality is added to the language at some point.
Sep 07 2013
On 7 September 2013 20:04, Jonas Drewsen <nospam4321 hotmail.com> wrote:What about the absence of parameter names in the declaration? struct Foo { int bar (string, int, int); } int Foo.bar (string str, int start, int end) { /* ... */ } -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';3. Parameter names need not match.I think we should be conservative and require that parameter names match. This will ensure that code will not break in the future if named parameter functionality is added to the language at some point.
Sep 07 2013
On 9/7/13, Walter Bright <newshound2 digitalmars.com> wrote:http://wiki.dlang.org/DIP47Am I correct to say that such member definitions will have the same overload rules as before? Currently using UFCS has issues where function hijacking prevention will cause errors at compile time, for example: ----- module a; import b; struct A { } void test(A a) { } // hides B.test! void main() { B b; // error: function a.test (A a) is not // callable using argument types (B) b.test(); } ----- ----- module b; struct B { } void test(B b) { } ----- I just want to ensure that the following does not issue a compiler error: ----- module a; import b; struct A { void test() { } } void A.test() { } // outlined void main() { B b; b.test(); // should be ok, A.test should not hide B.test! } ----- ----- module b; struct B { void test() { } } void B.test() { } // outlined -----
Sep 07 2013
On 9/7/2013 12:05 PM, Andrej Mitrovic wrote:Am I correct to say that such member definitions will have the same overload rules as before?Yes. This proposal does not add the outlined function name to any other scope than where it is declared, hence it cannot hide anything.
Sep 07 2013
On 9/7/13, Walter Bright <newshound2 digitalmars.com> wrote:3. Parameter names need not match.I disagree with this, because it will practically guarantee that declarations and definitions go out of sync, which will be *harmful* for readability (which is partly what this DIP is all about).4. If there is a default parameter value, it may only appear in the member function declaration.Also disagreed, because again you can't tell how a function can be called just by looking at its definition, now you have to go back and forth between the declaration and the definition to fully understand how the function works and how it can be used. On the other hand, allowing both the declaration and the definition to have the default values (which must match of course) might have issues with readability as well: module a; enum val = 1; struct S { void test(int x = val); } module a_impl; enum val = 2; void S.test(int x = val); // a.val or a_impl.val? If 'val' will always refer to a.val in the declaration module, then there's no conflict, however it does create a bit of a readability issue. Still, I think default values should appear at both sides. It's very easy to forget you've defaulted a parameter when you start implementing the function, you could even implement it wrongly.safe/ trusted/ system, private/package/public/export access, linkage and storage classes are as set in the declaration, overriding any in effect for the definition.They should both match or there should be an error. Don't allow sloppy code to be written like that, people *will* read both the declarations and the definitions (the team or contributors in an open-source project), and any mismatch will only cause confusion.
Sep 07 2013
On 9/7/2013 12:30 PM, Andrej Mitrovic wrote:On 9/7/13, Walter Bright <newshound2 digitalmars.com> wrote:Good point.3. Parameter names need not match.I disagree with this, because it will practically guarantee that declarations and definitions go out of sync, which will be *harmful* for readability (which is partly what this DIP is all about).How a function is to be *used* should be all there in the *declaration*. Not the definition. I didn't mention it in the DIP, and should, that the reason for the default value to be in the declaration is 1. it should only depend on the declaration's scope and 2. because all uses of it should rely only on the declaration and 3. because making an exact duplicate of it in the definition is pointless.4. If there is a default parameter value, it may only appear in the member function declaration.Also disagreed, because again you can't tell how a function can be called just by looking at its definition, now you have to go back and forth between the declaration and the definition to fully understand how the function works and how it can be used.On the other hand, allowing both the declaration and the definition to have the default values (which must match of course) might have issues with readability as well: module a; enum val = 1; struct S { void test(int x = val); } module a_impl; enum val = 2; void S.test(int x = val); // a.val or a_impl.val? If 'val' will always refer to a.val in the declaration module, then there's no conflict, however it does create a bit of a readability issue. Still, I think default values should appear at both sides. It's very easy to forget you've defaulted a parameter when you start implementing the function, you could even implement it wrongly.No, see above.I have mixed feelings about this. I think there needs to be just enough in the definition to match it to the declaration, and nothing else.safe/ trusted/ system, private/package/public/export access, linkage and storage classes are as set in the declaration, overriding any in effect for the definition.They should both match or there should be an error. Don't allow sloppy code to be written like that, people *will* read both the declarations and the definitions (the team or contributors in an open-source project), and any mismatch will only cause confusion.
Sep 07 2013
On 9/7/13, Walter Bright <newshound2 digitalmars.com> wrote:How a function is to be *used* should be all there in the *declaration*. Not the definition.I mean the *header* part of the function's definition (everything up to the closing parens of the parameter list). If someone is currently looking at an implementation file: void S.foo(int x) { ... } They will assume 'x' must be specified. You can argue that people shouldn't be looking at the implementation, but do have in mind two things: 1. This new feature is *optional*, meaning people will still look at the implementation for guidance, and not all new library writers will take advantage of this new feature. This has the consequence that a user looking at a function called "foo", and looking at one called "S.foo" will have to be careful not to assume that "S.foo" documents the parameter list properly (because it can mismatch the declaration if you allow default arguments to be missing). 2. People are already used to looking at implementation files and method implementations in almost all public D projects. Header files have not proven to be popular among D projects.I didn't mention it in the DIP, and should, that the reason for the default value to be in the declaration is 1. it should only depend on the declaration's scopeThe code in the function's body already depends on the declaration's scope. It would be a little strange if the body of the function has access to one scope, but the parameter list has either no scope or a different scope.
Sep 07 2013
On 9/7/13, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:If 'val' will always refer to a.val in the declaration moduleI meant if 'val' in the parameter list in the outlined function always refers to 'a.val'.
Sep 07 2013
On 9/7/13, Walter Bright <newshound2 digitalmars.com> wrote:http://wiki.dlang.org/DIP471. Only member functions of aggregates at module scope can be outlined.This is an unnecessary restriction. You haven't provided any reason in
Sep 07 2013
On 9/7/13, Walter Bright <newshound2 digitalmars.com> wrote:http://wiki.dlang.org/DIP47Your example code: ----- struct S { static int mfunc(int a, int b = 5) pure; // member function declaration } int S.mfunc(int a, int b) pure { // member function definition ... } ----- Two things: 1. Why are you demonstrating static functions and not regular member functions (or better yet why not both)? 2. Why has 'static' been removed at the outlined implementation function? It should also be there: static int S.mfunc(int a, int b) pure { // member function definition } To reiterate, let's not introduce a feature where we can be totally lax about what we do at the declaration and implementation site. My strong opinion is that the declaration and implementation must perfectly match, otherwise you can throw the readability argument out the window.
Sep 07 2013
On 9/7/2013 12:43 PM, Andrej Mitrovic wrote:On 9/7/13, Walter Bright <newshound2 digitalmars.com> wrote:Because I wanted to point out that you didn't need to put the 'static' in front of the definition.http://wiki.dlang.org/DIP47Your example code: ----- struct S { static int mfunc(int a, int b = 5) pure; // member function declaration } int S.mfunc(int a, int b) pure { // member function definition ... } ----- Two things: 1. Why are you demonstrating static functions and not regular member functions (or better yet why not both)?2. Why has 'static' been removed at the outlined implementation function? It should also be there: static int S.mfunc(int a, int b) pure { // member function definition }Why?To reiterate, let's not introduce a feature where we can be totally lax about what we do at the declaration and implementation site. My strong opinion is that the declaration and implementation must perfectly match, otherwise you can throw the readability argument out the window.On the other hand, DRY, and I don't recall anyone ever complaining about this in C++ outlined members.
Sep 07 2013
On Sunday, 8 September 2013 at 03:37:35 UTC, Walter Bright wrote:On the other hand, DRY, and I don't recall anyone ever complaining about this in C++ outlined members.Let me be the first, then, to formally lodge my complaint. As for the DIP itself, I had enough of this tedium in C++. I would strongly prefer that it not be introduced in D. Working realized what a pain this "feature" is.
Sep 08 2013
On Saturday, 7 September 2013 at 17:00:08 UTC, Walter Bright wrote:Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47Many details were ommited. Just some of them, others were raised. 1) If you allow to have definition in external module (by the way, this point is not clear), how can you control name mangling? 2) Does outlining limited only to static functions? 3) With UFSC if you have a.foo you cannot know where to found foo(a) - it can be hidden in dozens of imports, and if there are public imports, the situation becomes even more complex.
Sep 07 2013
On 9/7/2013 12:56 PM, Maxim Fomin wrote:On Saturday, 7 September 2013 at 17:00:08 UTC, Walter Bright wrote:You import the module containing the declaration. Like in C++.Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47Many details were ommited. Just some of them, others were raised. 1) If you allow to have definition in external module (by the way, this point is not clear), how can you control name mangling?2) Does outlining limited only to static functions?No.3) With UFSC if you have a.foo you cannot know where to found foo(a) - it can be hidden in dozens of imports, and if there are public imports, the situation becomes even more complex.??? You find the declaration in the module that declares it. Same as for C++.
Sep 07 2013
On Saturday, 7 September 2013 at 17:00:08 UTC, Walter Bright wrote:Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47By the way, what is the ratio implemented DIPS/total DIPS? I guess it is <5%. Shouldn't it be a sign of DIP process flaws? I seems that many take care of pushing their ideas in form of DIPs but don't bother to take care of implementing them (last sentence obviously doesn't apply personally to Walter).
Sep 07 2013
On 9/7/2013 1:14 PM, Maxim Fomin wrote:By the way, what is the ratio implemented DIPS/total DIPS? I guess it is <5%. Shouldn't it be a sign of DIP process flaws? I seems that many take care of pushing their ideas in form of DIPs but don't bother to take care of implementing them (last sentence obviously doesn't apply personally to Walter).Even if they are unimplemented, the same ideas crop up repeatedly. The DIPs provide an anchor to avoid everyone repeating the same things.
Sep 07 2013
Like I said in Manu's thread, we can actually do this already, via pragma(mangle) hacks. That's brittle, the compiler doesn't tell you if you messed up the signature, but it works and gives answers to a lot of the questions in this thread. class A { void foo(); } pragma(mangle, A.foo.mangleof) void foo_impl(A _this) {} That's compile and run today. Things to note: * The name is figured out by regular importing rules. A is whatever A is in schope. * foo_impl might as well not exist as far as the outside world is concerned. It just is A.foo. * I think the privacy should work this same way too: if it is in the same module, it can see private members, if not, it can't.
Sep 07 2013
On 9/7/13, Adam D. Ruppe <destructionator gmail.com> wrote:pragma(mangle, A.foo.mangleof) void foo_impl(A _this) {}It's cute, but it it doesn't allow you to e.g. implement constructors outside the class. It also doesn't allow you to call a 'super' method without explicitly naming the class. E.g. with the above you can't do: _this.super.foo(); You would have to change it to: _this.ExplicitClassName.foo();
Sep 07 2013
"Walter Bright" <newshound2 digitalmars.com> wrote in message news:l0fm2o$2uat$1 digitalmars.com...Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47I am strongly opposed to this DIP. I think it brings a little slice of C++ hell to D. This change will result in manually-synchronized duplication. The argument that IDEs can deal with this automatically is irrelevant, because they currently can't and are unlikely to do so any time soon. The main motivation for this seems to be that you can't get a clear overview of a class from looking at the raw source code. I propose a much simpler solution to this: ** Introduce compiler-checked (via warnings) class summary documentation. ** This solves the problem - an overview of the class is available in the raw source code, and enabling the warning will prevent them from getting out of sync. Let's solve a documentation issue with documentation improvements.
Sep 07 2013
On Sunday, 8 September 2013 at 04:32:36 UTC, Daniel Murphy wrote:"Walter Bright" <newshound2 digitalmars.com> wrote in message news:l0fm2o$2uat$1 digitalmars.com...This generated documentation solution seems like the best approach.Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47I am strongly opposed to this DIP. I think it brings a little slice of C++ hell to D. This change will result in manually-synchronized duplication. The argument that IDEs can deal with this automatically is irrelevant, because they currently can't and are unlikely to do so any time soon. The main motivation for this seems to be that you can't get a clear overview of a class from looking at the raw source code. I propose a much simpler solution to this: ** Introduce compiler-checked (via warnings) class summary documentation. ** This solves the problem - an overview of the class is available in the raw source code, and enabling the warning will prevent them from getting out of sync. Let's solve a documentation issue with documentation improvements.
Sep 07 2013
On Saturday, 7 September 2013 at 17:00:08 UTC, Walter Bright wrote:Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47It's this post again: Why do all of the DIPs that change the grammar never detail the changes to the grammar?
Sep 07 2013
On Saturday, September 07, 2013 10:00:05 Walter Bright wrote:Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47I confess that I really don't like this idea. I think that the separation of declarations and definitions is a serious downside of C++ and that it negatively impacts code maintenence. And from the recent discussion on this, it's clear that quite a few people agree with me. However, at the same time, there are some folks (like Manu) who really prefer to separate the declaration and definitions so that they can just see the signatures for an entire class' functions at once without seeing any definitions. Personally, I don't think that that's a big deal and that it's far better to just use generated documentation for that, but clearly there's not a consensus on that. If this DIP is implemented, I do not expect to ever use it, and I hope to never have to deal with code that does (which is ultimately the main reason why I think that it would be a problem if this were implemented - eventually, I'll have to deal with code that uses it even though I think that it harms code maintainibility). But at the same time, I don't know that the fact that quite a few of this really don't like this paradigm is enough a reason to deny it to those who seem to think that it's of value. If I had to vote though, I'd vote against this, because I think that it's a bad paradigm, and I don't want to deal with it. that it should be an outright error if there is a difference between the declaration and definition rather than giving one precedence over the other. should be required to match, but it's unfortunately not all that uncommon in C++ for folks to not even give parameters names in their declarations, so requiring that the parameters match is probably too much, much as I think that that they should be required to. - Jonathan M Davis
Sep 07 2013
On 9/7/2013 9:46 PM, Jonathan M Davis wrote:that it should be an outright error if there is a difference between the declaration and definition rather than giving one precedence over the other.I'll point out that C++ has equivalent behavior, and it has not resulted in any complaints I've ever heard. When you outline a C++ member function, you do not need to add 'static', 'private', 'virtual', and in fact you cannot add the latter two.
Sep 07 2013
On 08/09/13 15:40, Walter Bright wrote:On 9/7/2013 9:46 PM, Jonathan M Davis wrote:Here's one. It's one of the things that I don't like about C/C++ as it doubles the work required in code maintenance. One of the things that I like about D is that forward references aren't required and this seems to me to be introducing a feature that was only ever in C/C++ to make forward references possible (which is why I tolerated it). In summary, you've gotten rid of the need for this type of duplication so why would you introduce it? Peterthink that it should be an outright error if there is a difference between the declaration and definition rather than giving one precedence over the other.I'll point out that C++ has equivalent behavior, and it has not resulted in any complaints I've ever heard. When you outline a C++ member function, you do not need to add 'static', 'private', 'virtual', and in fact you cannot add the latter two.
Sep 07 2013
On 9/7/2013 11:08 PM, Peter Williams wrote:In summary, you've gotten rid of the need for this type of duplication so why would you introduce it?I believe that is covered in the "Rationale" section of the dip.
Sep 07 2013
On Sunday, 8 September 2013 at 06:47:14 UTC, Walter Bright wrote:On 9/7/2013 11:08 PM, Peter Williams wrote:IMHO the rationale of the proposal il pretty weak: - You can't have a 1:1 correspondence with translated C++ code, so the translation barrier can be lower. - You can't read _easily_ the code. The first is not a problem, if it is true that D avoidance of duplication is better than C++ way of doing that stuff (and that's a C++ problem, as Peter suggested). I would also add that I don't think at all that this is a concrete translation barrier: usually I start copying and pasting the C++ header in the D code, and then filling the methods translating from the cpp part one after another. The second point is more subtle, as we are talking about an easy _navigation_ in the code in the editor, we are talking about being able to "gain a sense of familiarity" with foreign code? The former is something that should not impact over the language at all (alas, C++ navigation, back and forth between header and implementation is a mess), The latter resolved by D with DDOC, which it is perfectible BUT is _today_ a wonderful tool for strangers: the D library section on DLang site is there to prove it. You have at a glance all the definitions, documented and in sync with the last compilation. What is missing from that? - Paolo InvernizziIn summary, you've gotten rid of the need for this type of duplication so why would you introduce it?I believe that is covered in the "Rationale" section of the dip.
Sep 08 2013
On 08/09/13 16:47, Walter Bright wrote:On 9/7/2013 11:08 PM, Peter Williams wrote:Couldn't see a rational answer to my question in the rationale. Looked more like a "I want to do this and I think that we should change the language syntax to allow it" statement to me. It doesn't really add functionality just makes what's there more complex. PeterIn summary, you've gotten rid of the need for this type of duplication so why would you introduce it?I believe that is covered in the "Rationale" section of the dip.
Sep 08 2013
On Sunday, 8 September 2013 at 04:47:04 UTC, Jonathan M Davis wrote:On Saturday, September 07, 2013 10:00:05 Walter Bright wrote:I completely agree with Jonathan! This will only produce more code which will lead to more bugs and more maintenance.Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47I confess that I really don't like this idea. I think that the separation of declarations and definitions is a serious downside of C++ and that it negatively impacts code maintenence. And from the recent discussion on this, it's clear that quite a few people agree with me. However, at the same time, there are some folks (like Manu) who really prefer to separate the declaration and definitions so that they can just see the signatures for an entire class' functions at once without seeing any definitions. Personally, I don't think that that's a big deal and that it's far better to just use generated documentation for that, but clearly there's not a consensus on that. </ snip> - Jonathan M Davis
Sep 09 2013
Am 07.09.2013 19:00, schrieb Walter Bright:Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47"Parameter names need not match." please don't do this - that will nearly kill any easy way of finding the implementation, and there is absolutely no reason for differ here - that is too much sort of C/C++ compatible and i think in the end all styleguides around the world will tell you not to change the name on implementation
Sep 07 2013
On Sep 8, 2013 5:55 AM, "dennis luehring" <dl.soluz gmx.net> wrote:Am 07.09.2013 19:00, schrieb Walter Bright:of aOutlining of member functions is the practice of placing the declarationit atmember function in the struct/class/union, and placing the definition ofimplementation, That depends on your coding style and is not necessarily true. Eg: I put function names at the start of the line. int foo_bar () { } So all global functions are easily grep'able ('^foo_bar'). Same thing is also done with C++ outlined members ('^Class::foo_bar') and I could see myself adopting the same for D aggregate methods too. Regards -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';global scope in the module or even in another module. http://wiki.dlang.org/DIP47"Parameter names need not match." please don't do this - that will nearly kill any easy way of finding the
Sep 07 2013
Am 08.09.2013 07:48, schrieb Iain Buclaw:On Sep 8, 2013 5:55 AM, "dennis luehring" <dl.soluz gmx.net> wrote:im talking about "Parameter names need not match." so it will become hard to find the same overload of a method if someone else writes int a, int b in declaration and int pa, int pb in implementation - and the only benefit is beeing compatible with c/c++ - that will introduce another point in all D-coding-style guides around the world not to rename parameter in implementationAm 07.09.2013 19:00, schrieb Walter Bright:of aOutlining of member functions is the practice of placing the declarationit atmember function in the struct/class/union, and placing the definition ofimplementation, That depends on your coding style and is not necessarily true. Eg: I put function names at the start of the line. int foo_bar () { } So all global functions are easily grep'able ('^foo_bar'). Same thing is also done with C++ outlined members ('^Class::foo_bar') and I could see myself adopting the same for D aggregate methods too. Regardsglobal scope in the module or even in another module. http://wiki.dlang.org/DIP47"Parameter names need not match." please don't do this - that will nearly kill any easy way of finding the
Sep 07 2013
On 8 September 2013 07:14, dennis luehring <dl.soluz gmx.net> wrote:Am 08.09.2013 07:48, schrieb Iain Buclaw:I was talking about "Parameter names need not match" too... I disagree that mismatched parameter names makes things hard to find, and by way of example, I just search for the function. I never say "right, I need to find this implementation" and grep for the parameter list in the declaration... Regards -- Iain Buclaw *(p < e ? p++ : p) = (c & 0x0f) + '0';On Sep 8, 2013 5:55 AM, "dennis luehring" <dl.soluz gmx.net> wrote:im talking about "Parameter names need not match." so it will become hard to find the same overload of a method if someone else writes int a, int b in declaration and int pa, int pb in implementation - and the only benefit is beeing compatible with c/c++ - that will introduce another point in all D-coding-style guides around the world not to rename parameter in implementationAm 07.09.2013 19:00, schrieb Walter Bright:of aOutlining of member functions is the practice of placing the declarationit atmember function in the struct/class/union, and placing the definition ofimplementation, That depends on your coding style and is not necessarily true. Eg: I put function names at the start of the line. int foo_bar () { } So all global functions are easily grep'able ('^foo_bar'). Same thing is also done with C++ outlined members ('^Class::foo_bar') and I could see myself adopting the same for D aggregate methods too. Regardsglobal scope in the module or even in another module. http://wiki.dlang.org/DIP47"Parameter names need not match." please don't do this - that will nearly kill any easy way of finding the
Sep 07 2013
Am 08.09.2013 08:46, schrieb Iain Buclaw:i work as a independed refactorig/bug hunter developer on big team (30+ developers) big projects (1Mio LOC+) - i need to do that most of the time - i like D for beeing better refactorable/readable in the long run (years) of projects different people - different needsim talking about "Parameter names need not match." so it will become hard to find the same overload of a method if someone else writes int a, int b in declaration and int pa, int pb in implementation - and the only benefit is beeing compatible with c/c++ - that will introduce another point in all D-coding-style guides around the world not to rename parameter in implementationI was talking about "Parameter names need not match" too... I disagree that mismatched parameter names makes things hard to find, and by way of example, I just search for the function. I never say "right, I need to find this implementation" and grep for the parameter list in the declaration...
Sep 08 2013
On Saturday, September 07, 2013 21:30:10 Andrej Mitrovic wrote:On 9/7/13, Walter Bright <newshound2 digitalmars.com> wrote:Agreed. If we're going to do this, let's not allow the possibility of mismatches or it will make the maintenance problems that this DIP introduces even worse (though I'd prefer that we not implement it at all). - Jonathan M Davissafe/ trusted/ system, private/package/public/export access, linkage and storage classes are as set in the declaration, overriding any in effect for the definition.They should both match or there should be an error. Don't allow sloppy code to be written like that, people *will* read both the declarations and the definitions (the team or contributors in an open-source project), and any mismatch will only cause confusion.
Sep 07 2013
On Saturday, September 07, 2013 10:00:05 Walter Bright wrote:Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47Actually, for those who really want this sort of thing, why don't they just use .di files? At that point, you're doing basically the same thing that C++ does anyway (which is part of why I hate .di files). What benefit over that do we really get by adding this feature? - Jonathan M Davis
Sep 07 2013
08-Sep-2013 09:00, Jonathan M Davis пишет:On Saturday, September 07, 2013 10:00:05 Walter Bright wrote:And speaking of IDEs, they easily grow a simple feature - press some short-cut and it would display what dmd -H of the current file looks like. No need to bend the language backwards.Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47Actually, for those who really want this sort of thing, why don't they just use .di files? At that point, you're doing basically the same thing that C++ does anyway (which is part of why I hate .di files). What benefit over that do we really get by adding this feature?- Jonathan M Davis-- Dmitry Olshansky
Sep 08 2013
On 09/08/2013 07:00 AM, Jonathan M Davis wrote:Actually, for those who really want this sort of thing, why don't they just use .di files?Because this is a prerequisite to do so. One important point is being able to verify the definition against the declaration which isn't currently possible.
Sep 09 2013
On 9/8/13 1:00, Walter Bright wrote:Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47I would restrict it to a single module for the time being. We can always open it up to other modules later, but we wouldn't be able to restrict it back to a single module, since that would be a breaking change. L.
Sep 07 2013
On Saturday, 7 September 2013 at 17:00:08 UTC, Walter Bright wrote:Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47I'm against that. Reasons: - Do not change a language without very solid or even urgent need. - A concise spec (we are going there that, right?) and reliability is way more important than gadgets or "X has that. We need that, too!". - What for? This approach is anyway not the right one. If this is about readability then ... ... what's the big issue? "I don't like 'class ...{' at the beginning of my source code and a '}' at the end"? Because that's what it comes down to. If this is about readability as in "I want to have a quick and comfortable look at my module or class interface" (which is a reasonable desire and a useful thing) then ... ... the solution is not to change the language but to have a compiler switch to have the compiler generate a client/interface view file. (One might discuss what exactly should should go there) A+ -R
Sep 07 2013
On Saturday, 7 September 2013 at 17:00:08 UTC, Walter Bright wrote:Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47"Parameter names need not match." I can't wait to implement a static code analysis rule that yells at people for not having them match. "If there is a default parameter value, it may only appear in the member function declaration." Shouldn't they match? " safe/ trusted/ system, private/package/public/export access, linkage and storage classes are as set in the declaration, overriding any in effect for the definition." Again. Someone will create a static code analysis tool that warns about this. Why allow it in the language?
Sep 07 2013
I'm against it. More important than such a gimmick are the many open bugs, auto ref, AA, scope, etc. And don't forget the implementation of the virtual keyword.
Sep 08 2013
On Sunday, 8 September 2013 at 09:15:52 UTC, Namespace wrote:I'm against it. More important than such a gimmick are the many open bugs, auto ref, AA, scope, etc. And don't forget the implementation of the virtual keyword.+1
Sep 08 2013
On Sunday, 8 September 2013 at 09:24:52 UTC, Michael wrote:On Sunday, 8 September 2013 at 09:15:52 UTC, Namespace wrote:I strongly dislike DIP47, I found many unintended discrepancies in our C code-base at work... precisely because of "lax rules", even cases with wrong linkage as result! "Parameter names need not match." "If there is a default parameter value, it may only appear in the member function declaration." This forces indexing of source and jump to declaration features in the IDE, the current way is more friendly to simpler text-editors, the problem which DIP47 is trying to solve is anyway solved by IDE:s "Class View" feature etc. i.e. For people using IDE:s(class view, or ddoc) nothing changes with DIP47. For people using plain editors, DIP47 makes it worse. Even if DIP47 is implemented, I hope this feature is strongly discouraged in the standard library.I'm against it. More important than such a gimmick are the many open bugs, auto ref, AA, scope, etc. And don't forget the implementation of the virtual keyword.+1
Sep 08 2013
Wouldn't this style be an acceptable compromise instead? with both declaration and definition 100% identical. struct S { // member function declarations static int mfunc1(int a, int b = 5) pure; static int mfunc2(int a, int b = 5) pure; static int mfunc3(int a, int b = 5) pure; // member function definitions static int mfunc1(int a, int b = 5) pure { } static int mfunc2(int a, int b = 5) pure { } static int mfunc3(int a, int b = 5) pure { } }
Sep 08 2013
On 2013-09-08, 12:46, Tove wrote:Wouldn't this style be an acceptable compromise instead? with both declaration and definition 100% identical. struct S { // member function declarations static int mfunc1(int a, int b = 5) pure; static int mfunc2(int a, int b = 5) pure; static int mfunc3(int a, int b = 5) pure; // member function definitions static int mfunc1(int a, int b = 5) pure { } static int mfunc2(int a, int b = 5) pure { } static int mfunc3(int a, int b = 5) pure { } }The problem here is the compiler does not enforce that all definitions are present in the declaration list. Apart from that, I feel this is the correct solution to the problem. -- Simen
Sep 08 2013
On 09/08/2013 06:46 AM, Jonathan M Davis wrote:If I had to vote though, I'd vote against this, because I think that it's a bad paradigm, and I don't want to deal with it.+1
Sep 08 2013
On Sunday, 8 September 2013 at 10:59:34 UTC, Robert Schadek wrote:On 09/08/2013 06:46 AM, Jonathan M Davis wrote:+1 Also issues mentioned by Manu are easily solvable: DI files and/or DDOC + remove one level of indentation after class: --- class Foo { void foo() { writeln("hello world"); } } --- ;)If I had to vote though, I'd vote against this, because I think that it's a bad paradigm, and I don't want to deal with it.+1
Sep 08 2013
On 2013-09-07 17:00:05 +0000, Walter Bright <newshound2 digitalmars.com> said:Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47About placing the definition in another module, you say that the definition when outlined in another module would have private access to the private members of the module of declaration. Does that mean that the definition has access to the private members of two modules at the same time, the one it is declared in and the one it is defined in? That seems strange to me. I find it strange that pure/const/immutable/shared/nothrow need to match, yet static does not. Beside this being the way it works in C++ (presumably because static at global scope has another meaning inherited from C), I see no reason for this. In C++ I often find myself wondering whether a function has access to the member variables and I have to find the definition in the header file, which is inconvenient. Static being part of the definition seems to only make sense. About parameter names, I think it'd be better if they were forced to match. Mismatches are a code smell to me: if you reverse the meaning of two parameters with the same type while refactoring, you must be sure the public interface and the implementation still agree. I guess you could allow the declaration to omit the parameter names in which case the definition could add a name, but don't allow *different* names, it's pointless and it can easily hide a bug. I think it's fine that default values for parameters don't have to be repeated, but it'd be nice if they *could* because it enables copy-pasting of the declarations. The compiler would of course have to check that both expressions are identical. I'd like to make a suggestion. If one goal is effectively to allow the implementation of a function to live in a separate file from its declaration, then we already have a mechanism for that: .di files. So I'd like to suggest this: allow a .d file to "import" its corresponding .di file. Then the .d file should only contain the missing definitions for what's declared in the hand-crafted .di file. That'd remove the dubious semantics of making the definition part of another module and would also allow outlining of global functions. And it also matches better the C++ model of header/implementation files. Also, I'd allow outlining only for this specific case where a .di file is imported by a .d file. This way you know for sure when you see a declaration without the definition in a .di file that this declaration is in the corresponding .d file and not anywhere else, making it easier to hunt it down. Example: // test.di module test; class A { void foo(int a, int b); } // test.d import module test; // import declarations from the .di file void A.foo(int a, int b) { // member function definition } -- Michel Fortin michel.fortin michelf.ca http://michelf.ca
Sep 08 2013
On 9/8/13, Michel Fortin <michel.fortin michelf.ca> wrote:So I'd like to suggest this: allow a .d file to "import" its corresponding .di file.This is actually what Andrei proposed as well.
Sep 08 2013
On Sunday, 8 September 2013 at 12:34:06 UTC, Andrej Mitrovic wrote:On 9/8/13, Michel Fortin <michel.fortin michelf.ca> wrote:+42So I'd like to suggest this: allow a .d file to "import" its corresponding .di file.This is actually what Andrei proposed as well.
Sep 08 2013
On Sunday, 8 September 2013 at 15:14:51 UTC, deadalnix wrote:On Sunday, 8 September 2013 at 12:34:06 UTC, Andrej Mitrovic wrote:That is why I had a feeling I have already seen it somewhere :)On 9/8/13, Michel Fortin <michel.fortin michelf.ca> wrote:+42So I'd like to suggest this: allow a .d file to "import" its corresponding .di file.This is actually what Andrei proposed as well.
Sep 08 2013
On 9/8/13 5:33 AM, Andrej Mitrovic wrote:On 9/8/13, Michel Fortin <michel.fortin michelf.ca> wrote:I have to say I was a lot more in favor of the proposal before this thread. The problem as I see it has two facets: 1. Code duplication 2. Modularity and logistics Regarding (1), we currently force duplication of the entire class layout. My understanding is that this is the way it's done: // file acme.di class A { int x; double y; void fun(); } // file acme.d // cannot import acme.di class A { int x; double y; void fun() { ... } } The fact that acme.d cannot import acme.di is an unforced error of embarrassing proportions and consequence. That should be fixed yesterday no matter how we proceed otherwise. The problem with acme.d not having access to acme.di is that any error in duplicating the layout of A (e.g. swapping x and y or adding some other members etc) will have undefined behavior, and there is no reasonable way for the compiler to check against that. Assuming that bug is fixed, the problem of duplication remains - all state of the class must be duplicated. (I also suspect constructors might need to be white-boxed (i.e. available in the .di) for raw/cooked typechecking, but I'm not sure.) If we go with DIP47, the duplication of state goes away. However we have a distinct problem - modularity, which segues into (2). Allowing out-of-module implementations of individual methods poses additional modularity problems. Consider: // file acme.di class A { int x; double y; void fun(); } private int a; private void gun(); // file acme.d // assume we solve the import problem import acme; void A.fun() { gun(); a = 42; } If A.fun() were defined inside acme.di, it would have access to gun() and a. Defining it outside asks the question - do we allow such access, or not? Intuitively the body of a method should not be all too sensitive to where it's placed, so that argues in favor of visibility. D's module system has always favored a file-granular approach, e.g. private stuff is module-private. This notion of spilling private access outside the file into methods defined in various other files works against that nice tenet. So it looks there's no obvious and obviously good solution. Probably the first one is more sensible. AndreiSo I'd like to suggest this: allow a .d file to "import" its corresponding .di file.This is actually what Andrei proposed as well.
Sep 08 2013
Am 09.09.2013 02:03, schrieb Andrei Alexandrescu:On 9/8/13 5:33 AM, Andrej Mitrovic wrote:The approach should be like in Modula-2 family, only public stuff is allowed in .di files. -- PauloOn 9/8/13, Michel Fortin <michel.fortin michelf.ca> wrote:I have to say I was a lot more in favor of the proposal before this thread. The problem as I see it has two facets: 1. Code duplication 2. Modularity and logistics Regarding (1), we currently force duplication of the entire class layout. My understanding is that this is the way it's done: // file acme.di class A { int x; double y; void fun(); } // file acme.d // cannot import acme.di class A { int x; double y; void fun() { ... } } The fact that acme.d cannot import acme.di is an unforced error of embarrassing proportions and consequence. That should be fixed yesterday no matter how we proceed otherwise. The problem with acme.d not having access to acme.di is that any error in duplicating the layout of A (e.g. swapping x and y or adding some other members etc) will have undefined behavior, and there is no reasonable way for the compiler to check against that. Assuming that bug is fixed, the problem of duplication remains - all state of the class must be duplicated. (I also suspect constructors might need to be white-boxed (i.e. available in the .di) for raw/cooked typechecking, but I'm not sure.) If we go with DIP47, the duplication of state goes away. However we have a distinct problem - modularity, which segues into (2). Allowing out-of-module implementations of individual methods poses additional modularity problems. Consider: // file acme.di class A { int x; double y; void fun(); } private int a; private void gun(); // file acme.d // assume we solve the import problem import acme; void A.fun() { gun(); a = 42; } If A.fun() were defined inside acme.di, it would have access to gun() and a. Defining it outside asks the question - do we allow such access, or not? Intuitively the body of a method should not be all too sensitive to where it's placed, so that argues in favor of visibility. D's module system has always favored a file-granular approach, e.g. private stuff is module-private. This notion of spilling private access outside the file into methods defined in various other files works against that nice tenet. So it looks there's no obvious and obviously good solution. Probably the first one is more sensible. AndreiSo I'd like to suggest this: allow a .d file to "import" its corresponding .di file.This is actually what Andrei proposed as well.
Sep 09 2013
On 9/8/2013 5:03 PM, Andrei Alexandrescu wrote:D's module system has always favored a file-granular approach, e.g. private stuff is module-private. This notion of spilling private access outside the file into methods defined in various other files works against that nice tenet. So it looks there's no obvious and obviously good solution. Probably the first one is more sensible.One solution that has been proposed here (by Manu and perhaps others) is that the outlined functions can only appear inside the same module that the declaration is in. This would resolve the private access problem and the modularity problem.
Sep 09 2013
On 9/9/13 5:12 PM, Walter Bright wrote:On 9/8/2013 5:03 PM, Andrei Alexandrescu wrote:It also reduces the motivation for the thing as it becomes a minor convenience. AndreiD's module system has always favored a file-granular approach, e.g. private stuff is module-private. This notion of spilling private access outside the file into methods defined in various other files works against that nice tenet. So it looks there's no obvious and obviously good solution. Probably the first one is more sensible.One solution that has been proposed here (by Manu and perhaps others) is that the outlined functions can only appear inside the same module that the declaration is in. This would resolve the private access problem and the modularity problem.
Sep 09 2013
On 9/9/2013 5:39 PM, Andrei Alexandrescu wrote:On 9/9/13 5:12 PM, Walter Bright wrote:Yup.This would resolve the private access problem and the modularity problem.It also reduces the motivation for the thing as it becomes a minor convenience.
Sep 09 2013
On 2013-09-09 00:03:11 +0000, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> said:D's module system has always favored a file-granular approach, e.g. private stuff is module-private. This notion of spilling private access outside the file into methods defined in various other files works against that nice tenet.Is the D module system file-granular or module-granular? I always thought the later. Putting the implementation of functions in the .d file while the declarations are in the corresponding .di does not change things much: it's still one module, but it's one module split over two files. It also helps solve another problem: the problem where you're shipping a library and want to force some things to not be inlined. This is needed if the library is to be swapped for another version without having to recompile all client code. You can do this currently by hand-crafting .di files, but it's a pain to keep it manually in sync with the .d file. -- Michel Fortin michel.fortin michelf.ca http://michelf.ca
Sep 09 2013
On Mon, Sep 09, 2013 at 10:09:51PM -0400, Michel Fortin wrote:On 2013-09-09 00:03:11 +0000, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> said:[...] It would be nice if UDAs can somehow be used to mark functions as don't-inline, so that dmd -H produces the correct .di file without requiring manual maintenance. T -- Mediocrity has been pushed to extremes.D's module system has always favored a file-granular approach, e.g. private stuff is module-private. This notion of spilling private access outside the file into methods defined in various other files works against that nice tenet.Is the D module system file-granular or module-granular? I always thought the later. Putting the implementation of functions in the .d file while the declarations are in the corresponding .di does not change things much: it's still one module, but it's one module split over two files. It also helps solve another problem: the problem where you're shipping a library and want to force some things to not be inlined. This is needed if the library is to be swapped for another version without having to recompile all client code. You can do this currently by hand-crafting .di files, but it's a pain to keep it manually in sync with the .d file.
Sep 09 2013
On 10/09/13 04:09, Michel Fortin wrote:Is the D module system file-granular or module-granular? I always thought the later. Putting the implementation of functions in the .d file while the declarations are in the corresponding .di does not change things much: it's still one module, but it's one module split over two files. It also helps solve another problem: the problem where you're shipping a library and want to force some things to not be inlined. This is needed if the library is to be swapped for another version without having to recompile all client code. You can do this currently by hand-crafting .di files, but it's a pain to keep it manually in sync with the .d file.Is it possible to manually craft some parts of the .di file, while being able to rely on the compiler to automatically add any module contents that aren't manually declared? If so it might be the best solution to everyone's concerns.
Sep 10 2013
08-Sep-2013 16:02, Michel Fortin пишет:On 2013-09-07 17:00:05 +0000, Walter Bright <newshound2 digitalmars.com> said:Same here. This was the ugliest point. [snip]Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47About placing the definition in another module, you say that the definition when outlined in another module would have private access to the private members of the module of declaration. Does that mean that the definition has access to the private members of two modules at the same time, the one it is declared in and the one it is defined in? That seems strange to me.I'd like to make a suggestion. If one goal is effectively to allow the implementation of a function to live in a separate file from its declaration, then we already have a mechanism for that: .di files. So I'd like to suggest this: allow a .d file to "import" its corresponding .di file. Then the .d file should only contain the missing definitions for what's declared in the hand-crafted .di file. That'd remove the dubious semantics of making the definition part of another module and would also allow outlining of global functions. And it also matches better the C++ model of header/implementation files.Also, I'd allow outlining only for this specific case where a .di file is imported by a .d file. This way you know for sure when you see a declaration without the definition in a .di file that this declaration is in the corresponding .d file and not anywhere else, making it easier to hunt it down. Example: // test.di module test; class A { void foo(int a, int b); } // test.d import module test; // import declarations from the .di file void A.foo(int a, int b) { // member function definition }With this suggestion it finally becomes sane. -- Dmitry Olshansky
Sep 08 2013
On Sunday, 8 September 2013 at 13:00:11 UTC, Dmitry Olshansky wrote:08-Sep-2013 16:02, Michel Fortin пишет:[Snip]+1Example: // test.di module test; class A { void foo(int a, int b); } // test.d import module test; // import declarations from the .di file void A.foo(int a, int b) { // member function definition }With this suggestion it finally becomes sane.
Sep 08 2013
On Saturday, 7 September 2013 at 17:00:08 UTC, Walter Bright wrote:Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47I'm absolutely against this DIP. This proposal is just going back to the hell of header files again. Why on earth would you emulate C/C++ when D was supposed to be designed taking into account lessons learned from them. This is unnecessary complexity added for the sake of a few programmers who can't get out of C++ mode. I think you need to have a good hard think about *why* header files were introduced into those early languages and then consider if that reason is fine without this. Seriously, this goes against everything you learn as a programmer, nothing should ever be typed twice and then to say that the declaration and implementation could be different just boggles my mind?!?! Great more work! If implemented, i will never used this feature and i will never deal with code that uses it either. I choose D *purely* because it didn't have this header file nonsense. If i find in future i start seeing more and more of this style of D code i would just move on to use something else that doesn't have all this extra baggage and work associated with it. Just because Manu brings it up randomly you decide to create a DIP? In reality this is a documentation issue. Which has already been addressed by DDOC or *.di files. If data exists in one form, and it is needed in another, that's work a computer should do. Not a human! IDE's also give you numerous tools to get class overviews and such. If you are suggesting that you also need these class overviews in code to be viewed on github etc, just use comments. They are as arbitrary and simpler to implement. Honestly this DIP is going backwards, i was under the impression D was going forwards! I am so disappointed.
Sep 08 2013
On Sunday, 8 September 2013 at 12:46:49 UTC, Gary Willoughby wrote:This proposal is just going back to the hell of header files again.It has nothing to do with header files. Or real header file problems.Seriously, this goes against everything you learn as a programmer, nothing should ever be typed twice and then to say that the declaration and implementation could be different just boggles my mind?!?! Great more work!It is no different from overriding `interface` methods in class. From the code structure point of view, declaration is interface. Implementation is implementation. Keeping those separate may sometimes/often be useful. That said, I am strongly against permissive rules proposed in this DIP. It should be similar to overriding rules - any smallest difference between to signatures and program stops compiling. Otherwise it is maintenance hell.
Sep 08 2013
P.S. In general I'd love to have feature feature proposed in DIP47 but its importance is very, _very_ low, right now it is probably the least important DIP in the whole list.
Sep 08 2013
On Sunday, 8 September 2013 at 12:53:11 UTC, Dicebot wrote:Well you've just argued against your first paragraph there. The issue is (as you recognise) the extra complexity introduced with having a declaration and an implementation both of which could be different and/or not clear how they relate. But it goes further than that. If this DIP is implemented and you are working with code written like this you now have to change the code in two places when you want to update a method. Also you now have to find the implementation or declaration which is a total pain when not using an IDE. You now have more files. Longer compilation times. All for what? Not using -D on the command line? Come on! This is entirely different to how overloading works because in that scenario you are explicitly saying in your code this method overrides the parent (or interface) with this one that matches that signature exactly. There is no duplication, it's explicit overriding which is different. Also could you give me any examples of where keeping the declaration separate to the implementation is "sometimes/often fine. I don't think Walter realises how much of a plus point it is for D to not have this 'feature'. I mean if this was implemented and code started appearing written in this style (as it will) why would people choose D over C++ to get stuff done when they both offer the same headaches now?Seriously, this goes against everything you learn as a programmer, nothing should ever be typed twice and then to say that the declaration and implementation could be different just boggles my mind?!?! Great more work!It is no different from overriding `interface` methods in class. From the code structure point of view, declaration is interface. Implementation is implementation. Keeping those separate may sometimes/often be useful. That said, I am strongly against permissive rules proposed in this DIP. It should be similar to overriding rules - any smallest difference between to signatures and program stops compiling. Otherwise it is maintenance hell.
Sep 08 2013
Am 08.09.2013 15:11, schrieb Gary Willoughby:On Sunday, 8 September 2013 at 12:53:11 UTC, Dicebot wrote:the ones that have native compilers by default. The ones that offer interface definitions, like Delphi, Modula-{2,3}, ML family among many others, have a model that D already offers via the .di files. So I also agree this is a step backwards. -- PauloWell you've just argued against your first paragraph there. The issue is (as you recognise) the extra complexity introduced with having a declaration and an implementation both of which could be different and/or not clear how they relate. But it goes further than that. If this DIP is implemented and you are working with code written like this you now have to change the code in two places when you want to update a method. Also you now have to find the implementation or declaration which is a total pain when not using an IDE. You now have more files. Longer compilation times. All for what? Not using -D on the command line? Come on! This is entirely different to how overloading works because in that scenario you are explicitly saying in your code this method overrides the parent (or interface) with this one that matches that signature exactly. There is no duplication, it's explicit overriding which is different. Also could you give me any examples of where keeping the declaration separate to the implementation is "sometimes/often useful". Because IMHO I don't think Walter realises how much of a plus point it is for D to not have this 'feature'. I mean if this was implemented and code started appearing written in this style (as it will) why would people choose D over C++ to get stuff done when they both offer the same headaches now?Seriously, this goes against everything you learn as a programmer, nothing should ever be typed twice and then to say that the declaration and implementation could be different just boggles my mind?!?! Great more work!It is no different from overriding `interface` methods in class. From the code structure point of view, declaration is interface. Implementation is implementation. Keeping those separate may sometimes/often be useful. That said, I am strongly against permissive rules proposed in this DIP. It should be similar to overriding rules - any smallest difference between to signatures and program stops compiling. Otherwise it is maintenance hell.
Sep 08 2013
On Sunday, 8 September 2013 at 13:11:01 UTC, Gary Willoughby wrote:Not really. Issue is cognitive load of matching definition and declaration if they are allowed to be out of sync.That said, I am strongly against permissive rules proposed in this DIP. It should be similar to overriding rules - any smallest difference between to signatures and program stops compiling. Otherwise it is maintenance hell.Well you've just argued against your first paragraph there. The issue is (as you recognise) the extra complexity introduced with having a declaration and an implementation both of which could be different and/or not clear how they relate.But it goes further than that. If this DIP is implemented and you are working with code written like this you now have to change the code in two places when you want to update a method. Also you now have to find the implementation or declaration which is a total pain when not using an IDE.I consider it a minor inconvenience for a certain structural gain.This is entirely different to how overloading works because in that scenario you are explicitly saying in your code this method overrides the parent (or interface) with this one that matches that signature exactly. There is no duplication, it's explicit overriding which is different.overloading != overriding. I am speaking about overriding. From the maintenance point of view this two snippets are identical: --- interface A { void foo(); } class A_prim : A { void foo() { } } --- class A { void foo(); } void A.foo() { } --- Same amount of duplication, same amount of information available for compiler verification.Also could you give me any examples of where keeping the declaration separate to the implementation is "sometimes/often fine.But it C++ once amount of entities grows large enough clear interface overview in header files is basically only way to get familiar quickly with sources. As I have already said it is good for same reasons interfaces are good - easier to abstract away information you shouldn't be aware of when working in large teams.I don't think Walter realises how much of a plus point it is for D to not have this 'feature'. I mean if this was implemented and code started appearing written in this style (as it will) why would people choose D over C++ to get stuff done when they both offer the same headaches now?I don't think it will matter at all. As it was mentioned, usage of such feature tends to be private business of certain project - it won't propagate to yours if you don't use it. And you really underestimate issues of C++ that force programmers to seek other languages. Separation of definition and declaration won't probably be even in top 50.
Sep 08 2013
But it C++ once amount of entities grows large enough clear interface overview in header files is basically only way to get familiar quickly with sources.This is a job for the *documentation* and if documentation is automatically generated (which it is, see '-D') then this argument is moot.I don't think it will matter at all. As it was mentioned, usage of such feature tends to be private business of certain project - it won't propagate to yours if you don't use it.Except when dealing with books, tutorials, third party libraries, pull requests, etc... I dismay.
Sep 08 2013
On Sunday, 8 September 2013 at 15:09:31 UTC, Gary Willoughby wrote:This is a job for the *documentation* and if documentation is automatically generated (which it is, see '-D') then this argument is moot.Documentation is tool to help with cross-project learning. I have never seen one used internally inside the same project. It simply does not work that way, not even close in convenience to matching source organization. Takes more time, uses different information representation other than plain code, is not applicable in some contexts (i.e. git log). Built-in IDE tools are generally better for that but, as I have already said, I am not aware of a single one that does it conveniently enough.Except when dealing with books, tutorials, third party libraries, pull requests, etc...That applies to any other possible feature that may or may not exist in D. What I do mean though is that you shouldn't care how third-party library is organized - for you it remains same import statement and documentation investigation that requires to change nothing in your code flow even if third-party library uses this feature and you do not.
Sep 08 2013
On Sun, Sep 08, 2013 at 02:53:10PM +0200, Dicebot wrote:On Sunday, 8 September 2013 at 12:46:49 UTC, Gary Willoughby wrote:[...][...] I agree that declaration is interface, and implementation is implementation, and that it's good to separate them. What I *don't* agree with is that the interface should be *manually* maintained. There is absolutely no reason, in this day and age, that something so trivial as extracting the interface *automatically* and *reliably* by the compiler, can't be done. Therefore, the *real* solution to this problem is to fix the compiler's .di output to give a proper overview of the class *automatically*, and nicely pretty-printed. Manu has already said that the whole motivation behind wanting this sort of interface/implementation separation was to be able to tell what a class does at a glance. Well guess what? If we clean up the current messy .di generation to produce something decent, then all you have to do is to run dmd -H, and you have your at-a-glance version of the class. No unnecessary complication of the language, no maintenance nightmare, no code duplication, very little implementation effort, and 100% reliable because the .di file is generated straight from the implementation, and therefore by definition is correct. *This* is the correct solution to Manu's issue, IMO. DIP47 is approaching it from a completely wrong angle. Please, let's not go back to the C++ way. We've abandoned that a long time ago, and for good reason. That bridge should've been burned already. T -- INTEL = Only half of "intelligence".Seriously, this goes against everything you learn as a programmer, nothing should ever be typed twice and then to say that the declaration and implementation could be different just boggles my mind?!?! Great more work!It is no different from overriding `interface` methods in class. From the code structure point of view, declaration is interface. Implementation is implementation. Keeping those separate may sometimes/often be useful.
Sep 08 2013
On Monday, 9 September 2013 at 00:43:39 UTC, H. S. Teoh wrote:Therefore, the *real* solution to this problem is to fix the compiler's .di output to give a proper overview of the class *automatically*, and nicely pretty-printed.Yes, that should be superior approach in general though exact usability is very detail-specific - currently relation between .di and .d and not really well-defined and pulling this off will requires its own DIP at the very least. For example, it is not entirely clear to me, what should happen if there are both .di and .d files in the file system at the same time and they have minor difference (remember, it is perfectly legal to tweak .di manually). It is likely, that improving .di tool chain will require similar signature matching verification anyway. Also I am wondering how to differ purely auto-generated .di files (should be updated completely upon build) and ones with manual changes (should be only verified). It is all about small details.
Sep 09 2013
On Monday, 9 September 2013 at 12:28:54 UTC, Dicebot wrote:On Monday, 9 September 2013 at 00:43:39 UTC, H. S. Teoh wrote:In languages like Modula-2, it is a compile error if there are differences. So I would say D compilers should follow the same behavior, unless it is requested to generate .di files automatically, which will then overwrite the corresponding .di files.Therefore, the *real* solution to this problem is to fix the compiler's .di output to give a proper overview of the class *automatically*, and nicely pretty-printed.Yes, that should be superior approach in general though exact usability is very detail-specific - currently relation between .di and .d and not really well-defined and pulling this off will requires its own DIP at the very least. For example, it is not entirely clear to me, what should happen if there are both .di and .d files in the file system at the same time and they have minor difference (remember, it is perfectly legal to tweak .di manually). It is likely, that improving .di tool chain will require similar signature matching verification anyway. Also I am wondering how to differ purely auto-generated .di files (should be updated completely upon build) and ones with manual changes (should be only verified). It is all about small details.
Sep 09 2013
On Mon, Sep 09, 2013 at 03:26:23PM +0200, PauloPinto wrote:On Monday, 9 September 2013 at 12:28:54 UTC, Dicebot wrote:I'd propose to make it such that you *don't* have to tweak the .di manually. Maybe the use of UDAs could help get rid of the need to edit .di by hand, by instructing the compiler what kind of output is desired. Anything that requires hand-tweaking is unreliable and prone to errors and careless bugs. The best way is to have .di completely automated.On Monday, 9 September 2013 at 00:43:39 UTC, H. S. Teoh wrote:Therefore, the *real* solution to this problem is to fix the compiler's .di output to give a proper overview of the class *automatically*, and nicely pretty-printed.Yes, that should be superior approach in general though exact usability is very detail-specific - currently relation between .di and .d and not really well-defined and pulling this off will requires its own DIP at the very least. For example, it is not entirely clear to me, what should happen if there are both .di and .d files in the file system at the same time and they have minor difference (remember, it is perfectly legal to tweak .di manually).I think it is a bug for the .di and .d to have mismatches. For example, I don't see how the following code could be correct: ---module.di--- int func(int x) pure; ---module.d--- int global; int func(int x) { return global; } Any such mismatch should be considered a bug. In fact, the current lax enforcement of matching makes it possible for something to be declared pure safe nothrow in .di, but impure system throwing in .d. I think there has been a few bugs like this in druntime that got fixed. T -- Microsoft is to operating systems & security ... what McDonalds is to gourmet cooking.It is likely, that improving .di tool chain will require similar signature matching verification anyway. Also I am wondering how to differ purely auto-generated .di files (should be updated completely upon build) and ones with manual changes (should be only verified). It is all about small details.In languages like Modula-2, it is a compile error if there are differences. So I would say D compilers should follow the same behavior, unless it is requested to generate .di files automatically, which will then overwrite the corresponding .di files.
Sep 09 2013
Am 09.09.2013 16:36, schrieb H. S. Teoh:On Mon, Sep 09, 2013 at 03:26:23PM +0200, PauloPinto wrote:I should have read your earlier post better. The better approach would then be like the compilers of the Oberon language family do, by generating the interface file when compiling the packages. -- PauloOn Monday, 9 September 2013 at 12:28:54 UTC, Dicebot wrote:I'd propose to make it such that you *don't* have to tweak the .di manually. Maybe the use of UDAs could help get rid of the need to edit .di by hand, by instructing the compiler what kind of output is desired. Anything that requires hand-tweaking is unreliable and prone to errors and careless bugs. The best way is to have .di completely automated.On Monday, 9 September 2013 at 00:43:39 UTC, H. S. Teoh wrote:Therefore, the *real* solution to this problem is to fix the compiler's .di output to give a proper overview of the class *automatically*, and nicely pretty-printed.Yes, that should be superior approach in general though exact usability is very detail-specific - currently relation between .di and .d and not really well-defined and pulling this off will requires its own DIP at the very least. For example, it is not entirely clear to me, what should happen if there are both .di and .d files in the file system at the same time and they have minor difference (remember, it is perfectly legal to tweak .di manually).I think it is a bug for the .di and .d to have mismatches. For example, I don't see how the following code could be correct: ---module.di--- int func(int x) pure; ---module.d--- int global; int func(int x) { return global; } Any such mismatch should be considered a bug. In fact, the current lax enforcement of matching makes it possible for something to be declared pure safe nothrow in .di, but impure system throwing in .d. I think there has been a few bugs like this in druntime that got fixed. TIt is likely, that improving .di tool chain will require similar signature matching verification anyway. Also I am wondering how to differ purely auto-generated .di files (should be updated completely upon build) and ones with manual changes (should be only verified). It is all about small details.In languages like Modula-2, it is a compile error if there are differences. So I would say D compilers should follow the same behavior, unless it is requested to generate .di files automatically, which will then overwrite the corresponding .di files.
Sep 09 2013
On Sunday, 8 September 2013 at 12:46:49 UTC, Gary Willoughby wrote:I'm absolutely against this DIP. This proposal is just going back to the hell of header files again. Why on earth would you emulate C/C++ when D was supposed to be designed taking into account lessons learned from them. This is unnecessary complexity added for the sake of a few programmers who can't get out of C++ mode. I think you need to have a good hard think about *why* header files were introduced into those early languages and then consider if that reason is just fine without this. Seriously, this goes against everything you learn as a programmer, nothing should ever be typed twice and then to say that the declaration and implementation could be different just boggles my mind?!?! Great more work! If implemented, i will never used this feature and i will never deal with code that uses it either. I choose D *purely* because it didn't have this header file nonsense. If i find in future i start seeing more and more of this style of D code i would just move on to use something else that doesn't have all this extra baggage and work associated with it. Just because Manu brings it up randomly you decide to create a DIP? In reality this is a documentation issue. Which has already been addressed by DDOC or *.di files. If data exists in one form, and it is needed in another, that's work a computer should do. Not a human! IDE's also give you numerous tools to get class overviews and such. If you are suggesting that you also need these class overviews in code to be viewed on github etc, just use comments. They are as arbitrary and simpler to implement. Honestly this DIP is going backwards, i was under the impression D was going forwards! I am so disappointed.I totally agree (stating this just in case number of votes matters).
Sep 08 2013
On 08/09/13 22:46, Gary Willoughby wrote:On Saturday, 7 September 2013 at 17:00:08 UTC, Walter Bright wrote:Well said. PeterOutlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47I'm absolutely against this DIP. This proposal is just going back to the hell of header files again. Why on earth would you emulate C/C++ when D was supposed to be designed taking into account lessons learned from them. This is unnecessary complexity added for the sake of a few programmers who can't get out of C++ mode. I think you need to have a good hard think about *why* header files were introduced into those early languages and then consider if do just fine without this. Seriously, this goes against everything you learn as a programmer, nothing should ever be typed twice and then to say that the declaration and implementation could be different just boggles my mind?!?! Great more work! If implemented, i will never used this feature and i will never deal with code that uses it either. I choose D *purely* because it didn't have this header file nonsense. If i find in future i start seeing more and more of this style of D code i would just move on to use something else that doesn't have all this extra baggage and work associated with it. Just because Manu brings it up randomly you decide to create a DIP? In reality this is a documentation issue. Which has already been addressed by DDOC or *.di files. If data exists in one form, and it is needed in another, that's work a computer should do. Not a human! IDE's also give you numerous tools to get class overviews and such. If you are suggesting that you also need these class overviews in code to be viewed on github etc, just use comments. They are as arbitrary and simpler to implement. Honestly this DIP is going backwards, i was under the impression D was going forwards! I am so disappointed.
Sep 08 2013
On 2013-09-07, 19:00, Walter Bright wrote:Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47I like the idea, but I feel the DIP is missing some info: - What happens to UDAs? Do I need to declare them both places? - Why no nested classes/structs? - How do outlined ctors/dtors look? - How does it look in practice? Is this how it works: // foo.d: module foo; class Foo { int bar(); } //foo_impl.d: module foo; import foo; int Foo.bar() { return 3; } - Do the module names have to be the same? - Do I have to import the 'header' module in the implementation modules? - If the module names don't have to be the same: Can I implement the functions in any package? Sub-package? Only the same package? Also, I disagree with these points: - Parameter names should match. I can accept nameless parameters in the declaration, but otherwise they should match. Anything else is an invitation for things to go out of sync. - Default parameter values - either disallow them or enforce that they are the same in both places. - Implementation in a module different from the declaration. .di files provide all the good stuff here, without sending you on a wild goose chase through all your files for that one function your resident junior programmer hid away inside the implementation of a completely different class. Lastly, I want more examples - is this the same for structs and classes? Interfaces? Can I spread the function definitions over several modules? All in all, I would currently vote against. As an aside, I do like the idea of having a nice list of member functions that is statically compared to those actually implemented. This could however be done in different ways. My favorite would be something along these lines: class Foo { interface { float bar(int n) const; Foo clone(); static int qux(); // Compile-time error on this line: declared // function with no implementation. } float bar(int n) const { return 0.0; } Foo clone() { return this; } static int baz() { // Compile-time error on this line: undeclared // function with implementation. return 2; } } For the sake of fueling discussion, I have created a DIP with this suggestion: http://wiki.dlang.org/DIP48 -- Simen
Sep 08 2013
On Saturday, 7 September 2013 at 17:00:08 UTC, Walter Bright wrote:Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47I am against this proposal. The rationale does not convince me we would be getting enough value out of solving this problem. 1. Converting C++ to D This is the strongest argument. Maybe the issue identified here 2. Having an outline of the code DDOC already provides this! And any such limitations should be fixed. This point has several supporting points. a. An IDE is not always available to fold code I never do this, I hate code folding. b. People read their code just as much in github commits, merge/diff windows, emails/chat, etc. And? I could see some value having a summary for signature changes/additions when reviewing commits. For merges this proposal just adds one more line of conflict to deal with. Brining up emails would suggest that you want someone to write down their class signature; instead of having them go to that much work I'd rather ask them to generate the docs and email them to me. Chat, well I think that is a lost cause (I haven't had any code sent to me over chat that I had been glad to have received over chat) I believe requiring the programmer to keep function prototypes in sync is a mistake. I also don't think having this be optional is addressing the issue of those that are for it. When C/C++ programmers talk of the problems header files, they talk of the problems cause by textual replacements and compiled header files. When everyone who doesn't program in C/C++ talk of the problems of header files, they talk about the troubles of writing prototypes twice. By providing this feature as an optional statement, you'll be left with Manu and his team using it, an no one else touching it (Sorry Manu, you're the only one I've seen with a strong conviction for it, I know others will use it too). I realize that we want to make it as painless as possible for Remedy to switch from C++ to D (along with the rest of the game developers). I'm also really glad about the changes which have come from their use/insistence. However I think this is mostly a superficial change which will result in a divide in the community much like property.
Sep 08 2013
On 9/8/13, Jesse Phillips <Jesse.K.Phillips+D gmail.com> wrote:I realize that we want to make it as painless as possible for Remedy to switch from C++ to D (along with the rest of the game developers).FWIW I don't think this has anything to do with Remedy (afaik Manu doesn't work there anymore).
Sep 08 2013
On Sunday, 8 September 2013 at 19:47:06 UTC, Andrej Mitrovic wrote:On 9/8/13, Jesse Phillips <Jesse.K.Phillips+D gmail.com> wrote:I did not realize he had left, but I did realize he was speaking for himself. I'm mostly just using Remedy as the symbol of large C++ code bases/programmers which want to use D because they actually are. I could see Manu's position being common for this user type, I don't think it is common for most D or other language programmers.I realize that we want to make it as painless as possible for Remedy to switch from C++ to D (along with the rest of the game developers).FWIW I don't think this has anything to do with Remedy (afaik Manu doesn't work there anymore).
Sep 09 2013
On 9 September 2013 05:46, Andrej Mitrovic <andrej.mitrovich gmail.com>wrote:On 9/8/13, Jesse Phillips <Jesse.K.Phillips+D gmail.com> wrote:Indeed. These opinions are my own, and I raised it on the merit of our experience last weekend in a 48hour game-dev-jam with a few former colleagues (including one who still works at Remedy). This discussion has come up at remedy in the past, but I don't think this is of particular significance to the remedy workflow; the modules were small enough to not cause issues, at least not as I left it. I believe the scenarios I describe are going to be very typical though, at least in the game-dev context, particularly when larger volumes of D code emerge. I've demonstrated this across 2 separate 48 hour game-jam's now, which simulate the environment of a commercial crunch period quite faithfully.I realize that we want to make it as painless as possible for Remedy to switch from C++ to D (along with the rest of the game developers).FWIW I don't think this has anything to do with Remedy (afaik Manu doesn't work there anymore).
Sep 08 2013
On Monday, 9 September 2013 at 04:00:39 UTC, Manu wrote:On 9 September 2013 05:46, Andrej Mitrovic <andrej.mitrovich gmail.com>wrote:seem to have issues with that, as far as I can tell.On 9/8/13, Jesse Phillips <Jesse.K.Phillips+D gmail.com> wrote:Indeed. These opinions are my own, and I raised it on the merit of our experience last weekend in a 48hour game-dev-jam with a few former colleagues (including one who still works at Remedy). This discussion has come up at remedy in the past, but I don't think this is of particular significance to the remedy workflow; the modules were small enough to not cause issues, at least not as I left it. I believe the scenarios I describe are going to be very typical though, at least in the game-dev context, particularly when larger volumes of D code emerge. I've demonstrated this across 2 separate 48 hour game-jam's now, which simulate the environment of a commercial crunch period quite faithfully.I realize that we want to make it as painless as possible for Remedy to switch from C++ to D (along with the rest of the game developers).FWIW I don't think this has anything to do with Remedy (afaik Manu doesn't work there anymore).
Sep 08 2013
On Monday, 9 September 2013 at 04:00:39 UTC, Manu wrote:Indeed. These opinions are my own, and I raised it on the merit of our experience last weekend in a 48hour game-dev-jam with a few former colleagues (including one who still works at Remedy). This discussion has come up at remedy in the past, but I don't think this is of particular significance to the remedy workflow; the modules were small enough to not cause issues, at least not as I left it. I believe the scenarios I describe are going to be very typical though, at least in the game-dev context, particularly when larger volumes of D code emerge. I've demonstrated this across 2 separate 48 hour game-jam's now, which simulate the environment of a commercial crunch period quite faithfully.I don't believe that typical. We are working with some very big modules, and we have _no_ problems at all regarding that aspect. I think that this is a swift for the discussion: discussing about an issue that it is present _today_ in a commercial user of the product, or a discussion about an a _potential_ problem. The worst part of all this mess it is that the proposal ditches one of the *strong* selling point of D: no code duplication, use documentation if you want an overview. I also strongly disagree that this way of coding is not typical: here at work we are using it without problems with D, and, again, DDocs are the right way. I would also add that also here we have a lot of time pressures for the releases... as in every commercial software company I know of... ;-P - Paolo Invernizzi
Sep 08 2013
I'm opposed to this DIP. It's aimed solely at aiding readability, but having two ways to do something usually detracts from readability. I don't see the point.
Sep 08 2013
Missed the action... Well it's clear this is not a popular proposal. And even to me personally, it's certainly not of critical importance. If there was a single thing I'd like to see *DONE* in D, it would be temporary/r-value->ref args, without question (really, really annoying to work around). For the record, I tend to agree with the arguments of many in the 'against' camp *from a purist point of view*, but the problem remains, and the reason I raised it; this has demonstrated to me and my colleagues on a number of occasions that it is a consistent productivity hindrance. I guess a significant reason my experience seems to differ from many(/most) on this forum, is that they're not in the business of banging out quick throw-away commercial code. The practical reality in my experience in the games industry is this: - Some (perhaps small) percentage of code is tech/foundation code. It is carefully authored, but still typically documented only of the class outline in the header file isn't already self-explanatory (I'm a big fan of self-documenting code). It is to be re-used. - Much (perhaps most) code is rudimentary logic and glue code, or 'game code' as we call it. This tends to be code that is written by more inexperienced programmers and written to tight schedules. It is almost never documented (apart from the occasional inline comments), rarely conforms to some spec (unless it's implementing from foundational interface), and usually exists to serve only the life of this one very specific project, ie, throw-away. It is also almost always logic-intensive code, riddled with switch/if/else constructs that take an awful lot of vertical space, which further magnifies the problem of inline function definitions breaking up the readability of the class outline. Now further, from an absolutely practical point of view, the time that someone unfamiliar with this code has to deal with it in the first place is very likely at 11pm the night before the publisher is demanding a build so they can show it to a bunch of arseholes in fancy suits who will decide if they're going to pay us or not. In C++ there is a very useful tool for unfamiliar programmers to get a good brief overview of the code before they go hacking at it, that is the class outline. We've lost that. And I have demonstrably missed it. People make claims like "write better code, split it up better, document your code better, use the IDE folding", blah blah, but it's simply not the practical reality. The budget and schedule does not typically allow for careful consideration, design, and documentation of such throw away code which glues the project together. The code is what it is, and whether it's written in C++, or D, or lua, it's probably not going to change the nature of this huge volume of crappy code. Code folding doesn't work in foreign editors, communication tools, diff windows; code reviews become more time consuming to approve, and I don't know many programmers that like/use it regardless, even if it may help in some occasions. I think it's bat-shit-crazy to rely on a tool to simply make code readable and easy to understand for a start. I also personally feel code folding alienates me from the code I'm writing. As an author, you quickly gain a feel for the layout of your source file; the flow and shape of the code across the file is kinda picturesque. For me personally, code folding ruins that relationship with my code, and I don't like it. It makes it harder for me to sweep through my file and quickly locate the points of interest that I'm working through. So if I'm not using it in my own code, but I'm required to use it to understand someone else's code... there's a bit of a conflict of interest there. If I'm one of very few voices in favour of class outlines, I'm going to suggest letting this argument sleep until other more serious issues are resolved which people have been waiting on for ages. I certainly want r-values -> ref args to work much more. Keep in mind, I raised this debate as a practical account of last weekend, among a bunch of other issues which were certainly more significant than this one, but this seemed to capture the most attention. It's not the first time it's come up and it'll be back again I'm sure :) I support this DIP, obviously, but I'd suggest perhaps a conservative restriction that definitions should only be allowed to appear within the same module as the declaration. This would seem to simplify things like mangling issues and access rights. In my own use case, I have no reason to spread definitions across files. I just want to see class outlines clearly summarised at the top of the file. This saves time, and time is money. On 8 September 2013 03:00, Walter Bright <newshound2 digitalmars.com> wrote:Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47
Sep 08 2013
On Monday, 9 September 2013 at 03:46:23 UTC, Manu wrote:For the record, I tend to agree with the arguments of many in the 'against' camp *from a purist point of view*, but the problem remains, and the reason I raised it; this has demonstrated to me and my colleagues on a number of occasions that it is a consistent productivity hindrance.I think that you guys being experienced C++ devs makes it worse. As a matter of fact, changing an habit is difficult. I suspect your experience here was in fact a source f increased difficulty. Let me take an actual example. When you put a total newbie in front of a linux or OSX, they usually manage pretty well (considering they are newbies). Now take the average windows user and put it in front of a linux or an OSX, and you'll notice that they have tremendous difficulties to use them. Because everything they know, every expectation they have, get into their way. Anyway, this outline, first, the need of better IDE support (but that isn't big news, I guess we all know that by now). Second some need of interface/implementation separation. For that second, it has been discussed in the thread to improve the di behavior to fit that role. Do think this is a viable approach, and that your team of happy devs would have benefited from that ?
Sep 08 2013
This seems like a waste of time compared to the other complaints Manu brought up(bad IDE/debugger support etc.)
Sep 08 2013
Manu has pointed to some issue behind the obvious issue that will come up again and again unless it's settled once and for all. Let's call it "To please everyone somewhat (and never really enough) - vs - to stick to a clear and well founded concept". My personal view is that we should make D a mixed pickles with lots of "but C++ has that" and then some more gadgets thrown in for good measure. The point that triggered me was "quick and dirty throw away code". Frankly, I don't care batshit about that. Don't get me wrong, Manus desire is doubtlessly valid and I wish him the best of luck to achieve maximum happyness. But I also see that comfort for "throw away code" has a strong tendency to run counter reliability. There's a gazillion C++ compilers, pretty printers, analysers and other tools out there. And C++ has proven to be useful as a throw away code language - just look at mountains of throw away code out there (they won't call it that, of course). trobletickets - or to not even care to), etc, etc. The issue is not to please crowd A or crowd B. The issue is to make up ones mind and to establish a clear definition of what D is meant to be - and than to bloody stick to it. D had "reliability" and "safety" written in quite big letters in it's PR. It's a *major* reason for (sure enough not only) me to be here. Comfort and some luxury is important, too, when you make your living using a tool, sure. But that's no contradiction. One can have both. If I wanted to play a mixture of hide and seek and lottery I'd use C++ in the first place (and would have tools thrown at me). In case I missed it, could someone kindly point me to a more or less binding priorities list of what D is meant to be and in what order of priorities. Maybe it's my fault and I just didn't see then glue some more gadgets to it" I wouldn't be here. Thanks -R
Sep 08 2013
Correction (3rd paragraph) My personal view is that we should *not* make D a mixed pickles with lots of "but C++ has that" and then some more gadgets thrown in for good measure. Sorry -R
Sep 08 2013
On Monday, 9 September 2013 at 04:18:29 UTC, deadalnix wrote:For that second, it has been discussed in the thread to improve the di behavior to fit that role. Do think this is a viable approach, and that your team of happy devs would have benefited from that ?Correct me if I'm wrong, but isn't the problem of using manually-written .di files to separate out class declaration and definition, that you consequently also have to manually include all the declarations of all the other module content?
Sep 09 2013
On 2013-09-09 05:46, Manu wrote:Missed the action... Well it's clear this is not a popular proposal. And even to me personally, it's certainly not of critical importance. If there was a single thing I'd like to see *DONE* in D, it would be temporary/r-value->ref args, without question (really, really annoying to work around).So what's wrong with this approach, that's already working today: class Foo { void foo (); void foo () { } } void main () { auto foo = new Foo; foo.foo(); } BTW, this feature was implemented because you asked for it. -- /Jacob Carlborg
Sep 09 2013
On Monday, 9 September 2013 at 07:00:23 UTC, Jacob Carlborg wrote:On 2013-09-09 05:46, Manu wrote:This is super useful to generate boilerplate from compile time reflection !Missed the action... Well it's clear this is not a popular proposal. And even to me personally, it's certainly not of critical importance. If there was a single thing I'd like to see *DONE* in D, it would be temporary/r-value->ref args, without question (really, really annoying to work around).So what's wrong with this approach, that's already working today: class Foo { void foo (); void foo () { } } void main () { auto foo = new Foo; foo.foo(); } BTW, this feature was implemented because you asked for it.
Sep 09 2013
On 9 September 2013 18:08, deadalnix <deadalnix gmail.com> wrote:On Monday, 9 September 2013 at 07:00:23 UTC, Jacob Carlborg wrote:Which is what I requested it for, and use it very extensively.On 2013-09-09 05:46, Manu wrote:This is super useful to generate boilerplate from compile time reflection !Missed the action... Well it's clear this is not a popular proposal. And even to me personally, it's certainly not of critical importance. If there was a single thing I'd like to see *DONE* in D, it would be temporary/r-value->ref args, without question (really, really annoying to work around).So what's wrong with this approach, that's already working today: class Foo { void foo (); void foo () { } } void main () { auto foo = new Foo; foo.foo(); } BTW, this feature was implemented because you asked for it.
Sep 09 2013
On 2013-09-09 14:36, Manu wrote:Which is what I requested it for, and use it very extensively.Doesn't this already solve what this DIP47 is trying to solve? -- /Jacob Carlborg
Sep 09 2013
On 09/09/13 16:34, Jacob Carlborg wrote:Doesn't this already solve what this DIP47 is trying to solve?See the objection given in my reply to Daniel Murphy.
Sep 09 2013
"Jacob Carlborg" <doob me.com> wrote in message news:l0jrm7$3199$1 digitalmars.com...On 2013-09-09 05:46, Manu wrote:Whoa, I didn't think of applying that to member functions. This seems like the answer. Put your variables and function prototypes at the top of your class. Done.Missed the action... Well it's clear this is not a popular proposal. And even to me personally, it's certainly not of critical importance. If there was a single thing I'd like to see *DONE* in D, it would be temporary/r-value->ref args, without question (really, really annoying to work around).So what's wrong with this approach, that's already working today: class Foo { void foo (); void foo () { } } void main () { auto foo = new Foo; foo.foo(); } BTW, this feature was implemented because you asked for it. -- /Jacob Carlborg
Sep 09 2013
On 09/09/13 15:12, Daniel Murphy wrote:"Jacob Carlborg" <doob me.com> wrote in message news:l0jrm7$3199$1 digitalmars.com...Problem -- what about: class Foo { // Declarations void foo(); int bar(double n); // Definitions void foo() { .... } int bar(double n) { ....} // Whoops! Forgot to include this one in the // declarations list, but it's still accepted // as part of the class void goo() { ... } } A well-defined rule for separating out declarations and definitions would check for that and throw a compile error.So what's wrong with this approach, that's already working today: class Foo { void foo (); void foo () { } } void main () { auto foo = new Foo; foo.foo(); } BTW, this feature was implemented because you asked for it. -- /Jacob CarlborgWhoa, I didn't think of applying that to member functions. This seems like the answer. Put your variables and function prototypes at the top of your class. Done.
Sep 09 2013
On Monday, 9 September 2013 at 13:51:20 UTC, Joseph Rushton Wakeling wrote:On 09/09/13 15:12, Daniel Murphy wrote:[snip]I would argue that it is actually better this way (that not all functions need to be in the declarations list) - its way more flexible! This way you can leave out function declarations that you are not really interested to see from a "functional overview perspective" of the class. AFAIC the cost of implementing this would be way too high for any potential benefit gained from this. And, since Walter already stated that this would "no way be mandatory", the implications are that the compiler would need to enforce it once any one function is declared in the declarations list, but... not enforce it if no functions are declared in the list! Also, leaving it flexible as it is now cannot silently break anything. Worse that can happen is that you may inadvertently try to implement goo() twice (since you may think the missing declaration imply there is no definition), but then the compiler will anyway complain about the duplicate definition. So I agree with Jacob Carlborg - I would also like to know why the above is not already sufficient...?Problem -- what about: class Foo { // Declarations void foo(); int bar(double n); // Definitions void foo() { .... } int bar(double n) { ....} // Whoops! Forgot to include this one in the // declarations list, but it's still accepted // as part of the class void goo() { ... } } A well-defined rule for separating out declarations and definitions would check for that and throw a compile error./Whoa, I didn't think of applying that to member functions. This seems like the answer. Put your variables and function prototypes at the top of your class. Done.
Sep 09 2013
On 09/09/13 18:41, Ettienne Gilbert wrote:I would argue that it is actually better this way (that not all functions need to be in the declarations list) - its way more flexible! This way you can leave out function declarations that you are not really interested to see from a "functional overview perspective" of the class.AFAICS the request is for separation of declaration and definition, so you'd be able to do things like this: class Foo { void foo(); int bar(double x); void goo(int n); // ... etc. } ... and then later in the same file: void Foo.foo() { /* ... function body ... */ } int Foo.bar(double x) { /* ... ditto ... */ } void Foo.goo(int n) { /* ... and so on ... */ } Now, you'd be at liberty to mix declarations and definitions in the _class_ (or struct) declaration, e.g.: class Foo { void foo(); // we define this somewhere else int bar(double x) { /* ... but we define this here */ } // ... etc. } But supposing that a function is declared but not defined inside the class declaration, it should be obligatory that it _is_ defined somewhere else in the file -- and conversely, if a class function is defined somewhere else in the file, it should be obligatory that it's declared in the class declaration. And on top of that, it should be obligatory that the declaration and definition match perfectly. (Note that for any function defined in the class declaration, this is automatically and unavoidably true:-)AFAIC the cost of implementing this would be way too high for any potential benefit gained from this. And, since Walter already stated that this would "no way be mandatory", the implications are that the compiler would need to enforce it once any one function is declared in the declarations list, but... not enforce it if no functions are declared in the list!I am personally inclined to leave it to Walter to decide whether the cost of this is too much. At the very least having this possibility seems to be in line with earlier plans.Also, leaving it flexible as it is now cannot silently break anything. Worse that can happen is that you may inadvertently try to implement goo() twice (since you may think the missing declaration imply there is no definition), but then the compiler will anyway complain about the duplicate definition. So I agree with Jacob Carlborg - I would also like to know why the above is not already sufficient...?Because it allows a situation where you can have an incomplete list of member function declarations for a class or struct, and yet not know that it's incomplete without manual checking -- which I think fails to satisfy the needs Manu has identified. We can reasonably debate whether those needs are worth addressing at all, and whether addressing them comes at too high a cost, but we should be clear on what solutions address them properly and what don't.
Sep 09 2013
On Monday, 9 September 2013 at 17:34:23 UTC, Joseph Rushton Wakeling wrote:On 09/09/13 18:41, Ettienne Gilbert wrote:Ahh, ok. I see where you are coming from - you were evaluating the implications of what Jacob Carlborg proposed if "mixed" in with Walter's DIP47, right? My points though was specifically on the implications of Jacob Carlborg's proposal "in isolation" i.e. as an acceptable alternative to DIP47. And, AFAICS, Jacob posed the question to Manu this way as well (I think - but maybe Jacob can confirm/deny). If you mix the 2 I agree with you for the most part. But the real question for me (and I suspect Jacob) is this: Is this...I would argue that it is actually better this way (that not all functions need to be in the declarations list) - its way more flexible! This way you can leave out function declarations that you are not really interested to see from a "functional overview perspective" of the class.AFAICS the request is for separation of declaration and definition, so you'd be able to do things like this: class Foo { void foo(); int bar(double x); void goo(int n); // ... etc. } ... and then later in the same file: void Foo.foo() { /* ... function body ... */ } int Foo.bar(double x) { /* ... ditto ... */ } void Foo.goo(int n) { /* ... and so on ... */ } Now, you'd be at liberty to mix declarations and definitions in the _class_ (or struct) declaration, e.g.: class Foo { void foo(); // we define this somewhere else int bar(double x) { /* ... but we define this here */ } // ... etc. } But supposing that a function is declared but not defined inside the class declaration, it should be obligatory that it _is_ defined somewhere else in the file -- and conversely, if a class function is defined somewhere else in the file, it should be obligatory that it's declared in the class declaration. And on top of that, it should be obligatory that the declaration and definition match perfectly. (Note that for any function defined in the class declaration, this is automatically and unavoidably true:-)class Foo { void foo(); int bar(double x); void goo(int n); // ... etc. } void Foo.foo() { /* ... function body ... */ } int Foo.bar(double x) { /* ... ditto ... */ } void Foo.goo(int n) { /* ... and so on ... */ }...really so much better than this?class Foo { void foo(); int bar(double x); void goo(int n); // ... etc. void foo() { /* ... function body ... */ } int bar(double x) { /* ... ditto ... */ } void goo(int n) { /* ... and so on ... */ } }Granted, this sacrifices some flexibility from DIP47. But these are of such dubious quality/use/potential pitfalls (as discussed in this thread), that I hardly think DIP47 is worth implementing as a result. Especially since, what we currently have (as shown by Carl,) already gives you arguably 90%+ (IMHO) of Manu's request for (I quote) "You don't need to see the function bodies in the class definition, you want to quickly see what a class has and does". Does it really matter that the function definitions are also present inside the class definition, as long as you can also see "what a class has and does" in the declarations list at the top? Of course fixing the current issues with .di generation is important as a separate issue.
Sep 09 2013
On 09/09/13 23:45, Ettienne Gilbert wrote:Ahh, ok. I see where you are coming from - you were evaluating the implications of what Jacob Carlborg proposed if "mixed" in with Walter's DIP47, right?The code that Jacob proposed is currently legit D code and that isn't going to change -- and if that solution works for you (or other people), great. However, I don't think it completely address the requirements the DIP is attempting to meet. In my previous email I was simply trying to show that implementing new functionality to allow class functions to be defined outside the class declaration, wouldn't be incompatible with writing code like Jacob's (although I don't see why anyone would mix the approaches in this way). In terms of where I'm coming from, it's more in line with Dicebot -- I think both of us have been focused on the simultaneous usefulness and necessity of being able to check declaration against definition for class member functions that are declared and defined separately.If you mix the 2 I agree with you for the most part. But the real question for me (and I suspect Jacob) is this: Is this...The point is about being able to check that your declaration list has a one-to-one match with your definition list. If you just decide to place declarations at the top of the class definition, and definitions lower down, you run the risk of accidentally missing one of the defined functions out of the declaration list: class Foo { // Declarations void foo(); void bar(); // Definitions void foo() { ... } void bar() { ... } void goo() { ... } // Whoops! This is part of the class API but // we forgot to include it in our declaration // list ... } But Andrej Mitrovic has suggested a means to implement those kind of introspective checks at compile-time, so maybe it's not as urgent as I first thought. (My one caveat is that I think solutions based on programmer virtue, like remembering to insert a line: "mixin VerifyDeclarations;" into a class, are generally less nice than solutions where the compiler does your checking for you without you having to ask.)[ ... snip code ...]...really so much better than this?[ ... snip again ...]Granted, this sacrifices some flexibility from DIP47. But these are of such dubious quality/use/potential pitfalls (as discussed in this thread), that I hardly think DIP47 is worth implementing as a result. Especially since, what we currently have (as shown by Carl,) already gives you arguably 90%+ (IMHO) of Manu's request for (I quote) "You don't need to see the function bodies in the class definition, you want to quickly see what a class has and does". Does it really matter that the function definitions are also present inside the class definition, as long as you can also see "what a class has and does" in the declarations list at the top?Of course fixing the current issues with .di generation is important as a separate issue.Yes, absolutely.
Sep 09 2013
On 2013-09-10 08:49, Joseph Rushton Wakeling wrote:(My one caveat is that I think solutions based on programmer virtue, like remembering to insert a line: "mixin VerifyDeclarations;" into a class, are generally less nice than solutions where the compiler does your checking for you without you having to ask.)That shouldn't be necessary, see my reply to Andrej: http://forum.dlang.org/thread/l0fm2o$2uat$1 digitalmars.com?page=14#post-l0mjh4:2418bp:241:40digitalmars.com -- /Jacob Carlborg
Sep 10 2013
On 2013-09-09 23:45, Ettienne Gilbert wrote:Ahh, ok. I see where you are coming from - you were evaluating the implications of what Jacob Carlborg proposed if "mixed" in with Walter's DIP47, right? My points though was specifically on the implications of Jacob Carlborg's proposal "in isolation" i.e. as an acceptable alternative to DIP47. And, AFAICS, Jacob posed the question to Manu this way as well (I think - but maybe Jacob can confirm/deny).Yes, my suggestion would be an alternative to DIP47. -- /Jacob Carlborg
Sep 10 2013
On Monday, September 09, 2013 15:51:11 Joseph Rushton Wakeling wrote:On 09/09/13 15:12, Daniel Murphy wrote:Walter's proposal would be no different on that count. All that the DIP is proposing is a way to define a member function outside of a class. That requires that it already be declared in the class, but it doesn't make it so that you can't define other functions directly in the class. - Jonathan M Davis"Jacob Carlborg" <doob me.com> wrote in message news:l0jrm7$3199$1 digitalmars.com...Problem -- what about: class Foo { // Declarations void foo(); int bar(double n); // Definitions void foo() { .... } int bar(double n) { ....} // Whoops! Forgot to include this one in the // declarations list, but it's still accepted // as part of the class void goo() { ... } } A well-defined rule for separating out declarations and definitions would check for that and throw a compile error.So what's wrong with this approach, that's already working today: class Foo { void foo (); void foo () { } } void main () { auto foo = new Foo; foo.foo(); } BTW, this feature was implemented because you asked for it. -- /Jacob CarlborgWhoa, I didn't think of applying that to member functions. This seems like the answer. Put your variables and function prototypes at the top of your class. Done.
Sep 09 2013
On 09/09/13 21:30, Jonathan M Davis wrote:Walter's proposal would be no different on that count. All that the DIP is proposing is a way to define a member function outside of a class. That requires that it already be declared in the class, but it doesn't make it so that you can't define other functions directly in the class.Sure. The thing is that if you can only declare and define within the class, this potential problem is unavoidable -- you can _never_ be certain that your list of declarations is complete. If on the other hand you can define outside the class declaration, then you can make it a design decision to only declare within the class declaration, and to define elsewhere in the module. In that case it should be possible to guarantee a safety check that what's declared is defined and what's defined is declared -- and that the two match precisely.
Sep 09 2013
On 9/9/13, Joseph Rushton Wakeling <joseph.wakeling webdrake.net> wrote:A well-defined rule for separating out declarations and definitions would check for that and throw a compile error.You could use compile-time introspection where the API would look like: class C { void foo(); void foo() { } void bar() { } // missing declaration mixin VerifyDeclarations; } And this would statically assert if there's a missing declaration for a definition. I think this might even be doable with the current introspection features, although I'm not sure whether we have a way to determine if something is a declaration or a definition. Certainly such a trait could easily be added to the compiler.
Sep 09 2013
On 2013-09-09 22:01, Andrej Mitrovic wrote:You could use compile-time introspection where the API would look like: class C { void foo(); void foo() { } void bar() { } // missing declaration mixin VerifyDeclarations; } And this would statically assert if there's a missing declaration for a definition. I think this might even be doable with the current introspection features, although I'm not sure whether we have a way to determine if something is a declaration or a definition. Certainly such a trait could easily be added to the compiler.A mixin should not be necessary. RTInfo can be used for that: https://github.com/D-Programming-Language/druntime/blob/master/src/object.di#L575 The compiler will instantiate RTInfo once for each user defined type. The only downside is that you need to modify druntime. -- /Jacob Carlborg
Sep 10 2013
On 10/09/13 09:59, Jacob Carlborg wrote:A mixin should not be necessary. RTInfo can be used for that: https://github.com/D-Programming-Language/druntime/blob/master/src/object.di#L575 The compiler will instantiate RTInfo once for each user defined type. The only downside is that you need to modify druntime.Can you explain a bit more about how that works? As long as it can provide a guarantee that everything declared has a definition, and everything defined has a declaration -- and that they match! -- then I think this is probably the solution required. What I mean is -- it needs to ensure that the issue identified in a couple of my earlier posts will be flagged and prevented: http://forum.dlang.org/post/mailman.1104.1378795749.1719.digitalmars-d puremagic.com However, I'm suspicious of anything that would require the programmer to be "virtuous" and manually ensure that those checks take place, rather than the checks simply being a natural part of the compilation process.
Sep 10 2013
On 2013-09-10 10:49, Joseph Rushton Wakeling wrote:Can you explain a bit more about how that works?The "object" module, part of druntime defines a template with the name "RTInfo". That template will be instantiated with each user defined type. Currently RTInfo doesn't do anything: template RTInfo(T) { enum RTInfo = cast(void*)0x12345678; } https://github.com/D-Programming-Language/druntime/blob/master/src/object.di#L575 If you replace that template with something like: template RTInfo(T) { enum RTInfo = verifyDeclarations!(T); } verifyDeclarations would look something like this, in pseudo code: void* verifyDeclarations (T) () { static if (is(T == class)) { foreach (member ; methods!(T)) { static if (!hasDefinition!(member)) static assert (false, "The member '" fullyQualifiedName!(T) ~ "." ~ member.stringof ~ "' doesn't have a definition"); } } return null; }As long as it can provide a guarantee that everything declared has a definition, and everything defined has a declaration -- and that they match! -- then I think this is probably the solution required. What I mean is -- it needs to ensure that the issue identified in a couple of my earlier posts will be flagged and prevented: http://forum.dlang.org/post/mailman.1104.1378795749.1719.digitalmars-d puremagic.com However, I'm suspicious of anything that would require the programmer to be "virtuous" and manually ensure that those checks take place, rather than the checks simply being a natural part of the compilation process.The idea is then you build a tool that "compiles" all your files which uses druntime with the above implementation of RTInfo. -- /Jacob Carlborg
Sep 10 2013
On 10/09/13 14:12, Jacob Carlborg wrote:verifyDeclarations would look something like this, in pseudo code: void* verifyDeclarations (T) () { static if (is(T == class)) { foreach (member ; methods!(T)) { static if (!hasDefinition!(member)) static assert (false, "The member '" fullyQualifiedName!(T) ~ "." ~ member.stringof ~ "' doesn't have a definition"); } } return null; }But the problem that I identified wasn't the possibility of members that are declared but not defined. It was the possibility of members that are defined but not included in the top-of-the-class list of separate declarations. The whole point is that both the author and the recipient of the code should be able to verify at compile-time that the list of declarations is an accurate summary of the class. I imagine you could define a verifySeparateDeclarations that would indeed enforce that (for every declaration a definition, and for every definition a separate declaration) but that would have its own issues.
Sep 10 2013
On 9/10/13, Jacob Carlborg <doob me.com> wrote:A mixin should not be necessary. RTInfo can be used for that: https://github.com/D-Programming-Language/druntime/blob/master/src/object.di#L575The mixin was demonstrated for convenience so you don't have to manually type in the class name (or use typeof(this)).
Sep 10 2013
On 09/09/13 22:01, Andrej Mitrovic wrote:You could use compile-time introspection where the API would look like: class C { void foo(); void foo() { } void bar() { } // missing declaration mixin VerifyDeclarations; } And this would statically assert if there's a missing declaration for a definition. I think this might even be doable with the current introspection features, although I'm not sure whether we have a way to determine if something is a declaration or a definition. Certainly such a trait could easily be added to the compiler.Fair enough. In that case I guess my objections don't really hold water.
Sep 09 2013
On Monday, 9 September 2013 at 03:46:23 UTC, Manu wrote:People make claims like "write better code, split it up better, document your code better, use the IDE folding", blah blah, but it's simply not the practical reality. The budget and schedule does not typically allow for careful consideration, design, and documentation of such throw away code which glues the project together.I think DDOC should be improved to handle this scenario. Being able to generate docs with undocumented members would be great for internal development of the module. I realize that doesn't address all your problems, but I think that is the correct direction.
Sep 09 2013
On 09/09/13 20:05, Jesse Phillips wrote:I think DDOC should be improved to handle this scenario. Being able to generate docs with undocumented members would be great for internal development of the module. I realize that doesn't address all your problems, but I think that is the correct direction.Better DDoc is always going to be nice, but come on -- that doesn't address the issue of looking at code in a diff or a copy-paste via chat software, and in the scenarios Manu has described, no one's going to have time to write documentation comments. OK, you could have a DDoc setting to at least _list_ all elements of class interfaces etc., even if there's no doc comment, but that doesn't address the other factors.
Sep 09 2013
On Monday, 9 September 2013 at 18:23:21 UTC, Joseph Rushton Wakeling wrote:Better DDoc is always going to be nice, but come on -- that doesn't address the issue of looking at code in a diff or a copy-paste via chat software, and in the scenarios Manu has described, no one's going to have time to write documentation comments.This is such a poor argument for changing and further complicating the language. There are so many ways to get a class overview *even* in plain text. I can't honestly believe this is the catalyst for this DIP.
Sep 09 2013
On 09/09/13 20:30, Gary Willoughby wrote:This is such a poor argument for changing and further complicating the language. There are so many ways to get a class overview *even* in plain text. I can't honestly believe this is the catalyst for this DIP.I can understand anyone feeling that the costs aren't worth it, but I don't think it's ever good to dismiss battle experience of skilled developers, especially when it comes from scenarios that you or I may not have personal experience of. I don't mind finding out I'm wrong (actually, I'd quite like to be in this case:-), but I'd like to understand how I could get the class overview in the plain-text scenarios described in my previous email.
Sep 09 2013
On Monday, 9 September 2013 at 18:23:21 UTC, Joseph Rushton Wakeling wrote:On 09/09/13 20:05, Jesse Phillips wrote:I hope you realize you've restated what I said? Include undocumented members, won't address all problems. There can definitely be value for diff; if you're objective is to find modifications to public API. I don't want to have a class pasted in a chat window, with or without function definitions (Unavoidable I know). If I need to do anything complicated with that information, into a text editor it goes (and on linux this would be in /tmp and easy to compile docs for; Windows, I just hope I'm not there).I think DDOC should be improved to handle this scenario. Being able to generate docs with undocumented members would be great for internal development of the module. I realize that doesn't address all your problems, but I think that is the correct direction.Better DDoc is always going to be nice, but come on -- that doesn't address the issue of looking at code in a diff or a copy-paste via chat software, and in the scenarios Manu has described, no one's going to have time to write documentation comments. OK, you could have a DDoc setting to at least _list_ all elements of class interfaces etc., even if there's no doc comment, but that doesn't address the other factors.
Sep 10 2013
On Mon, Sep 09, 2013 at 08:23:07PM +0200, Joseph Rushton Wakeling wrote:On 09/09/13 20:05, Jesse Phillips wrote:Auto-generation of .di files solves this problem. (Provided we fix the mess that is the current implementation of .di generation, of course.) T -- It said to install Windows 2000 or better, so I installed Linux instead.I think DDOC should be improved to handle this scenario. Being able to generate docs with undocumented members would be great for internal development of the module. I realize that doesn't address all your problems, but I think that is the correct direction.Better DDoc is always going to be nice, but come on -- that doesn't address the issue of looking at code in a diff or a copy-paste via chat software, and in the scenarios Manu has described, no one's going to have time to write documentation comments. OK, you could have a DDoc setting to at least _list_ all elements of class interfaces etc., even if there's no doc comment, but that doesn't address the other factors.
Sep 09 2013
On 9/9/13 12:35 PM, H. S. Teoh wrote:Auto-generation of .di files solves this problem. (Provided we fix the mess that is the current implementation of .di generation, of course.)OK, so what's the trouble with .di generation today? Andrei
Sep 09 2013
On Monday, 9 September 2013 at 21:20:34 UTC, Andrei Alexandrescu wrote:On 9/9/13 12:35 PM, H. S. Teoh wrote:Related to this: Is semantic information necessary for .di generation, or can it be built from the AST?Auto-generation of .di files solves this problem. (Provided we fix the mess that is the current implementation of .di generation, of course.)OK, so what's the trouble with .di generation today? Andrei
Sep 09 2013
On Mon, Sep 09, 2013 at 02:20:34PM -0700, Andrei Alexandrescu wrote:On 9/9/13 12:35 PM, H. S. Teoh wrote:[...] 1) It could be pretty-printed (it currently tries to, but it's not very pretty). 2) Eponymous templates look ugly. I.e., this: template MyClass(T) { class MyClass { ... } } instead of: class MyClass(T) { ... } 3) It loses manual formatting, like turning this: writeln("This is a very very long string "~ "broken across multiple lines"); into: writeln("This is a very very long string "~ "broken across multiple lines"); which detracts from readability when the expression is very long. This also applies to signature contraints, which are just concatenated onto an already-over-long function signature. A related issue concerns reordering of function qualifiers, e.g., if your code looks like this: void func(int a) pure safe nothrow { ... } it gets turned into: pure safe nothrow void func(int a) { ... } which is a bit jarring since when reviewing the .di file you may be expecting what you wrote, not what the compiler thinks you should have written. 4) It includes template function bodies inline, which means it fails to serve as a class-at-a-glance format in that case. It could use the declare-first, implement-later approach some have suggested, i.e.: class MyTemplateClass(T) { void member(); ... void member() { /* implementation here */ } } instead of the current: class MyTemplateClass(T) { void member() { /* implementation here */ } ... } 5) Private templates are included along with public ones: to achieve Manu's goal of interface-at-a-glance, private members and private templates should be put at the end of the file, rather than in the midst of the public symbols. Though this is a minor issue; you could just reorder code in the source manually. There may be a few other points I missed. But all in all, it's not *quite* ready to serve as an interface-at-a-glance format yet. I didn't find any inherent limitations, though (except possibly for templated private members, but those can be largely alleviated by suitable reordering), so once these issues are addressed, we should be good to go. T -- In theory, there is no difference between theory and practice.Auto-generation of .di files solves this problem. (Provided we fix the mess that is the current implementation of .di generation, of course.)OK, so what's the trouble with .di generation today?
Sep 09 2013
On 9/9/13 4:43 PM, H. S. Teoh wrote:On Mon, Sep 09, 2013 at 02:20:34PM -0700, Andrei Alexandrescu wrote:[more good stuff] Please paste all of the above into a bug report! AndreiOn 9/9/13 12:35 PM, H. S. Teoh wrote:[...] 1) It could be pretty-printed (it currently tries to, but it's not very pretty).Auto-generation of .di files solves this problem. (Provided we fix the mess that is the current implementation of .di generation, of course.)OK, so what's the trouble with .di generation today?
Sep 09 2013
On Mon, Sep 09, 2013 at 05:39:06PM -0700, Andrei Alexandrescu wrote:On 9/9/13 4:43 PM, H. S. Teoh wrote:[...] http://d.puremagic.com/issues/show_bug.cgi?id=11003 T -- "I suspect the best way to deal with procrastination is to put off the procrastination itself until later. I've been meaning to try this, but haven't gotten around to it yet. " -- swrOn Mon, Sep 09, 2013 at 02:20:34PM -0700, Andrei Alexandrescu wrote:[more good stuff] Please paste all of the above into a bug report!On 9/9/13 12:35 PM, H. S. Teoh wrote:[...] 1) It could be pretty-printed (it currently tries to, but it's not very pretty).Auto-generation of .di files solves this problem. (Provided we fix the mess that is the current implementation of .di generation, of course.)OK, so what's the trouble with .di generation today?
Sep 09 2013
Main issue of .di files that make them useless for anything but providing declarations for blobs is that there is absolutely zero compiler control of .d and .di relation. Fixing this either implies providing good control of how .di is generated via compiler flags (and prohibiting manual modifications) or implementing good part of DIP47 restricted to .di/.d combo (all the signature verifications). Also it does not seem defined in spec how lookup should happen if both .d and .di are present, and, for example, .di has only declaration. Will compiler check .d for possible inlining if it is present? I think that .di should always contain only declarations and be _always_ auto-generated by compiler with strict 1-to-1 matching signatures. Then .d are also queried if implementation is needed/considered - but those are not mandatory (aside from templates). Blob bindings distributed may then simply have a stripped down version of .d file (similar to what is now generated by dmd -H). Key point here is that .di needs _always_ to be there, with hard guarantees that it is in sync with actual code. Add even one more extra step of getting those and it becomes considerably less convenient than C++-like overview.
Sep 10 2013
On 9/10/13, Dicebot <public dicebot.lv> wrote:Main issue of .di files that make them useless for anything but providing declarations for blobs is that there is absolutely zero compiler control of .d and .di relation.Yeah, I think we could attempt to provide an alternative to DIP47 by adding a compiler flag that verifies .d implementations match .di declarations. We don't even have to make the .d files explicitly import the .di files like Andrei proposed.
Sep 10 2013
On Tuesday, 10 September 2013 at 13:32:14 UTC, Andrej Mitrovic wrote:On 9/10/13, Dicebot <public dicebot.lv> wrote:Please, no compiler flags. It should be default behavior. We are speaking about fundamental binary-level application sanity here.Main issue of .di files that make them useless for anything but providing declarations for blobs is that there is absolutely zero compiler control of .d and .di relation.Yeah, I think we could attempt to provide an alternative to DIP47 by adding a compiler flag that verifies .d implementations match .di declarations. We don't even have to make the .d files explicitly import the .di files like Andrei proposed.
Sep 10 2013
On 09/09/13 21:35, H. S. Teoh wrote:Auto-generation of .di files solves this problem. (Provided we fix the mess that is the current implementation of .di generation, of course.)Maybe you'll think I'm being too picky, but I don't think that generated files of any kind (whether .di or Ddoc) really help with the situations Manu was describing. If you want to be able to look at the latest diff and see at a glance how the class API has changed, a generated file doesn't help (unless you store that generated file in the VCS, but I've always understood that to be bad practice).
Sep 09 2013
On 09/09/2013 04:46, Manu wrote:Missed the action... Well it's clear this is not a popular proposal. And even to me personally, it's certainly not of critical importance. If there was a single thing I'd like to see *DONE* in D, it would be temporary/r-value->ref args, without question (really, really annoying to work around). For the record, I tend to agree with the arguments of many in the 'against' camp *from a purist point of view*, but the problem remains, and the reason I raised it; this has demonstrated to me and my colleagues on a number of occasions that it is a consistent productivity hindrance. I guess a significant reason my experience seems to differ from many(/most) on this forum, is that they're not in the business of banging out quick throw-away commercial code. The practical reality in my experience in the games industry is this: - Some (perhaps small) percentage of code is tech/foundation code. It is carefully authored, but still typically documented only of the class outline in the header file isn't already self-explanatory (I'm a big fan of self-documenting code). It is to be re-used. - Much (perhaps most) code is rudimentary logic and glue code, or 'game code' as we call it. This tends to be code that is written by more inexperienced programmers and written to tight schedules. It is almost never documented (apart from the occasional inline comments), rarely conforms to some spec (unless it's implementing from foundational interface), and usually exists to serve only the life of this one very specific project, ie, throw-away. It is also almost always logic-intensive code, riddled with switch/if/else constructs that take an awful lot of vertical space, which further magnifies the problem of inline function definitions breaking up the readability of the class outline. Now further, from an absolutely practical point of view, the time that someone unfamiliar with this code has to deal with it in the first place is very likely at 11pm the night before the publisher is demanding a build so they can show it to a bunch of arseholes in fancy suits who will decide if they're going to pay us or not. In C++ there is a very useful tool for unfamiliar programmers to get a good brief overview of the code before they go hacking at it, that is the class outline. We've lost that. And I have demonstrably missed it. People make claims like "write better code, split it up better, document your code better, use the IDE folding", blah blah, but it's simply not the practical reality. The budget and schedule does not typically allow for careful consideration, design, and documentation of such throw away code which glues the project together. The code is what it is, and whether it's written in C++, or D, or lua, it's probably not going to change the nature of this huge volume of crappy code. Code folding doesn't work in foreign editors, communication tools, diff windows; code reviews become more time consuming to approve, and I don't know many programmers that like/use it regardless, even if it may help in some occasions. I think it's bat-shit-crazy to rely on a tool to simply make code readable and easy to understand for a start. I also personally feel code folding alienates me from the code I'm writing. As an author, you quickly gain a feel for the layout of your source file; the flow and shape of the code across the file is kinda picturesque. For me personally, code folding ruins that relationship with my code, and I don't like it. It makes it harder for me to sweep through my file and quickly locate the points of interest that I'm working through. So if I'm not using it in my own code, but I'm required to use it to understand someone else's code... there's a bit of a conflict of interest there. If I'm one of very few voices in favour of class outlines, I'm going to suggest letting this argument sleep until other more serious issues are resolved which people have been waiting on for ages. I certainly want r-values -> ref args to work much more. Keep in mind, I raised this debate as a practical account of last weekend, among a bunch of other issues which were certainly more significant than this one, but this seemed to capture the most attention. It's not the first time it's come up and it'll be back again I'm sure :) I support this DIP, obviously, but I'd suggest perhaps a conservative restriction that definitions should only be allowed to appear within the same module as the declaration. This would seem to simplify things like mangling issues and access rights. In my own use case, I have no reason to spread definitions across files. I just want to see class outlines clearly summarised at the top of the file. This saves time, and time is money. On 8 September 2013 03:00, Walter Bright <newshound2 digitalmars.com <mailto:newshound2 digitalmars.com>> wrote: Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47Ok, basically you are trying to add some language complexity just to help with the use case where you can't, or is not convenient, to use an IDE. (communication tools, diff viewers, etc.) I don't agree with this DIP then. Let' see: A) does this use case merit these languages changes? B) is this proposal short-sighted in what it improves? Regarding point B, I think that is the case. Reviewing code outside of an IDE is always going to be a limiting experience. (you don't see compilation errors/warnings, you can't do open definition, you can't see documentation hovers, etc.) And some of these limits you cannot work-around by making changes to the language and the code of your project. Consider this example, imagine you want to see the outline of a class (signatures of the members), like you sugest, but including the members of superclasses *as well* (this is a feature supported by some IDEs, and fairly useful for large hierarchical classes). How would you address this with a language feature? You can't, unless you want your DIP to allow the source class outline to include the superclass member signatures as well, but that would just be an insane amount of bloat and code duplication. :S BTW, some IDEs (JDT for example) support semantic functionality (code complete, etc) in their diff viewers, at least if one of the sides you are comparing with is your workspace code. -- Bruno Medeiros - Software Engineer
Sep 16 2013
On 2013-09-07 19:00, Walter Bright wrote:Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47What's wrong with the code below, that works today: class Foo { void foo (); void foo () { writeln("Foo.foo"); } } void main () { auto foo = new Foo; foo.foo(); } -- /Jacob Carlborg
Sep 09 2013
On Saturday, 7 September 2013 at 17:00:08 UTC, Walter Bright wrote:Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47--------------------------------------- unit Unit1; {$mode objfpc}{$H+} interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls; type { TForm1 } TForm1 = class(TForm) Button1: TButton; Memo1: TMemo; procedure Button1Click(Sender: TObject); private { private declarations } public { public declarations } procedure ChangeTitle(x:string); procedure ChangeOtherTitle(x: string); end; var Form1: TForm1; implementation {$R *.lfm} { TForm1 } procedure TForm1.Button1Click(Sender: TObject); begin ChangeTitle('test'); end; procedure TForm1.ChangeTitle(x: string); begin Memo1.Lines.Add(x); end; procedure TForm1.ChangeOtherTitle(x: string); begin Memo1.Lines.Add(x); end; end. Here is how it looks like in Lazarus. In the class definition you type the declaration. public { public declarations } procedure ChangeTitle(x:string); Then you press "control shift c" this will create the empty implementation. Use "control shift up" to cycle between the interface section and the implementation section. There are two keywords "interface" and "implementation" to separate the two sections. Honestly. There is not much typing going on. If you go want to go the the next procedure in the implementation section it is faster to go "control shift up" back to the interface section. And then go to the next method and go back "control shift up" to the implentation section than to press the arrow down button until you are at the next method. Lazarus does not accept changes in the name of the parameter.
Sep 09 2013
On 09/09/13 05:46, Manu wrote:For the record, I tend to agree with the arguments of many in the 'against' camp *from a purist point of view*, but the problem remains, and the reason I raised it; this has demonstrated to me and my colleagues on a number of occasions that it is a consistent productivity hindrance.For what it's worth, I think this kind of baptism-by-fire practical experience is very valuable, and that it's worth considering carefully even if the final decision is not to implement the requested feature. Question: do you have any access to information about similar short-deadline separation of declaration and definition, and how devs using those languages cope with that? It might offer an alternative solution that no one here has thought of.I support this DIP, obviously, but I'd suggest perhaps a conservative restriction that definitions should only be allowed to appear within the same module as the declaration. This would seem to simplify things like mangling issues and access rights. In my own use case, I have no reason to spread definitions across files. I just want to see class outlines clearly summarised at the top of the file. This saves time, and time is money.I think the conservative approach is probably correct -- the class outline and the function definitions should have to be in the same module, and the outline and definitions should match precisely. Any mismatch (including in variable names)? Compile error. A function in the outline that isn't implemented? Compile error. A function implemented that isn't in the outline? Compile error. That should greatly reduce the possibility of error caused by code duplication. Then it simply becomes a question of deciding if the manual labour of writing separate outlines and definitions is worth it. I guess this is probably somewhere where a tool really _can_ be useful, to ensure that the definitions and the outline stay in sync. Writing D code in this way should probably be disapproved of in the D style guidelines, but with the proviso that it's there for the circumstances where it really is useful.
Sep 09 2013
On Monday, 9 September 2013 at 14:22:15 UTC, Joseph Rushton Wakeling wrote:Then it simply becomes a question of deciding if the manual labour of writing separate outlines and definitions is worth it. I guess this is probably somewhere where a tool really _can_ be useful, to ensure that the definitions and the outline stay in sync. Writing D code in this way should probably be disapproved of in the D style guidelines, but with the proviso that it's there for the circumstances where it really is useful.Very well spoken, this is exactly how I see it.
Sep 09 2013
On 09/09/13 16:29, Dicebot wrote:On Monday, 9 September 2013 at 14:22:15 UTC, Joseph Rushton Wakeling wrote:Thank you! :-)Then it simply becomes a question of deciding if the manual labour of writing separate outlines and definitions is worth it. I guess this is probably somewhere where a tool really _can_ be useful, to ensure that the definitions and the outline stay in sync. Writing D code in this way should probably be disapproved of in the D style guidelines, but with the proviso that it's there for the circumstances where it really is useful.Very well spoken, this is exactly how I see it.
Sep 10 2013
On Monday, 9 September 2013 at 14:22:15 UTC, Joseph Rushton Wakeling wrote:Question: do you have any access to information about similar short-deadline programming activity using other languages and definition, and how devs using those languages cope with that? It might offer an alternative solution that no one here has thought of.As a long-time Java developer, my answer would be that it's dealt with via careful code crafting. Keep classes small, follow the principle of single responsibility etc. There are tons of good advice for writing maintainable, easy-to-understand code. And there's certainly nothing stopping us from doing the same in D. However, if I understood Manu correctly, the issue here is those instances where there is not a lot of time, as in 48-hour game jams and game industry crunch mode. The cases where it is felt that code quality takes second place to getting things out fast. In those cases, I think Java people would feel the same problem. It can be alleviated, in Java, by making sure you write interfaces for all public-facing code. The same could be done in D, but I am unsure if that would involve a performance hit that might actually matter in games programming. So at that point, the Java programmer would rely on the IDE to make sense of the bigfiles they are producing. Now, I think an argument could be made that the initial productivity loss from performing refactorings to make sure you are producing maintainable code will pay off in a short while, even in crunchmode, but I realise this is something the games industry in general would have to deal with, and it should not be a burden put upon the individuals wishing to adopt D for making games. As for the DIP, I would not want to code using that style myself, but I wouldn't mind it if the requirement was to keep all parts of the same class in the same module. Once we start crossing file boundaries, finding out where stuff is is going to be terrible unless you have a good IDE support for things like "Go to definition".
Sep 09 2013
On 09/07/2013 07:00 PM, Walter Bright wrote:Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47I'm really happy to see this discussed. The DIP misses to mention one of the most important rationale IMO, hiding of implementation details.http://wiki.dlang.org/DIP47#Semantics 7. Outlined member function return types, parameter types, andfunction bodies have private access to the module where the aggregate is declared. I think this is problematic because it gives up the nice everything-within-this-file property of private. Doesn't package access mitigate the need for private access? What about module scope functions?
Sep 09 2013
On 9/9/2013 9:24 PM, Martin Nowak wrote:> 7. Outlined member function return types, parameter types, and function bodies have private access to the module where the aggregate is declared. I think this is problematic because it gives up the nice everything-within-this-file property of private. Doesn't package access mitigate the need for private access?The trouble with eschewing private access for member functions is then arguably the member functions do not belong in the class at all - they should be UFCS functions.
Sep 09 2013
On 09/10/2013 06:59 AM, Walter Bright wrote:The trouble with eschewing private access for member functions is then arguably the member functions do not belong in the class at all - they should be UFCS functions.Functions are placed inside classes for convenient scoping and vtables.
Sep 10 2013
Walter Bright:Outlining of member functions is the practice of placing the declaration of a member function in the struct/class/union, and placing the definition of it at global scope in the module or even in another module. http://wiki.dlang.org/DIP47I was away and very busy, I have read only part of the answers in this thread. I don't like this DIP. If this DIP passes I am probably not going to use this feature in my code. Go and Python show that it's good to minimize the number of trivially different ways to write code in a language. This DIP does the opposite.or even in another module.This is not a good idea."If you rely on tools to make the code _readable_,In my opinion this DIP makes the code less readable, and makes the code less DRY.3. Parameter names need not match.This seems bad. What's the rationale for this? (One perhaps acceptable solution is to put no parameter names in the signature inside the class). Generally I suggest to fix the biggest module system bugs before modifying the design of related features, like the ones discussed in DIP47. ----------------- Daniel Murphy:Let's solve a documentation issue with documentation improvements.This seems one better solution to the problem. But I also suggest people here to read and discuss about the post written by Andrei that touches deeper issues. The module system is currently significantly buggy, and it needs a principled design before trying to add DIP47. ----------------- Manu:People make claims like "write better code, split it up better, document your code better,The D compiler could be modified a bit to generate a bare bones documentation even with not even a comment written in the code. Bye, bearophile
Sep 10 2013
On Tuesday, 10 September 2013 at 13:49:21 UTC, bearophile wrote:Walter Bright:clipI am sure there is a good reason for having no parameter names in a declaration, but to me this doesn't make much sense. If people want separate declaration/definition so that they can get an idea of what a class does, then for non-trivial functions if the variable names are omitted then your more or less have to look at the definition anyway. I must admit whenever I come across such declarations in code I am reading I always find them kind of irritating. Apart from functions with say variadic parameter lists, is this really all that useful? clip3. Parameter names need not match.This seems bad. What's the rationale for this? (One perhaps acceptable solution is to put no parameter names in the signature inside the class).The D compiler could be modified a bit to generate a bare bones documentation even with not even a comment written in the code. Bye, bearophileI agree on this last point.
Sep 10 2013
Craig Dillabaugh:Apart from functions with say variadic parameter lists, is this really all that useful?There are rare situations when you need to add a certain argument to the function signature, but you don't need to use that argument inside the method/function. This happens for example because of code evolution. In such cases not giving a name to the argument is good, you avoid introducing a useless and unused variable name, making the code simpler, safer, and more clear. Bye, bearophile
Sep 10 2013
On Tuesday, 10 September 2013 at 14:15:19 UTC, bearophile wrote:Craig Dillabaugh:I think using calling the variable 'dummy' would likely do the trick in those instances, but this makes sense.Apart from functions with say variadic parameter lists, is this really all that useful?There are rare situations when you need to add a certain argument to the function signature, but you don't need to use that argument inside the method/function. This happens for example because of code evolution. In such cases not giving a name to the argument is good, you avoid introducing a useless and unused variable name, making the code simpler, safer, and more clear. Bye, bearophile
Sep 10 2013
On Tuesday, 10 September 2013 at 14:15:19 UTC, bearophile wrote:Craig Dillabaugh:It is never the case in the declaration though. You always want parameter names there, to reference them in DDOC comment at the very least.Apart from functions with say variadic parameter lists, is this really all that useful?There are rare situations when you need to add a certain argument to the function signature, but you don't need to use that argument inside the method/function. This happens for example because of code evolution. In such cases not giving a name to the argument is good, you avoid introducing a useless and unused variable name, making the code simpler, safer, and more clear. Bye, bearophile
Sep 10 2013