digitalmars.D - auto storage class - infer or RAII?
- Walter Bright (15/15) Nov 11 2006 The auto storage class currently is a little fuzzy in meaning, it can
- Carlos Santander (6/28) Nov 11 2006 Since this has been talked a lot already, I'll only say: auto for RAII, ...
- Bill Baxter (20/30) Nov 11 2006 I agree. Even if "everybody else is doing it", I think auto is a poor
- Walter Bright (16/18) Nov 12 2006 No, it's way way more than that. Auto type deduction gets us much closer...
- Jim Hewes (28/34) Nov 12 2006 I hope you don't mind a comment from a lurker. :)
- Walter Bright (26/64) Nov 12 2006 I think I must have presented the case for it very poorly. The goal is
- Bill Baxter (14/32) Nov 12 2006 From a software maintenance and robustness standpoint I think that cuts...
- Walter Bright (7/20) Nov 12 2006 If you wrote:
- Bill Baxter (14/27) Nov 12 2006 Yeh, I suppose. On the other hand my specification of a type is a kind
- Chris Miller (15/19) Nov 11 2006 =
- Lars Ivar Igesund (8/26) Nov 11 2006 Considering that scope already exists as a keyword, I find this an excel...
- Chris Nicholson-Sauls (7/35) Nov 11 2006 I've already said it before, but it bears repeating yet again. I also p...
- Tydr Schnubbis (4/15) Nov 11 2006 'scope' and 'infer' sound good to me, very to-the-point and unambiguous....
- Tydr Schnubbis (5/21) Nov 11 2006 It just occurred to me that since it's not the keyword itself that makes...
- Bill Baxter (17/37) Nov 11 2006 "scope" seems a pretty popular suggestion.
- Andrey Khropov (19/33) Nov 12 2006 Yes I also thought of 'scoped'. Sounds like a good idea to me.
- Bill Baxter (10/22) Nov 12 2006 I realized 'scope' is already a keyword. I think that's why people are
- Boris Kolar (17/18) Nov 11 2006 Excellent suggestion! I would also like to see scoped classes like:
- Kyle Furlong (3/21) Nov 11 2006 scope has my vote, its elegant, as raii is functionally similar to the
- Dave (7/29) Nov 11 2006 Vote++.
- Don Clugston (8/42) Nov 12 2006 Not so, 'auto' *never* means 'type inference'. It's the absence of a
- Dave (5/52) Nov 12 2006 I realize 'auto' is technically the default storage class, but was sugge...
- Chris Miller (9/24) Nov 11 2006 =
- Derek Parnell (37/58) Nov 11 2006 Please excuse my bash and amateur crashing in here ... but Walter, for a
- Derek Parnell (6/9) Nov 11 2006 By the way, I refuse to use the current 'auto' nowadays precicely becaus...
- Hasan Aljudy (3/13) Nov 11 2006 I do use auto, but only because I never use RAII, so there's no room for...
- Bill Baxter (33/50) Nov 11 2006 At least the first 4 have some consistent logic behind them, but #5 is
- Bill Baxter (24/45) Nov 11 2006 Addendum:
- Walter Bright (4/16) Nov 12 2006 I know it's a little different, but it's so convenient. Also, the
- Lionello Lunesu (6/12) Nov 12 2006 I completely agree. The current "auto" can then be tagged as deprecated ...
- Walter Bright (15/28) Nov 12 2006 My problem with "var" is the history of the keyword. Back in the olden
- Andrey Khropov (17/33) Nov 12 2006 Well, 'var' is used in C# 3.0 for this purpose (which is obviously a C-f...
- Chris Miller (4/15) Nov 12 2006 I don't like "var" because it reminds me of a cheap script like
- Ary Manzana (9/30) Nov 12 2006 So change "var" into "infer", as others sugested, if the only concern is...
- Andrey Khropov (6/11) Nov 12 2006 Khm, 5 characters for such a common keyword is too long (may be 'inf', b...
- Ary Manzana (17/28) Nov 12 2006 What?!
- Chris Nicholson-Sauls (6/42) Nov 12 2006 Wholeheartedly agreed. I really do hope 'var' doesn't make it in... I ...
- Walter Bright (3/5) Nov 12 2006 C# was designed by a Anders Hjelsberg, who wrote Pascal compilers and
- Bill Baxter (4/13) Nov 12 2006 Good point. But have you heard *anyone* complain that they don't want
- Walter Bright (3/16) Nov 12 2006 Nope. But I also don't have a billion dollars to spend to convince
- Bill Baxter (7/21) Nov 12 2006 Forget about ML, 'let' is used in Lisp, the granddaddy of all functional...
- Andrey Khropov (5/7) Nov 12 2006 Thanks for the enlightment, I'm not that familiar with Lisp.
- Carlos Santander (9/29) Nov 12 2006 I don't think they're valid concerns (meaning they're subjective, not ev...
- Walter Bright (4/11) Nov 12 2006 I'm a bit surprised at that, but the negative reaction to it is pretty
- Bill Baxter (5/22) Nov 12 2006 And I'm a bit surprised by your surprise, given that it creates a
- Sean Kelly (17/39) Nov 12 2006 What is the special case here?
- Bill Baxter (7/38) Nov 12 2006 That doesn't look particularly consistent to me.
- Jarrett Billingsley (12/17) Nov 12 2006 My main problem with it (besides not being able to use static opCall, wh...
- Hasan Aljudy (9/21) Nov 12 2006 Actually that's not so bizzare at all, because "new" already accepts
- Bill Baxter (13/21) Nov 12 2006 That will have some affect on this:
- Walter Bright (7/23) Nov 13 2006 I don't think it'll be ambiguous. scope isn't a type or a function,
- Bill Baxter (4/29) Nov 13 2006 Yeh, that works given the above. Whew!
- Nils Hensel (12/13) Nov 13 2006 I have to agree, even though I was among the first to shout out against
- Walter Bright (3/7) Nov 13 2006 At this point, I agree.
- Sean Kelly (56/70) Nov 13 2006 Seems I was one of the few who actually sort of liked the proposals. So...
- Walter Bright (12/72) Nov 13 2006 Yes.
- Sean Kelly (8/26) Nov 13 2006 Hrm... so the compiler would have to do something like generate a dummy
- Boris Kolar (36/41) Nov 14 2006 I like the above suggestions. After thinking about it, I'm beginning to ...
- Boris Kolar (20/34) Nov 14 2006 Of course, I forgot about deallocaion, so allocators would be defined as...
- Bill Baxter (24/36) Nov 14 2006 Wouldn't you like to be able to return a file object from a function?
- Kristian Kilpi (30/41) Nov 14 2006 =
- Bill Baxter (8/14) Nov 14 2006 Does D have the same extern declaration ambiguity as C++?
- Lionello Lunesu (7/9) Nov 13 2006 I for one would like it!
- Georg Wrede (14/46) Nov 12 2006 Good point. "let" is a lot worse than var. And still, I used "let" a lot...
- Roberto Mariottini (8/22) Nov 13 2006 You are right, your concern is outdated.
- Lionello Lunesu (10/17) Nov 13 2006 On the other hand: D is the right language to bridge that gap!
- Bruno Medeiros (12/51) Nov 14 2006 I *fully* agree. It comes a few days late, but I still wanted to say it....
- Boris Kolar (179/179) Nov 14 2006 Proposed extensions, that should solve most RAII (and other) problems:
- Chris Nicholson-Sauls (41/257) Nov 14 2006 While in a certain sense true... I'd really like to avoid the C++ situat...
- Bill Baxter (19/27) Nov 14 2006 The only difference between struct and class in C++ is the default
- Boris Kolar (17/51) Nov 15 2006 Sorry, I expressed my "avoiding GC" idea very unclearly. What I meant wa...
- Chad J (50/61) Nov 15 2006 Myself I really dislike D-style properties (as opposed to C# style).
- Boris Kolar (18/55) Nov 15 2006 You're right, but it seems to me that your example is more of a hypothet...
- Chad J (94/144) Nov 15 2006 It's practical, I've been bitten by it. Otherwise I probably would have...
- Bill Baxter (85/210) Nov 14 2006 I don't see much point in that really.
- Boris Kolar (52/80) Nov 15 2006 Small utility structs should usually be immutable - it's simply a matter
- Bill Baxter (23/39) Nov 14 2006 Bruno Medeiros wrote:
- Ary Manzana (12/34) Nov 11 2006 Is backward compatibility the main restriction that stops you from
- Georg Wrede (6/27) Nov 11 2006 Maybe, when both autotyping and scoped variables are commonplace, we'll
- Jarrett Billingsley (31/45) Nov 11 2006 No effing way, period. That is unclear as sin. That's like copy
- Sean Kelly (59/81) Nov 11 2006 As Don explained to me, 'auto' is a storage class in D and in C along
- Bill Baxter (36/58) Nov 11 2006 Interesting. That does kinda make sense when seen in that light. So it...
- Sean Kelly (6/42) Nov 11 2006 It does. But I'm not sure I prefer the only viable alternative in my mi...
- Walter Bright (6/19) Nov 12 2006 True. Consider that type inference works in these cases:
- Kristian Kilpi (15/33) Nov 12 2006 n =
- Sean Kelly (14/49) Nov 12 2006 Storage class specifiers are really only intended to indicate how the
- Kristian Kilpi (39/84) Nov 12 2006 e =
- Sean Kelly (10/82) Nov 12 2006 Yes.
- Georg Wrede (22/49) Nov 12 2006 I think it's okay to "have a word" for "infer the type". Think about it
- Tom (10/32) Nov 11 2006 No, I don't like it, it's awful.
- Hasan Aljudy (11/33) Nov 11 2006 eeeh .. ?
- Daniel Keep (35/64) Nov 11 2006 What I would prefer is if you introduced a new keyword that meant
- Walter Bright (6/12) Nov 12 2006 It's an interesting proposal. What I was thinking of eventually for
- Kristian Kilpi (15/21) Nov 12 2006 On Sun, 12 Nov 2006 08:50:51 +0200, Daniel Keep
- Jim Hewes (24/43) Nov 14 2006 I think this is a good suggestion. Although "infer" is good because it s...
- Don Clugston (2/24) Nov 12 2006 I add my vote to the many others who want 'scope' for all cases of RAII.
- Kristian Kilpi (31/47) Nov 12 2006 =
- Charlie (6/29) Nov 12 2006 I also am voting the majority, two different words - neither of which
- Tomas Lindquist Olsen (14/36) Nov 12 2006 I'd like to see 'auto' remain as it is except for RAII. RAII only makes
- Bill Baxter (13/17) Nov 12 2006 I think
- Tomas Lindquist Olsen (2/27) Nov 13 2006 I think you are right. Hadn't thought of this.
-
Walter Bright
(2/3)
Nov 13 2006
I knew that somehow I couldn't be the only one
. - JC (17/20) Nov 13 2006 I don't see much wrong with 'var'. It has the nice connotation that it
- Andrey Khropov (5/14) Nov 13 2006 Heh, that's exactly how 'using' is used in C#.
- Bill Baxter (14/30) Nov 13 2006 Ugh yes. Please don't force any more extra indentation levels on us!
- Tomas Lindquist Olsen (5/30) Nov 13 2006 My issue with 'var' is that it looks ugly and doesn't really tell you
- Tom (2/13) Nov 13 2006
- Kristian Kilpi (14/39) Nov 13 2006 =
- Tomas Lindquist Olsen (5/48) Nov 13 2006 Okay seems I misunderstood. Though I dont see why this makes it better.
- JC (3/21) Nov 13 2006 According to whom? That's a style thing, not a rule.
- Kristian Kilpi (25/50) Nov 13 2006 by
- Bill Baxter (6/19) Nov 13 2006 You're free to have your opinion, but the C++ books I've read disagree
- Kristian Kilpi (6/23) Nov 13 2006 Hehheh. Ok, I think I understant the point behind that. Well, I guess bo...
- Don Clugston (3/31) Nov 13 2006 It used to be the only way that worked. Early C compilers couldn't cope
- JC (4/14) Nov 13 2006 Ugliness is in the eye of the beholder. And 'var' was never proposed for...
- Tomas Lindquist Olsen (4/20) Nov 13 2006 I realise (and was pointed out already that I misunderstood). Ugliness
- Tomas Lindquist Olsen (12/12) Nov 13 2006 Another argument for using 'auto' for ATI can be making it consistent
- Sean Kelly (6/20) Nov 13 2006 I think this works everywhere, as you're free to chain storage classes
- Tomas Lindquist Olsen (5/29) Nov 13 2006 That does not work:
- Sean Kelly (5/35) Nov 13 2006 Oh, so you can just do:
- Tomas Lindquist Olsen (29/68) Nov 13 2006 It is definitely a bit weird. I would like to see all combinations of
- Bill Baxter (5/17) Nov 13 2006 What's wrong with static and const together?
- Tomas Lindquist Olsen (5/23) Nov 13 2006 Does it really make sense to have the programmer decide this
- Bill Baxter (4/28) Nov 13 2006 In a function?
- Tomas Lindquist Olsen (8/38) Nov 13 2006 a static in a class is well defined. so is a const. for me 'static
- Walter Bright (6/7) Nov 13 2006 int foo(int x)
- Lionello Lunesu (5/13) Nov 13 2006 Confusing.. I thought const in D meant really 'constant'. If a const in
- Walter Bright (2/5) Nov 14 2006 Yes.
- Tomas Lindquist Olsen (7/13) Nov 14 2006 Where is this documented? I've tried finding it in the spec but to no
- Bill Baxter (12/16) Nov 14 2006 Agreed. I recommend using the comment page [click the button on the
- Tomas Lindquist Olsen (5/25) Nov 15 2006 Thanx for pointing this out, I had missed that button. I will definitely...
- Bruno Medeiros (11/19) Nov 14 2006 I get "main.d(4): non-constant expression x", with such code:
- Bruno Medeiros (30/39) Nov 14 2006 Much like "auto", D's "const" is ambiguous, it represents two different
- Chad J (3/25) Nov 12 2006 I'm going to chime in with the people who don't like (5). I'd much
- Derek Parnell (11/37) Nov 12 2006 Has anyone worked out how to grep for instances of RAII and/or TI using
The auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope". The latter only has meaning for class objects, so let's look at the syntax. There are 4 cases: class Class { } 1) auto c = new Class(); 2) auto Class c = new Class(); 3) auto c = some_expression(); 4) auto Class c = some_expression(); The ambiguity can be resolved by saying that if auto is used for type inference, i.e. cases (1) and (3), then it does not mean RAII. If it is not used for type inference, i.e. cases (2) and (4), then it does mean RAII. In the future, I'd like the following to work: 5) auto c = Class(); which would mean type inference *and* RAII.
Nov 11 2006
Walter Bright escribió:The auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope". The latter only has meaning for class objects, so let's look at the syntax. There are 4 cases: class Class { } 1) auto c = new Class(); 2) auto Class c = new Class(); 3) auto c = some_expression(); 4) auto Class c = some_expression(); The ambiguity can be resolved by saying that if auto is used for type inference, i.e. cases (1) and (3), then it does not mean RAII. If it is not used for type inference, i.e. cases (2) and (4), then it does mean RAII. In the future, I'd like the following to work: 5) auto c = Class(); which would mean type inference *and* RAII.Since this has been talked a lot already, I'll only say: auto for RAII, and something else (eg: var) for type inference. IMHO. -- Carlos Santander Bernal
Nov 11 2006
Carlos Santander wrote:Walter Bright escribió:I agree. Even if "everybody else is doing it", I think auto is a poor choice for an automatic type deduction indicator. I'd be much happier with any of var foo = expression; val foo = expression; def foo = expression; let foo = expression; As an added bonus all of those are one character less than the current auto. Which is good, since automatic type deduction is basically a typing saving feature to begin with. To me 'auto' in front of an identifier looks like it's saying this is an "automatic variable", which, going back to the original K&R book, has always meant a local, scoped variable. It sounds like it's going to do something at run time. For anyone who complains "I'm using that as a variable name already", I'll write you a script to fix your files. Here you go perl -pi -e 's/(\W)(val)(\W)/${1}${2}_${3}/g' *.d Or if you may already have things name val_ in your code perl -pi -e 's/(\W)(val_*)(\W)/${1}${2}_${3}/g' *.d --bbThe auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope". The latter only has meaning for class objects, so let's look at the syntax. There are 4 cases:Since this has been talked a lot already, I'll only say: auto for RAII, and something else (eg: var) for type inference. IMHO.
Nov 11 2006
Bill Baxter wrote:Which is good, since automatic type deduction is basically a typing saving feature to begin with.No, it's way way more than that. Auto type deduction gets us much closer to the goal of the type of something only needs to be specified once, and then anything that manipulates it infers the right type. This makes code much more robust. For example, auto len = foo.length; What is the type of foo.length? Is it an int? uint? size_t? class Abc? Without type inference, I'd have to go look it up. With type inference, I know I've got the *correct* type for i automatically. Now, suppose I change the type of foo.length. I've got to go through and check *every* use of it to get the types of the i's updated. I'll inevitably miss one and thereby have a bug. With automatic type inference, I'm done before I start, and it's done correctly. The fewer types one has to specify, the better, and note that none of the advantages of static typechecking are lost, either.
Nov 12 2006
I hope you don't mind a comment from a lurker. :) I had assumed that there was some more important purpose for type inference, such as that it was useful in generics or something. But if it's just to avoid having to declare types, I wonder if it's really that important to have. "Walter Bright" <newshound digitalmars.com> wrote in message news:ej6vb3$2s5m$1 digitaldaemon.com...What is the type of foo.length? Is it an int? uint? size_t? class Abc? Without type inference, I'd have to go look it up. With type inference, I know I've got the *correct* type for i automatically.However, you don't know what that type is. If you want to know, you need to go look it up. This is especially true if you're working on someone else's code. I think that's fine if you're working within an IDE that can tell you the type. I'm not a fan of Hungarian notation. When working within Visual Studio for example, there are multiple ways to find the type of a variable easily. You can hover the mouse over it. You can right-click on it and select "Go to Declaration". I think this obviates things like Hungarian notation. It would help with discovering the types of inferred variables. But if you're using some editor like vi, then you may find it tedious and time-consuming to always search for the types of variables. I would be more likely to avoid type inference altogether and simply write the type just for the sake of documenting it.Now, suppose I change the type of foo.length. I've got to go through and check *every* use of it to get the types of the i's updated. I'll inevitably miss one and thereby have a bug.I assume if you've made an assignment to the wrong variable type, the compiler will catch this (unless there's an implicit cast). At least the compiler errors should help you find all occurrences easily. Although, you'd still need to go through and manually change the type in each occurrence. I just feel that making these kinds of changes to code are more the job of development tools. Perhaps the line between language and tools can start to get a little blurry; that's another discussion. Anyway, I just wonder if there is a strong a case for having type inference at all. Jim
Nov 12 2006
Jim Hewes wrote:I hope you don't mind a comment from a lurker. :)Not at all.I had assumed that there was some more important purpose for type inference, such as that it was useful in generics or something. But if it's just to avoid having to declare types, I wonder if it's really that important to have.I think I must have presented the case for it very poorly. The goal is to minimize bugs; avoiding having to declare types is a means to that goal, not the end itself."Walter Bright" <newshound digitalmars.com> wrote in message news:ej6vb3$2s5m$1 digitaldaemon.com...If you're always viewing code by using such a tool, then discovering the type is trivial as you suggest. But even with such a tool available, lots of times you won't be using it to view the code. And just to make it clear, I am not advocating Hungarian notation in the sense that it normally means (I do think, however, such notation used in the manner that Joel Spolsky writes about is useful). http://www.joelonsoftware.com/articles/Wrong.htmlWhat is the type of foo.length? Is it an int? uint? size_t? class Abc? Without type inference, I'd have to go look it up. With type inference, I know I've got the *correct* type for i automatically.However, you don't know what that type is. If you want to know, you need to go look it up. This is especially true if you're working on someone else's code. I think that's fine if you're working within an IDE that can tell you the type. I'm not a fan of Hungarian notation. When working within Visual Studio for example, there are multiple ways to find the type of a variable easily. You can hover the mouse over it. You can right-click on it and select "Go to Declaration". I think this obviates things like Hungarian notation. It would help with discovering the types of inferred variables.But if you're using some editor like vi, then you may find it tedious and time-consuming to always search for the types of variables. I would be more likely to avoid type inference altogether and simply write the type just for the sake of documenting it.I'd posit here that if type inference is possible, then perhaps documenting the type at that point is the wrong place to document it.That's just the problem. There is a lot of implicit casting going on. Consider .length - it often does mean int, uint, size_t, etc., and there are implicit casts between them. So if you 'document' it as int, then there's a bug if it really should be size_t.Now, suppose I change the type of foo.length. I've got to go through and check *every* use of it to get the types of the i's updated. I'll inevitably miss one and thereby have a bug.I assume if you've made an assignment to the wrong variable type, the compiler will catch this (unless there's an implicit cast).At least the compiler errors should help you find all occurrences easily.Unfortunately, it doesn't. One could counter with "make all implicit casting illegal." Pascal tried that, and in my not-so-humble-opinion that was a big reason for the failure of Pascal, and it's the primary reason why I dropped it as soon as I discovered C. Even so, who wants to go through their source, compiler error by compiler error, fixing it? If the work could be cut in half using type inference, why not?Although, you'd still need to go through and manually change the type in each occurrence. I just feel that making these kinds of changes to code are more the job of development tools. Perhaps the line between language and tools can start to get a little blurry; that's another discussion. Anyway, I just wonder if there is a strong a case for having type inference at all.It is optional. The ability to explicitly type declarations is not going to go away.
Nov 12 2006
Walter Bright wrote:Bill Baxter wrote:From a software maintenance and robustness standpoint I think that cuts both ways. If I don't know the type then it's easy to do something wrong with it like auto len = foo.length; len = -1; // oops! len is unsigned! not what I intended! From the point of view of someone reading and maintaining code, I hope the only places I see auto are where the type is obvious from the context, like auto foo = new SomeClassWithALongNameIDontWantToTypeTwice. I think it's bad practice to use auto just becuase you're too lazy to go figure out what the right type is. If you don't figure it out when writing it, then every person after you reading or maintaining the code is going to have to go figure it out. --bbWhich is good, since automatic type deduction is basically a typing saving feature to begin with.No, it's way way more than that. Auto type deduction gets us much closer to the goal of the type of something only needs to be specified once, and then anything that manipulates it infers the right type. This makes code much more robust. For example, auto len = foo.length; What is the type of foo.length? Is it an int? uint? size_t? class Abc? Without type inference, I'd have to go look it up. With type inference, I know I've got the *correct* type for i automatically.
Nov 12 2006
Bill Baxter wrote:From a software maintenance and robustness standpoint I think that cuts both ways. If I don't know the type then it's easy to do something wrong with it like auto len = foo.length; len = -1; // oops! len is unsigned! not what I intended!If you wrote: int len = foo.length; and foo.length was unsigned, isn't that just another sort of bug?From the point of view of someone reading and maintaining code, I hope the only places I see auto are where the type is obvious from the context, like auto foo = new SomeClassWithALongNameIDontWantToTypeTwice.I see it as much more useful than that.I think it's bad practice to use auto just becuase you're too lazy to go figure out what the right type is. If you don't figure it out when writing it, then every person after you reading or maintaining the code is going to have to go figure it out.Not necessarily. Think of it like writing templates that depend on a generic type T and assume certain properties of that type.
Nov 12 2006
Walter Bright wrote:Bill Baxter wrote:Yeh, I suppose. On the other hand my specification of a type is a kind of contract that the compiler can check. Both have their uses, but I'm just saying specifying the type should be the default policy, unless there's a compelling reason not to (i.e. it's obvious from context). I guess the best maintenance argument for why auto should be used sparingly is that information should be as localized as possible. It's why C++ gurus say you should declare at point of use whenever possible (rather than using C-style top-of-the-function declarations). It's also one reason why globals are considered bad, and why creative operator overloading is a bad idea. All those things can make you have to go searching all over your codebase to figure out the meaning of one little line of code. --bbFrom a software maintenance and robustness standpoint I think that cuts both ways. If I don't know the type then it's easy to do something wrong with it like auto len = foo.length; len = -1; // oops! len is unsigned! not what I intended!If you wrote: int len = foo.length; and foo.length was unsigned, isn't that just another sort of bug?
Nov 12 2006
On Sat, 11 Nov 2006 13:48:00 -0500, Walter Bright = <newshound digitalmars.com> wrote:The auto storage class currently is a little fuzzy in meaning, it can ==mean "infer the type" and/or "destruct at end of scope". The latter on=ly =has meaning for class objects, so let's look at the syntax. There are =4 =cases:Choosing from your list I guess "auto" for auto destruction and "infer" = = for auto type deduction. However, I tend to prefer "scope" (without parentheses following) for au= to = destruction, which frees up "auto" for auto type deduction: scope Object o =3D new Object(); // Destructed at end of scope. scope auto q =3D new Foo(); // Auto type deduction and end-of-scope = = destruction.
Nov 11 2006
Chris Miller wrote:On Sat, 11 Nov 2006 13:48:00 -0500, Walter Bright <newshound digitalmars.com> wrote:Considering that scope already exists as a keyword, I find this an excellent suggestion that is also very much clearer in meaning (I find auto to miss the target for both cases really :P ). -- Lars Ivar Igesund blog at http://larsivi.net DSource & #D: larsiviThe auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope". The latter only has meaning for class objects, so let's look at the syntax. There are 4 cases:Choosing from your list I guess "auto" for auto destruction and "infer" for auto type deduction. However, I tend to prefer "scope" (without parentheses following) for auto destruction, which frees up "auto" for auto type deduction: scope Object o = new Object(); // Destructed at end of scope. scope auto q = new Foo(); // Auto type deduction and end-of-scope destruction.
Nov 11 2006
Lars Ivar Igesund wrote:Chris Miller wrote:I've already said it before, but it bears repeating yet again. I also prefer 'scope' for this. Although 'infer' wouldn't be bad -- but please, please, please, not 'var'! It smells too much like a scripting language construct, and besides, my Bovis code is overflowing with actual variables named var. (Probably because of the BVar struct that it passes most values around as. Go figure.) -- Chris Nicholson-SaulsOn Sat, 11 Nov 2006 13:48:00 -0500, Walter Bright <newshound digitalmars.com> wrote:Considering that scope already exists as a keyword, I find this an excellent suggestion that is also very much clearer in meaning (I find auto to miss the target for both cases really :P ).The auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope". The latter only has meaning for class objects, so let's look at the syntax. There are 4 cases:Choosing from your list I guess "auto" for auto destruction and "infer" for auto type deduction. However, I tend to prefer "scope" (without parentheses following) for auto destruction, which frees up "auto" for auto type deduction: scope Object o = new Object(); // Destructed at end of scope. scope auto q = new Foo(); // Auto type deduction and end-of-scope destruction.
Nov 11 2006
Chris Nicholson-Sauls wrote:'scope' and 'infer' sound good to me, very to-the-point and unambiguous. No need to make people wonder if 'auto' works like in C or not, etc. Just drop it.Considering that scope already exists as a keyword, I find this an excellent suggestion that is also very much clearer in meaning (I find auto to miss the target for both cases really :P ).I've already said it before, but it bears repeating yet again. I also prefer 'scope' for this. Although 'infer' wouldn't be bad -- but please, please, please, not 'var'! It smells too much like a scripting language construct, and besides, my Bovis code is overflowing with actual variables named var. (Probably because of the BVar struct that it passes most values around as. Go figure.)
Nov 11 2006
Tydr Schnubbis wrote:Chris Nicholson-Sauls wrote:It just occurred to me that since it's not the keyword itself that makes type inference happen, but the lack of a type specifier, maybe 'var' is better than 'infer' after all. I mean, since it doesn't really do anything, per se.'scope' and 'infer' sound good to me, very to-the-point and unambiguous. No need to make people wonder if 'auto' works like in C or not, etc. Just drop it.Considering that scope already exists as a keyword, I find this an excellent suggestion that is also very much clearer in meaning (I find auto to miss the target for both cases really :P ).I've already said it before, but it bears repeating yet again. I also prefer 'scope' for this. Although 'infer' wouldn't be bad -- but please, please, please, not 'var'! It smells too much like a scripting language construct, and besides, my Bovis code is overflowing with actual variables named var. (Probably because of the BVar struct that it passes most values around as. Go figure.)
Nov 11 2006
Tydr Schnubbis wrote:Chris Nicholson-Sauls wrote:"scope" seems a pretty popular suggestion. I find it not so bad myself, but I would prefer "scoped" because it's less ambiguious. "scope" makes sense if you think of scope as a verb (scope this variable), but just seeing it outside of a sentence it looks like a noun (this variable is a scope -- huh?), simply because 'scope' isn't used as a verb very often in English. 'scoped' is clearly an adjective, as in 'this variable is scoped'. And being an adjective puts it in good company with most of the other storage classes which are also adjectives: (abstract, auto(matic), const(ant), deprecated, extern(al), final, static, synchronized). The only non-adjective storage class is 'override'. I have no idea why it's not "overridden". It should be. At least override reads clearly, whether you take it to be a noun (this is an override) or a verb (override the method). "Scope" does not have this property. "This is a scope" does not make sense. --bb'scope' and 'infer' sound good to me, very to-the-point and unambiguous. No need to make people wonder if 'auto' works like in C or not, etc. Just drop it.Considering that scope already exists as a keyword, I find this an excellent suggestion that is also very much clearer in meaning (I find auto to miss the target for both cases really :P ).I've already said it before, but it bears repeating yet again. I also prefer 'scope' for this. Although 'infer' wouldn't be bad -- but please, please, please, not 'var'! It smells too much like a scripting language construct, and besides, my Bovis code is overflowing with actual variables named var. (Probably because of the BVar struct that it passes most values around as. Go figure.)
Nov 11 2006
Bill Baxter wrote:"scope" seems a pretty popular suggestion. I find it not so bad myself, but I would prefer "scoped" because it's less ambiguious. "scope" makes sense if you think of scope as a verb (scope this variable), but just seeing it outside of a sentence it looks like a noun (this variable is a scope -- huh?), simply because 'scope' isn't used as a verb very often in English. 'scoped' is clearly an adjective, as in 'this variable is scoped'.Yes I also thought of 'scoped'. Sounds like a good idea to me. But I can live with 'scope' or 'var' as well. I don't like the original proposal 'auto x = ClassName(...)' // type inference, new object, RAII because sometimes it is hard to distinguish between ClassName (i.e. new object is created) and FunctionName (it's returned) With 'scoped' it's clear: 1) auto a = new A(); // type inference, new object, no RAII 2) scoped a = new A(); // type inference, new object, RAII 3) auto a = SomeFunc(); // type inference, object returned from func, no RAII 4) scoped a = SomeFunc(); // type inference, object returned from func, RAII and of course longer form should be also possible: 'scoped A a = new A();' // RAII, no type inferenceAnd being an adjective puts it in good company with most of the other storage classes which are also adjectives: (abstract, auto(matic), const(ant), deprecated, extern(al), final, static, synchronized). The only non-adjective storage class is 'override'. I have no idea why it's not "overridden".I think because 'overridden' is too long to type. I also think "lock(x)" could be better than "synchronized(x)" for the same reason. -- AKhropov
Nov 12 2006
Andrey Khropov wrote:Bill Baxter wrote:I realized 'scope' is already a keyword. I think that's why people are gravitating towards that instead of the more natural 'scoped'. I think the globally optimum solution would be to make the other 'scope' into 'scoped' too. scoped(exit) writefln("leaving now"); That reads just fine to me. Whereas scope var = new Class; looks funny. Oh well. Probably hopeless. --bb"scope" seems a pretty popular suggestion. I find it not so bad myself, but I would prefer "scoped" because it's less ambiguious. "scope" makes sense if you think of scope as a verb (scope this variable), but just seeing it outside of a sentence it looks like a noun (this variable is a scope -- huh?), simply because 'scope' isn't used as a verb very often in English. 'scoped' is clearly an adjective, as in 'this variable is scoped'.Yes I also thought of 'scoped'. Sounds like a good idea to me.
Nov 12 2006
== Quote from Chris Miller (chris dprogramming.com)'s articlescope Object o =3D new Object(); // Destructed at end of scope.Excellent suggestion! I would also like to see scoped classes like: scope class AutoDestroy { } AutoDestroy createAutoDestroyObject() { return new AutoDestroy(); } void test() { AutoDestroy d = createAutoDestroyObject(); // d will be destroyed here } This way, I can use classes with deterministic destruction the same way as other classes. Scoped classes should also be able to be returned from functions, passed as parameters, or be fields of other scoped classes. It is up to programmer (and maybe, later, compiler escape analysis) to make sure variable doesn't escape scope. good RAII is a major pain (auto classes are way too restricted).
Nov 11 2006
Chris Miller wrote:On Sat, 11 Nov 2006 13:48:00 -0500, Walter Bright <newshound digitalmars.com> wrote:scope has my vote, its elegant, as raii is functionally similar to the scope(x) construct.The auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope". The latter only has meaning for class objects, so let's look at the syntax. There are 4 cases:Choosing from your list I guess "auto" for auto destruction and "infer" for auto type deduction. However, I tend to prefer "scope" (without parentheses following) for auto destruction, which frees up "auto" for auto type deduction: scope Object o = new Object(); // Destructed at end of scope. scope auto q = new Foo(); // Auto type deduction and end-of-scope destruction.
Nov 11 2006
Kyle Furlong wrote:Chris Miller wrote:Vote++. But Walter specifically (and I think purposefully) left out any mention of new keywords. Nonetheless I'd like to see auto deprecated in favor of 'infer'. 'scope' and 'infer' both describe exactly what they are used for. 'auto' just seems too much like a deprecated artifact of C. Based on previous discussions though, 'auto' is here to stay one way or the other forever. I sincerely don't understand Walter's infatuation with 'auto', but it is what it is.On Sat, 11 Nov 2006 13:48:00 -0500, Walter Bright <newshound digitalmars.com> wrote:scope has my vote, its elegant, as raii is functionally similar to the scope(x) construct.The auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope". The latter only has meaning for class objects, so let's look at the syntax. There are 4 cases:Choosing from your list I guess "auto" for auto destruction and "infer" for auto type deduction. However, I tend to prefer "scope" (without parentheses following) for auto destruction, which frees up "auto" for auto type deduction: scope Object o = new Object(); // Destructed at end of scope. scope auto q = new Foo(); // Auto type deduction and end-of-scope destruction.
Nov 11 2006
Dave wrote:Kyle Furlong wrote:Not so, 'auto' *never* means 'type inference'. It's the absence of a type that means type inference. But the usage of auto to mean both 'raii' and 'local variable storage class' is really confusing people.Chris Miller wrote:Vote++. But Walter specifically (and I think purposefully) left out any mention of new keywords. Nonetheless I'd like to see auto deprecated in favor of 'infer'. 'scope' and 'infer' both describe exactly what they are used for.On Sat, 11 Nov 2006 13:48:00 -0500, Walter Bright <newshound digitalmars.com> wrote:scope has my vote, its elegant, as raii is functionally similar to the scope(x) construct.The auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope". The latter only has meaning for class objects, so let's look at the syntax. There are 4 cases:Choosing from your list I guess "auto" for auto destruction and "infer" for auto type deduction. However, I tend to prefer "scope" (without parentheses following) for auto destruction, which frees up "auto" for auto type deduction: scope Object o = new Object(); // Destructed at end of scope. scope auto q = new Foo(); // Auto type deduction and end-of-scope destruction.'auto' just seems too much like a deprecated artifact of C.Agreed, but I don't know of anything better. const infer x = 3.5; static infer x = 4.5L; are too wordy.Based on previous discussions though, 'auto' is here to stay one way or the other forever. I sincerely don't understand Walter's infatuation with 'auto', but it is what it is.
Nov 12 2006
Don Clugston wrote:Dave wrote:I realize 'auto' is technically the default storage class, but was suggesting when both a storage class and type are absent, 'infer' would be used (and not as a storage class) instead of auto.Kyle Furlong wrote:Not so, 'auto' *never* means 'type inference'. It's the absence of a type that means type inference. But the usage of auto to mean both 'raii' and 'local variable storage class' is really confusing people.Chris Miller wrote:Vote++. But Walter specifically (and I think purposefully) left out any mention of new keywords. Nonetheless I'd like to see auto deprecated in favor of 'infer'. 'scope' and 'infer' both describe exactly what they are used for.On Sat, 11 Nov 2006 13:48:00 -0500, Walter Bright <newshound digitalmars.com> wrote:scope has my vote, its elegant, as raii is functionally similar to the scope(x) construct.The auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope". The latter only has meaning for class objects, so let's look at the syntax. There are 4 cases:Choosing from your list I guess "auto" for auto destruction and "infer" for auto type deduction. However, I tend to prefer "scope" (without parentheses following) for auto destruction, which frees up "auto" for auto type deduction: scope Object o = new Object(); // Destructed at end of scope. scope auto q = new Foo(); // Auto type deduction and end-of-scope destruction.I think so too, but I don't think 'infer' would be necessary in those cases, even for the sake of consistency.'auto' just seems too much like a deprecated artifact of C.Agreed, but I don't know of anything better. const infer x = 3.5; static infer x = 4.5L; are too wordy.Based on previous discussions though, 'auto' is here to stay one way or the other forever. I sincerely don't understand Walter's infatuation with 'auto', but it is what it is.
Nov 12 2006
On Sat, 11 Nov 2006 14:22:19 -0500, Chris Miller <chris dprogramming.com==wrote:On Sat, 11 Nov 2006 13:48:00 -0500, Walter Bright =<newshound digitalmars.com> wrote:=The auto storage class currently is a little fuzzy in meaning, it can=mean "infer the type" and/or "destruct at end of scope". The latter =e =only has meaning for class objects, so let's look at the syntax. Ther=" =are 4 cases:Choosing from your list I guess "auto" for auto destruction and "infer=for auto type deduction. However, I tend to prefer "scope" (without parentheses following) for ==auto destruction, which frees up "auto" for auto type deduction: scope Object o =3D new Object(); // Destructed at end of scope. scope auto q =3D new Foo(); // Auto type deduction and end-of-scop=e =destruction.Actually, could probably also reuse "typeof" for auto type deduction: typeof x =3D new X;
Nov 11 2006
On Sat, 11 Nov 2006 10:48:00 -0800, Walter Bright wrote:The auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope". The latter only has meaning for class objects, so let's look at the syntax. There are 4 cases: class Class { } 1) auto c = new Class(); 2) auto Class c = new Class(); 3) auto c = some_expression(); 4) auto Class c = some_expression(); The ambiguity can be resolved by saying that if auto is used for type inference, i.e. cases (1) and (3), then it does not mean RAII. If it is not used for type inference, i.e. cases (2) and (4), then it does mean RAII. In the future, I'd like the following to work: 5) auto c = Class(); which would mean type inference *and* RAII.Please excuse my bash and amateur crashing in here ... but Walter, for a very intelligent person, why is it that you just don't get it? Type inference and RAII are two distinct, unrelated and orthogonal concepts. Using one keyword in subtly different syntax permutations to indicate both concepts is just plain stupid. In each of the suggested permutations above, the code reader and writer will constantly be thinking "now what's the precise syntax again?" This reminds me of the exact criticism that you have leveled against some C++ constructs, and some syntax changes to D suggested by your supporters. Namely that the subtle differences in syntax variants is a cause of bugs and makes writing code harder - because they are not visually distinct enough for the average person. Why do we want Type Inference? At least two reason pop into mind; to help write generic code, which means less rewriting/editing of code, and to avoid using long type names (shorter words to type). Thus a short keyword to indicate type inference would be a better idea than using a long word. Why do we want RAII? So we don't have to also write explicit 'destructor' invocation code and thus reduce the amount of coding required. So again, a short keyword rather than a long keyword would be more beneficial. However, to use the same keyword for these two unrelated uses is an ugly wart on your language. Further more 'auto' is ambiguous? Is it 'automatic'-inference, 'automatic'-RAII, 'automatic'-<some_thing_else>? My plea is ... (a) Get rid of 'auto'. (b) Create a new keyword that is more obviously read as 'type inference'. (c) Create a new keyword that is more obviously read as 'resource destruction at end of scope'. (d) Allow any combination of these new keywords on the same declaration statement. (e) Allow any combination of these new keywords on declarations at the module level. That will make reading and writing D code less costly, and increase the joy in using your wonderful language. -- Derek Parnell
Nov 11 2006
On Sun, 12 Nov 2006 10:44:37 +1100, Derek Parnell wrote:On Sat, 11 Nov 2006 10:48:00 -0800, Walter Bright wrote:By the way, I refuse to use the current 'auto' nowadays precicely because it adds to the cost of code maintenance, due to its ability to confuse and/or mislead code readers. -- Derek ParnellThe auto storage class currently is a little fuzzy in meaning
Nov 11 2006
Derek Parnell wrote:On Sun, 12 Nov 2006 10:44:37 +1100, Derek Parnell wrote:I do use auto, but only because I never use RAII, so there's no room for confusion (for me) when I read my code.On Sat, 11 Nov 2006 10:48:00 -0800, Walter Bright wrote:By the way, I refuse to use the current 'auto' nowadays precicely because it adds to the cost of code maintenance, due to its ability to confuse and/or mislead code readers.The auto storage class currently is a little fuzzy in meaning
Nov 11 2006
Derek Parnell wrote:On Sun, 12 Nov 2006 10:44:37 +1100, Derek Parnell wrote:On Sat, 11 Nov 2006 10:48:00 -0800, Walter Bright wrote:The auto storage class currently is a little fuzzy in meaning class Class { } 1) auto c = new Class(); 2) auto Class c = new Class(); 3) auto c = some_expression(); 4) auto Class c = some_expression();just pure special casing for something that's not all that common or special. It should just be auto auto c = new Class(); Besides Class may have a static opCall, no? Anyway, to me, all these things look harder to disinguish than even the a..b vs a...b thing, which you didn't like, so I'm baffled as to why you are so resistant to make 'auto' usages easier to distinguish.5) auto c = Class();By the way, I refuse to use the current 'auto' nowadays precicely because it adds to the cost of code maintenance, due to its ability to confuse and/or mislead code readers.Agreed. I stick with auto for auto-type inference, but I don't go near the other usage because it's just too confusing to have two different kinds of auto's in my code that can appear in such similar syntactic situations. I have my preferences as already stated, but I would be satisfied, if not overjoyed, with any solution that A) makes the keywords for RAII and ATI distinct, and B) doesn't make the ATI keyword any longer than it already is. Part of why I want auto for ATI to be short is that will get a lot of use. There are already 50 or so uses of auto in phobos/std/*.d. It looks like maybe 2 are RAII things but the rest are all ATI. So ATI is more common than RAII. Maybe ATI is common enough that it even warrants special syntax? If so then I think the at-sign makes sense for that. "AuTo"->"at" -- close enough for a mnemonic. That would mean "auto foo" could be compressed to " foo". Some examples of what it would look like: foo = some_expression(); bar = other_thing(); for ( v = start; v<end; v++) {...} if ( m = std.regexp.search("abcdef", "c()")) dim = this.dim(); sort(list, ( a, b){ return a.val-b.val; } // though I think in this case it should be allowable to omit the // auto's/ 's and just have sort(list, (a,b){...}); --bb
Nov 11 2006
Bill Baxter wrote:Derek Parnell wrote: So ATI is more common than RAII. Maybe ATI is common enough that it even warrants special syntax? If so then I think the at-sign makes sense for that. "AuTo"->"at" -- close enough for a mnemonic. That would mean "auto foo" could be compressed to " foo". Some examples of what it would look like: foo = some_expression(); bar = other_thing(); for ( v = start; v<end; v++) {...} if ( m = std.regexp.search("abcdef", "c()")) dim = this.dim(); sort(list, ( a, b){ return a.val-b.val; } // though I think in this case it should be allowable to omit the // auto's/ 's and just have sort(list, (a,b){...});Addendum: I personally find the implicit 'auto' in foreach to be a little jarring. Every time I see foreach(e; elements) {} I find myself looking around for where e is declared. Especially since foreach looks so much like a variation on a for loop, but 'auto' isn't automatic in a for loop in D (though after I learned about foreach, I assumed incorrectly it would work in D's for-loop too.). Additionally I keep getting bitten by things like int i; for (i=1; i<10; i++) { } ... foreach(i,elem; elements) { if (...) break; } writefln("last i was", i) Which using 'foreach-is-like-for' mentality seems perfectly natural but causes the compiler to complain. Anyway, e might be short enough that there wouldn't be any need to special case the foreach. Just use foreach( i, e; elements) { ... } --bb
Nov 11 2006
Bill Baxter wrote:Additionally I keep getting bitten by things like int i; for (i=1; i<10; i++) { } ... foreach(i,elem; elements) { if (...) break; } writefln("last i was", i) Which using 'foreach-is-like-for' mentality seems perfectly natural but causes the compiler to complain.I know it's a little different, but it's so convenient. Also, the no-shadowing rule helps flush out errors at compile time before one gets bitten.
Nov 12 2006
Please excuse my bash and amateur crashing in here ... but Walter, for a very intelligent person, why is it that you just don't get it?Didn't you mean "bright person" ? :P(a) Get rid of 'auto'.I completely agree. The current "auto" can then be tagged as deprecated and removed Jan 1st!(b) Create a new keyword that is more obviously read as 'type inference'.I like "var".(c) Create a new keyword that is more obviously read as 'resource destruction at end of scope'.I like "scope" L.
Nov 12 2006
Lionello Lunesu wrote:My problem with "var" is the history of the keyword. Back in the olden days, there were two main camps of programmers - the Pascal people, and the C people. Each camp looked with disdain upon the other as "not getting it". The Pascal crowd progressed to Modula 2, Object Pascal, and eventually Delphi. The C family progressed to C++, Java, and D. There didn't seem to be much voluntary mixing up, people would switch camps only under duress. So I have a real (possibly outdated) concern that "var" appearing in D will make the language distasteful to the C crowd. The appearance of a language matters a lot, it's like the clothes one wears that identifies one (consciously or not) as being with a particular group. And that's why I've avoided using "var". ("let" is far worse, as it gives the impression that D is some sort of new Basic language.)(a) Get rid of 'auto'.I completely agree. The current "auto" can then be tagged as deprecated and removed Jan 1st!(b) Create a new keyword that is more obviously read as 'type inference'.I like "var".(c) Create a new keyword that is more obviously read as 'resource destruction at end of scope'.I like "scope" L.
Nov 12 2006
Walter Bright wrote:My problem with "var" is the history of the keyword. Back in the olden days, there were two main camps of programmers - the Pascal people, and the C people. Each camp looked with disdain upon the other as "not getting it". The Pascal crowd progressed to Modula 2, Object Pascal, and eventually Delphi. The C family progressed to C++, Java, and D. There didn't seem to be much voluntary mixing up, people would switch camps only under duress. So I have a real (possibly outdated) concern that "var" appearing in D will make the language distasteful to the C crowd. The appearance of a language matters a lot, it's like the clothes one wears that identifies one (consciously or not) as being with a particular group. And that's why I've avoided using "var".language and a popular one) And it's also used in JavaScript and Scala (which have mostly C-family look and feel) So I think this isn't a serious concern. And as you can see from this and other threads most people here are happy with it except those who seldom use it for variable naming.("let" is far worse, as it gives the impression that D is some sort of new Basic language.)Forget about Basic, 'let' is used in ML that pioneered the concept of type inference! And there is also 'def' (from define) (used in Nemerle for this purpose, in many languages indicates function definition). But I'd like to see it short (3-4 characters) otherwise typing 'int' would be simpler :). -- AKhropov
Nov 12 2006
On Sun, 12 Nov 2006 08:28:51 -0500, Andrey Khropov <andkhropov_nosp m_mtu-net.ru> wrote:Walter Bright wrote:I don't like "var" because it reminds me of a cheap script like JavaScript, but I'm not that against it.And that's why I've avoided using "var".C-family language and a popular one) And it's also used in JavaScript and Scala (which have mostly C-family look and feel) So I think this isn't a serious concern. And as you can see from this and other threads most people here are happy with it except those who seldom use it for variable naming.
Nov 12 2006
Chris Miller escribió:On Sun, 12 Nov 2006 08:28:51 -0500, Andrey Khropov <andkhropov_nosp m_mtu-net.ru> wrote:So change "var" into "infer", as others sugested, if the only concern is the name of the keyword. :-) infer x = 2; infer y = new Foo(); I believe it's the most clear syntax: - "auto" -> automatic what? - "var" -> I know it's a variable, so...? - "infer" -> Ah! It's infering the type...Walter Bright wrote:I don't like "var" because it reminds me of a cheap script like JavaScript, but I'm not that against it.And that's why I've avoided using "var".C-family language and a popular one) And it's also used in JavaScript and Scala (which have mostly C-family look and feel) So I think this isn't a serious concern. And as you can see from this and other threads most people here are happy with it except those who seldom use it for variable naming.
Nov 12 2006
Ary Manzana wrote:So change "var" into "infer", as others sugested, if the only concern is the name of the keyword. :-) infer x = 2; infer y = new Foo();Khm, 5 characters for such a common keyword is too long (may be 'inf', but inf is a common word for infinity) And 'infer' also looks very close to 'inferior'. -- AKhropov
Nov 12 2006
Andrey Khropov escribió:Ary Manzana wrote:What?! I'm not going to time it, but typing "inf", "var", "auto", "infer", "while", "foreach", etc., should take you about the same time. I don't think a char or two make the difference (I don't know wether your concern is typing it or if the source code will have 5 o 6 bytes more). Second, I don't know if it such a common keyword. Look at all these keywords: "while", "static", "class", "interface", "foreach", "override", "alias", "import", "module", "assert" (very, very common!), "continue", "break", and the list goes on (let's not talk about "foreach_reverse" :-P). I think clarity instead of "let's save letters to make our language more compact... but less clear" is better. "interface" has 9 letters, why now change it to "inter"? It's a very common keyword, and we'll save some bytes there.So change "var" into "infer", as others sugested, if the only concern is the name of the keyword. :-) infer x = 2; infer y = new Foo();Khm, 5 characters for such a common keyword is too long (may be 'inf', but inf is a common word for infinity)And 'infer' also looks very close to 'inferior'.But "infer" *is* "infer", it's not "inferior". And people would know that "infer" is what it is (at least it's more obvious than "auto"). Just my opinion...
Nov 12 2006
Ary Manzana wrote:Chris Miller escribió:Wholeheartedly agreed. I really do hope 'var' doesn't make it in... I actually use it /quite a lot/ in my code. Last night, to see what the impact would be, I ran a search through some of my code... and had hundreds of hits for just "var", let alone all the other things with "-var-" in their names because I've assumed it was a safe name. -- Chris Nicholson-SaulsOn Sun, 12 Nov 2006 08:28:51 -0500, Andrey Khropov <andkhropov_nosp m_mtu-net.ru> wrote:So change "var" into "infer", as others sugested, if the only concern is the name of the keyword. :-) infer x = 2; infer y = new Foo(); I believe it's the most clear syntax: - "auto" -> automatic what? - "var" -> I know it's a variable, so...? - "infer" -> Ah! It's infering the type...Walter Bright wrote:I don't like "var" because it reminds me of a cheap script like JavaScript, but I'm not that against it.And that's why I've avoided using "var".C-family language and a popular one) And it's also used in JavaScript and Scala (which have mostly C-family look and feel) So I think this isn't a serious concern. And as you can see from this and other threads most people here are happy with it except those who seldom use it for variable naming.
Nov 12 2006
Andrey Khropov wrote:language and a popular one)designed Delphi.
Nov 12 2006
Walter Bright wrote:Andrey Khropov wrote:Good point. But have you heard *anyone* complain that they don't want --bbC-family language and a popular one)designed Delphi.
Nov 12 2006
Bill Baxter wrote:Walter Bright wrote:Nope. But I also don't have a billion dollars to spend to convince people to look deeper than a first impression.Andrey Khropov wrote:Good point. But have you heard *anyone* complain that they don't wantC-family language and a popular one)designed Delphi.
Nov 12 2006
Andrey Khropov wrote:Walter Bright wrote:Forget about ML, 'let' is used in Lisp, the granddaddy of all functional programming languages!("let" is far worse, as it gives the impression that D is some sort of new Basic language.)Forget about Basic, 'let' is used in ML that pioneered the concept of type inference!And there is also 'def' (from define) (used in Nemerle for this purpose, in many languages indicates function definition).It's a slightly different meaning -- let in functional programming languages, and def in Nemerle define something that's immutable. But close enough.But I'd like to see it short (3-4 characters) otherwise typing 'int' would be simpler :).Indeed.
Nov 12 2006
Bill Baxter wrote:Forget about ML, 'let' is used in Lisp, the granddaddy of all functional programming languages!Thanks for the enlightment, I'm not that familiar with Lisp. Anyway I associate Basic with this 'Dim' and 'As' things and not 'let'. -- AKhropov
Nov 12 2006
Walter Bright escribió:My problem with "var" is the history of the keyword. Back in the olden days, there were two main camps of programmers - the Pascal people, and the C people. Each camp looked with disdain upon the other as "not getting it". The Pascal crowd progressed to Modula 2, Object Pascal, and eventually Delphi. The C family progressed to C++, Java, and D. There didn't seem to be much voluntary mixing up, people would switch camps only under duress. So I have a real (possibly outdated) concern that "var" appearing in D will make the language distasteful to the C crowd. The appearance of a language matters a lot, it's like the clothes one wears that identifies one (consciously or not) as being with a particular group. And that's why I've avoided using "var". ("let" is far worse, as it gives the impression that D is some sort of new Basic language.)I don't think they're valid concerns (meaning they're subjective, not everyone will have those ideas), but I think we (the D community) just want a way to clearly differentiate both meanings of auto. So, choose any two words: auto/scope, var/auto, def/scoped, foo/bar, and let's move on. popular proposal (based on what has been said in the ng). -- Carlos Santander Bernal
Nov 12 2006
Carlos Santander wrote:I don't think they're valid concerns (meaning they're subjective, not everyone will have those ideas), but I think we (the D community) just want a way to clearly differentiate both meanings of auto. So, choose any two words: auto/scope, var/auto, def/scoped, foo/bar, and let's move on.I think the auto/scope is probably the best idea.be a popular proposal (based on what has been said in the ng).I'm a bit surprised at that, but the negative reaction to it is pretty clear.
Nov 12 2006
Walter Bright wrote:Carlos Santander wrote:And I'm a bit surprised by your surprise, given that it creates a special case rule for one particular, not-so-common situation, *AND* at the same time breaks static opCall. --bbI don't think they're valid concerns (meaning they're subjective, not everyone will have those ideas), but I think we (the D community) just want a way to clearly differentiate both meanings of auto. So, choose any two words: auto/scope, var/auto, def/scoped, foo/bar, and let's move on.I think the auto/scope is probably the best idea.to be a popular proposal (based on what has been said in the ng).I'm a bit surprised at that, but the negative reaction to it is pretty clear.
Nov 12 2006
Bill Baxter wrote:Walter Bright wrote:What is the special case here? int i = 5; // scoped int int* j = new int; // dynamic int MyClass c = MyClass(); // scoped class MyClass d = new MyClass(); // dynamic class The only thing better would be if the ctor syntax applied to concrete types as well. Then templates could almost be generic in how they dealt with types. That said, I do appreciate your concern about static opCall. As a somewhat bizarre suggestion that would break the consistency illustrated above: MyClass c = new(scope) MyClass(); // scoped class MyClass d = new MyClass; // dynamic class I don't really like this, but it would work with the existing placement new syntax and doesn't require any new keywords either. SeanCarlos Santander wrote:And I'm a bit surprised by your surprise, given that it creates a special case rule for one particular, not-so-common situation, *AND* at the same time breaks static opCall.I don't think they're valid concerns (meaning they're subjective, not everyone will have those ideas), but I think we (the D community) just want a way to clearly differentiate both meanings of auto. So, choose any two words: auto/scope, var/auto, def/scoped, foo/bar, and let's move on.I think the auto/scope is probably the best idea.to be a popular proposal (based on what has been said in the ng).I'm a bit surprised at that, but the negative reaction to it is pretty clear.
Nov 12 2006
Sean Kelly wrote:Bill Baxter wrote:That doesn't look particularly consistent to me. In one case you have int vs int*, the other case you have MyClass for both. But I could live with it if it weren't for that fact that x = MyClass() already has another meaning in D. --bbWalter Bright wrote:What is the special case here? int i = 5; // scoped int int* j = new int; // dynamic int MyClass c = MyClass(); // scoped class MyClass d = new MyClass(); // dynamic classCarlos Santander wrote:And I'm a bit surprised by your surprise, given that it creates a special case rule for one particular, not-so-common situation, *AND* at the same time breaks static opCall.I don't think they're valid concerns (meaning they're subjective, not everyone will have those ideas), but I think we (the D community) just want a way to clearly differentiate both meanings of auto. So, choose any two words: auto/scope, var/auto, def/scoped, foo/bar, and let's move on.I think the auto/scope is probably the best idea.seem to be a popular proposal (based on what has been said in the ng).I'm a bit surprised at that, but the negative reaction to it is pretty clear.
Nov 12 2006
"Sean Kelly" <sean f4.ca> wrote in message news:ej87h8$10nk$1 digitaldaemon.com...What is the special case here? int i = 5; // scoped int int* j = new int; // dynamic int MyClass c = MyClass(); // scoped class MyClass d = new MyClass(); // dynamic classMy main problem with it (besides not being able to use static opCall, which I do use), is that it's far, far too easy to miss. The first time Walter proposed this .. "syntax," I didn't know what he was proposing until I looked real hard at the code for a minute or two. If you _really_ want to make it obvious that it's a RAII class instance, either use a different keyword, or maybe even recycle the C++ way: MyClass c(params); Not that I'm entirely supporting that syntax, but the "Class name = new Class()" is such a common idiom that introducing the very-similar-looking "Class name = Class()" will only cause confusion.
Nov 12 2006
Sean Kelly wrote:That said, I do appreciate your concern about static opCall. As a somewhat bizarre suggestion that would break the consistency illustrated above: MyClass c = new(scope) MyClass(); // scoped class MyClass d = new MyClass; // dynamic class I don't really like this, but it would work with the existing placement new syntax and doesn't require any new keywords either.Actually that's not so bizzare at all, because "new" already accepts parameters. http://digitalmars.com/d/memory.html#stackclass With a little magic, you can achieve the same effect, using: MyClass c = new (alloca(MyClass.classinfo.init.length)) MyClass; Now, /that/ is bizzare. It would be very nice IMHO if there was a simpler way to do it, such as var c = new(scope) MyClass;Sean
Nov 12 2006
Walter Bright wrote:Carlos Santander wrote:That will have some affect on this: int (a) = 3; writefln(a); int (exit) = 9; writefln(exit); which all is currently ok. But with scope as a storage class, this: scope (exit) ; would become ambiguious. Is it an empty scope(exit){} or is it a scoped variable called exit that wasn't initialized? Not a huge deal, but perhaps a reason to consider using 'scoped' for the storage class instead of reusing the 'scope' keyword. --bbI don't think they're valid concerns (meaning they're subjective, not everyone will have those ideas), but I think we (the D community) just want a way to clearly differentiate both meanings of auto. So, choose any two words: auto/scope, var/auto, def/scoped, foo/bar, and let's move on.I think the auto/scope is probably the best idea.
Nov 12 2006
Bill Baxter wrote:Walter Bright wrote:I don't think it'll be ambiguous. scope isn't a type or a function, there is no: static (a) = 3; allowed anyway. The rule would be: scope ( means a scope statement, otherwise scope would be a storage class.I think the auto/scope is probably the best idea.That will have some affect on this: int (a) = 3; writefln(a); int (exit) = 9; writefln(exit); which all is currently ok. But with scope as a storage class, this: scope (exit) ; would become ambiguious. Is it an empty scope(exit){} or is it a scoped variable called exit that wasn't initialized?
Nov 13 2006
Walter Bright wrote:Bill Baxter wrote:Ah, I hadn't tried that. I assumed it would be OK, too.Walter Bright wrote:I don't think it'll be ambiguous. scope isn't a type or a function, there is no: static (a) = 3; allowed anyway.I think the auto/scope is probably the best idea.That will have some affect on this: int (a) = 3; writefln(a); int (exit) = 9; writefln(exit); which all is currently ok. But with scope as a storage class, this: scope (exit) ; would become ambiguious. Is it an empty scope(exit){} or is it a scoped variable called exit that wasn't initialized?The rule would be: scope ( means a scope statement, otherwise scope would be a storage class.Yeh, that works given the above. Whew! --bb
Nov 13 2006
Walter Bright schrieb:I think the auto/scope is probably the best idea.I have to agree, even though I was among the first to shout out against "auto". I have changed my mind since. Using a storage class for type inference is an easy and coherent method and since C++ will use "auto" for type inference it isn't such a bad choice after all. Perhaps I got used to it after all. I still think though that it should only mean that. My favourite choice for stack variables would be "local". It's short and completely obvious though I could live with "scope" if you want to avoid a new keyword at all costs. Cheers, Nils
Nov 13 2006
Nils Hensel wrote:Using a storage class for type inference is an easy and coherent method and since C++ will use "auto" for type inference it isn't such a bad choice after all. Perhaps I got used to it after all.I too think the (future) C++ use of 'auto' for type inference cinches it.I still think though that it should only mean that.At this point, I agree.
Nov 13 2006
Walter Bright wrote:Carlos Santander wrote:Seems I was one of the few who actually sort of liked the proposals. So where do we stand now? I couldn't see much of a consensus. I gather that type inference may remain as is, since it works, is clear (IMO), and doesn't introduce any new keywords. But I'm a bit fuzzy on whether anything was decided for RAII. Most folks seem to dislike the original proposal for two reasons: * It conflicts with static opCall. * It isn't easy to distinguish/grep such a declaration vs. a 'new' declaration. And most seem to favor the addition of a new keyword, probably 'scope' somewhere in the declaration. popular form seems to be: scope MyClass c = new MyClass(); // scoped decl auto scope c = new MyClass(); // inferred scoped decl Is this correct so far? And if so, I'd like to re-iterate my concerns about such a syntax: With the above, the 'scope' identifier is associated with the reference, not the data. Thus, it would be equivalent to: MyClass c = new MyClass(); scope(exit) delete c; This raises a host of issues if such references are reassignable, and in the worst case would mean that scoped data could not be allocated on the stack unless the compiler had some form of escape detection. For example: scope MyClass c = new MyClass(); c = new MyClass(); MyClass d = c; return d; Here, we have a new instance of MyClass that should be destroyed on scope exit (by my understanding). However, c is reassigned to a new instance of MyClass before this occurs. The current result is that the new instance is destroyed instead of the old one and the old one will remain in memory until the next GC collection. Also, 'd' will return a reference to data that no longer exists since it will be destroyed when 'c' goes out of scope. Even worse: scope MyClass c = new MyClass(); scope MyClass d = c; Here, we have two scoped references both referring to the same piece of data, which results in a double-deletion. Therefore, to be implemented correctly and safely, such references must uniquely refer to the underlying data, much like C++'s auto_ptr. Finally: scope int* i = new int; What happens here? Will the compiler disallow the use of 'scope' on non-class types, will 'i' be deleted on scope exit, or will 'scope' simply be ingored? If we are truly to use the 'scope' keyword for RAII objects, I humbly request that the data be flagged instead of the reference. Here are two suggestions for syntax: MyClass c = scope MyClass(); MyClass c = new(scope) MyClass(); Both would allow data to be allocated on the stack without escape detection (or an assumption that the user isn't being evil), and the latter is even almost identical to how alloca is used now. I dislike that both would make class allocation semantically different from concrete type allocation, but anything is better than associating 'scope' with the reference itself, for the reasons illustrated above. SeanI don't think they're valid concerns (meaning they're subjective, not everyone will have those ideas), but I think we (the D community) just want a way to clearly differentiate both meanings of auto. So, choose any two words: auto/scope, var/auto, def/scoped, foo/bar, and let's move on.I think the auto/scope is probably the best idea.to be a popular proposal (based on what has been said in the ng).I'm a bit surprised at that, but the negative reaction to it is pretty clear.
Nov 13 2006
Sean Kelly wrote:And most seem to favor the addition of a new keyword, probably 'scope' somewhere in the declaration. popular form seems to be: scope MyClass c = new MyClass(); // scoped decl auto scope c = new MyClass(); // inferred scoped decl Is this correct so far?Yes.And if so, I'd like to re-iterate my concerns about such a syntax: With the above, the 'scope' identifier is associated with the reference, not the data. Thus, it would be equivalent to: MyClass c = new MyClass(); scope(exit) delete c;Yes.This raises a host of issues if such references are reassignable, and in the worst case would mean that scoped data could not be allocated on the stack unless the compiler had some form of escape detection. For example: scope MyClass c = new MyClass(); c = new MyClass(); MyClass d = c; return d; Here, we have a new instance of MyClass that should be destroyed on scope exit (by my understanding). However, c is reassigned to a new instance of MyClass before this occurs. The current result is that the new instance is destroyed instead of the old one and the old one will remain in memory until the next GC collection. Also, 'd' will return a reference to data that no longer exists since it will be destroyed when 'c' goes out of scope.That's right. It isn't much different from the C++ code: MyClass c(); MyClass& d = c; return d; // Oops!Even worse: scope MyClass c = new MyClass(); scope MyClass d = c; Here, we have two scoped references both referring to the same piece of data, which results in a double-deletion. Therefore, to be implemented correctly and safely, such references must uniquely refer to the underlying data, much like C++'s auto_ptr.Right. I hope to improve the static analysis to detect and issue compile time errors for such cases.Finally: scope int* i = new int; What happens here? Will the compiler disallow the use of 'scope' on non-class types, will 'i' be deleted on scope exit, or will 'scope' simply be ingored?scope is ignored for non-reference types.If we are truly to use the 'scope' keyword for RAII objects, I humbly request that the data be flagged instead of the reference. Here are two suggestions for syntax: MyClass c = scope MyClass(); MyClass c = new(scope) MyClass(); Both would allow data to be allocated on the stack without escape detection (or an assumption that the user isn't being evil), and the latter is even almost identical to how alloca is used now. I dislike that both would make class allocation semantically different from concrete type allocation, but anything is better than associating 'scope' with the reference itself, for the reasons illustrated above.It's a good idea, but there's currently no way to flag data itself in this way.
Nov 13 2006
Walter Bright wrote:Sean Kelly wrote:Hrm... so the compiler would have to do something like generate a dummy variable referencing the class instance and act on that instead, and count on the optimizer to throw away the dummy variable when 'c' isn't reassigned in the enclosing scope. I suppose that could be a bit confusing when debugging... and some might complain about the unpredictable stack frame size or some such. Well darn :-) SeanIf we are truly to use the 'scope' keyword for RAII objects, I humbly request that the data be flagged instead of the reference. Here are two suggestions for syntax: MyClass c = scope MyClass(); MyClass c = new(scope) MyClass(); Both would allow data to be allocated on the stack without escape detection (or an assumption that the user isn't being evil), and the latter is even almost identical to how alloca is used now. I dislike that both would make class allocation semantically different from concrete type allocation, but anything is better than associating 'scope' with the reference itself, for the reasons illustrated above.It's a good idea, but there's currently no way to flag data itself in this way.
Nov 13 2006
== Quote from Sean Kelly (sean f4.ca)'s articleMyClass c = scope MyClass(); MyClass c = new(scope) MyClass(); Both would allow data to be allocated on the stack without escape detection (or an assumption that the user isn't being evil), and the latter is even almost identical to how alloca is used now.I like the above suggestions. After thinking about it, I'm beginning to wonder if scoped variables are usefull at all. The way I see it, there are three cases, where one might desire scoped variables: 1. Guaranteed, deterministic finalization (mostly disposal of system resources). For example, file should be closed when going out of scope. In this case, it would be better to make File class scoped, not individual variables: auto/scoped/whatever class File { this() { ... } ~this() { close; } } 2. Avoiding garbage collection. This can be accomplished, for example, with custom allocation (stack, for example). We can solve this by allowing a single parameter of type DeterministicAllocator to 'new' keyword in all cases (even if 'new' is not overriden in class). Maybe Allocator should be defined as a 'void* delegate()'. For example: // defined in Phobos and treated as special by compiler typedef void* delegate() DeterministicAllocator; class Foo { // 'new' is NOT defined here } void test() { DeterministicAllocator myOwnAllocator = stackAllocator; Foo foo = new(myOwnAllocator) Foo(); } 3. Some aspects of 'value class' semantics are required. Note that 'scope' or 'auto' didn't solve this problem. The best way to solve this is to make structs more powerful (allow inheritance, possibly even interface implementation, default constructors, destructors, but do NOT allow virtual/overriden methods). For example: struct BigInteger: BigCardinal { ~this() { dispose; } bool negative; } In either case, we don't really need scoped variables at all.
Nov 14 2006
== Quote from Boris Kolar (boris.kolar globera.com)'s article2. Avoiding garbage collection. This can be accomplished, for example, with custom allocation (stack, for example). We can solve this by allowing a single parameter of type DeterministicAllocator to 'new' keyword in all cases (even if 'new' is not overriden in class). Maybe Allocator should be defined as a 'void* delegate()'. For example: // defined in Phobos and treated as special by compiler typedef void* delegate() DeterministicAllocator; class Foo { // 'new' is NOT defined here } void test() { DeterministicAllocator myOwnAllocator = stackAllocator; Foo foo = new(myOwnAllocator) Foo(); }Of course, I forgot about deallocaion, so allocators would be defined as something like: // somewhere in Phobos ... typedef void* delegate() Allocate; typedef void delegate(void*) Deallocate; struct NormalAllocator { Allocate allocate; Deallocate deallocate; } struct DeterministicAllocator { Allocate allocate; Deallocate deallocate; } // in application DeterministicAllocator stack = deterministicStack; void test() { Foo foo = new(stack) Foo(); // foo is destroyed here, because stack is DeterministicAllocator }
Nov 14 2006
Boris Kolar wrote:== Quote from Sean Kelly (sean f4.ca)'s articleI like the above suggestions. After thinking about it, I'm beginning to wonder if scoped variables are usefull at all. The way I see it, there are three cases, where one might desire scoped variables: 1. Guaranteed, deterministic finalization (mostly disposal of system resources). For example, file should be closed when going out of scope. In this case, it would be better to make File class scoped, not individual variables: auto/scoped/whatever class File { this() { ... } ~this() { close; } }Wouldn't you like to be able to return a file object from a function? You wouldn't be able to if all File objects were destroyed as soon as the went out of scope. Anyway, thinking about it, "scoped" is kind of a limited concept. Take one variable in one scope and destroy it as soon as that scope ends. You can't return something like that, you can't really meaningfully assign it to other things that way. A more general concept would be to have something that is guaranteed to run its destructor as soon as there are no outstanding references. That's actually a lot simpler to do than general garbage collection. You just count references. It's exactly what boost::shared_ptr does. GC covers *most* cases where people use shared_ptr in C++ -- and in a much cleaner and potentially more efficient way. But the cases where you want something cleaned up as soon as not in use are not handled so well by GC. This includes "scoped" as one particular case. So what about "counted" instead of "scoped"? I guess this has the same issues as scoped (because scoped is basically just a binary refcount). Namely, do you attach it to the class or to the instance? In any event I think boost::shared_ptr / weak_ptr type functionality would be useful in D, but I don't see how to implement it cleanly as a library without an opAssign to keep track of the reference. --bb
Nov 14 2006
On Sun, 12 Nov 2006 20:59:05 +0200, Walter Bright = <newshound digitalmars.com> wrote:Carlos Santander wrote:=I don't think they're valid concerns (meaning they're subjective, not=t =everyone will have those ideas), but I think we (the D community) jus==want a way to clearly differentiate both meanings of auto. So, choose=any two words: auto/scope, var/auto, def/scoped, foo/bar, and let's =em =move on.I think the auto/scope is probably the best idea.=to be a popular proposal (based on what has been said in the ng).I'm a bit surprised at that, but the negative reaction to it is pretty=clear.Well I kind of like it. Unfortunate it breaks the static opCall, so it = would be too confusing to have I think. E.g. Class b; auto c =3D Class(); b =3D Class(); //wha? calls static opCall? The following (shorthand) notation won't have that problem: Class c(); Later new values cannot be assigned to 'c': Class c(10, 2); c =3D new Class; //error You could also use this notation with classes: class Foo { int v =3D 1; Bar b(10); } 'b' is binded to 'Foo', it gets destroyed with it. This notation would = remove the initialization of objects from the constructors to declaratio= n = lines (a nice ability to have sometimes). Which is consistent with = initialization of non-object variables. I think this would be great to have as a shorthand, an *alternative* way= = to create scoped/binded objects.
Nov 14 2006
Kristian Kilpi wrote:On Sun, 12 Nov 2006 20:59:05 +0200, Walter Bright <newshound digitalmars.com> wrote: The following (shorthand) notation won't have that problem: Class c();Does D have the same extern declaration ambiguity as C++? In C++ some compilers at least interpret that to be an extern declaration for a function 'c' that returns a "Class" and takes no parameters. So instead you have to say Class c; I don't know if D suffers from this particular ambiguity or not. --bb
Nov 14 2006
Carlos Santander wrote:be a popular proposal (based on what has been said in the ng).I for one would like it! It's much closer to C++. It hides the "new" and eventually might even be changed to allocate memory using the stack instead of the heap. It will be incompatible with static opCall (which I find hackish anyway) so people will probably ask for a way to add constructors to structs. L.
Nov 13 2006
Walter Bright wrote:Lionello Lunesu wrote:These are big things, no denying it.My problem with "var" is the history of the keyword. Back in the olden days, there were two main camps of programmers - the Pascal people, and the C people. Each camp looked with disdain upon the other as "not getting it". The Pascal crowd progressed to Modula 2, Object Pascal, and eventually Delphi. The C family progressed to C++, Java, and D. There didn't seem to be much voluntary mixing up, people would switch camps only under duress.(a) Get rid of 'auto'.I completely agree. The current "auto" can then be tagged as deprecated and removed Jan 1st!(b) Create a new keyword that is more obviously read as 'type inference'.I like "var".So I have a real (possibly outdated) concern that "var" appearing in D will make the language distasteful to the C crowd. The appearance of a language matters a lot, it's like the clothes one wears that identifies one (consciously or not) as being with a particular group. And that's why I've avoided using "var". ("let" is far worse, as it gives the impression that D is some sort of new Basic language.)Good point. "let" is a lot worse than var. And still, I used "let" a lot in Scheme. Go figure. But then, the very concept of type inference is not exactly a C concept, and hence it's sort of OK to then have a, er, unforgettable word for it, right? Things have also changed: in the old days it was pretty much Pascal vs C, but today everybody is fluent in a half dozen other languages as well, some of which do use "var". But the biggest thing of all with "var" is, it's only three letters! It's certainly easier to type than "let_the_compiler_freely_infer_the_type_here". <joke>How about "we"? Shorter still. Oh, what does it stand for? Well obviously it's whatever. Can't get much more appropriate.</joke>(c) Create a new keyword that is more obviously read as 'resource destruction at end of scope'.I like "scope"
Nov 12 2006
Walter Bright wrote:My problem with "var" is the history of the keyword. Back in the olden days, there were two main camps of programmers - the Pascal people, and the C people. Each camp looked with disdain upon the other as "not getting it". The Pascal crowd progressed to Modula 2, Object Pascal, and eventually Delphi. The C family progressed to C++, Java, and D. There didn't seem to be much voluntary mixing up, people would switch camps only under duress. So I have a real (possibly outdated) concern that "var" appearing in D will make the language distasteful to the C crowd. The appearance of a language matters a lot, it's like the clothes one wears that identifies one (consciously or not) as being with a particular group. And that's why I've avoided using "var".You are right, your concern is outdated. Take "var" from ECMAScript, so you don't need to get dirty with Pascal (we won't tell anyone). And, maybe, with "var" you can attract some old Pascal programmer. Ciao --- http://www.mariottini.net/roberto/
Nov 13 2006
Walter Bright wrote:My problem with "var" is the history of the keyword. Back in the olden days, there were two main camps of programmers - the Pascal people, and the C people. Each camp looked with disdain upon the other as "not getting it". The Pascal crowd progressed to Modula 2, Object Pascal, and eventually Delphi. The C family progressed to C++, Java, and D. There didn't seem to be much voluntary mixing up, people would switch camps only under duress.On the other hand: D is the right language to bridge that gap! Is there some a priori reason why there are those two groups? Probably not, since in the end they want to achieve the same thing: write a program to fix a problem. You're afraid of turning against the C crowd, but the C crowd is exactly the group that falls over "auto" meaning two things. In fact, they're probably the ones that don't like "auto" meaning anything other than its original C meaning. They should in fact be happy with "var" :) L.
Nov 13 2006
Derek Parnell wrote:On Sat, 11 Nov 2006 10:48:00 -0800, Walter Bright wrote:I *fully* agree. It comes a few days late, but I still wanted to say it. The irony and mischeviousness of the statement "The auto storage class currently is a *little fuzzy* in meaning" is teeth-grinding(or something). Walter, I hope that by judging the response in this thread you've seen that everyone agrees that these two language concepts should be well separated. There is really no discussion on that. The question to discuss is rather *how* that separations should be (which keywords, etc.). -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#DThe auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope". The latter only has meaning for class objects, so let's look at the syntax. There are 4 cases: class Class { } 1) auto c = new Class(); 2) auto Class c = new Class(); 3) auto c = some_expression(); 4) auto Class c = some_expression(); The ambiguity can be resolved by saying that if auto is used for type inference, i.e. cases (1) and (3), then it does not mean RAII. If it is not used for type inference, i.e. cases (2) and (4), then it does mean RAII. In the future, I'd like the following to work: 5) auto c = Class(); which would mean type inference *and* RAII.Please excuse my bash and amateur crashing in here ... but Walter, for a very intelligent person, why is it that you just don't get it? Type inference and RAII are two distinct, unrelated and orthogonal concepts. Using one keyword in subtly different syntax permutations to indicate both concepts is just plain stupid. In each of the suggested permutations above, the code reader and writer will constantly be thinking "now what's the precise syntax again?" This reminds me of the exact criticism that you have leveled against some C++ constructs, and some syntax changes to D suggested by your supporters. Namely that the subtle differences in syntax variants is a cause of bugs and makes writing code harder - because they are not visually distinct enough for the average person.
Nov 14 2006
Proposed extensions, that should solve most RAII (and other) problems: 1 Structs ========= Structs are a lot like classes, except they can NOT: - have virtual methods - override inherited methods (technically: they can't have VMT table) 1.1 Immutable structs --------------------- In addition to normal structs, immutable structs can be defined with: const struct Point { int x; int y; } They can be constructed as: void test() { Point p = Point(10, 20); // x = 10, y = 20 Point p = Point(x: 10, y: 20); // same as above p.x = 30; // COMPILER ERROR: Point is immutable } 1.2 Structs can have constructor(s) and destructor -------------------------------------------------- Also, structs may have constructor(s), destructor: struct File { this() { printf("File.this"); } this(char[] name) { handle = openFile(name); // handle can be modified only in constructor } ~this() { closeFile(handle); } HANDLE handle; } Invocation is deterministic (at the beginning and end of variable scope): void test() { File f; // prints "File.this" (default constructor is invoked) // destructor of f is called here } 1.3 Inheritance and implicit conversions of structs --------------------------------------------------- Structs can inherit from one or more other structs: struct A { int a; } struct B { int b; } struct C: A, B { // inherited: int a; // inherited: int b; int c; } Structs (and classes too) can define implicit conversions: // A may be struct, interface, class, ... struct D: A { // nothing is inherited because implicit conversion is defined this.A { return A(a: 10); } } Inheritance and implicit conversion test: void test() { C c; B b = c; // allowed D d; A a = d; // allowed } 2 Classes ========= 2.1 Explicit implementation of interfaces ----------------------------------------- Classes can explicitly implement interface methods or whole interfaces: interface IFoo { void foo(); } interface IBar { void bar(); } class Foo: IFoo, IBar { // explicitly implement IFoo interface methods void IFoo.foo() { } // explicitly implement interface IBar by delegation this.IBar { return getBar(); } } 2.2 Value classes ----------------- Value classes are like ordinary classes, except: - only constructor or destructor can change class state - they can not have null value (at least default constructor is called) - they have deterministic finalization if they implement 'Local' Example: const class Foo: Local { this() { foo = 5; // foo can be modified (only) in constructor/destructor } ~this() { printf("Foo.~this"); } int foo; } void test() { Foo foo; // foo.foo = 5 (default constructor is invoked, foo can't be null) // prints "Foo.~this" and destroys foo here } Value classes can easily support deterministic finalization, because no cycles are possible (without hacking, anyway) and simple reference counting is sufficient. 2.3 Custom allocators --------------------- Custom allocators allow any allocation strategy: // in Phobos interface Allocator { void* allocate(Type type); void deallocate(Type type, void* mem); } // test application void test() { Foo foo = new(myAllocator) Foo(); // if Foo is value class and implements 'Local', then foo is deleted here // ... else foo is deleted when myAllocator is deleted } 3 Summary ========= It seems that scoped variables are unnecessary, because value classes that implement 'Local' interface, together with implicit conversions, are sufficient in all of the following scenarios: 1. Finalization is required: const class File: Local { ~this() { close; } } 2. Garbage collection must be avoided: const class Scoped(T): T, Local { this(T object) { _object = object; } this.T { return _object; } private T _object; } Scoped(T) scoped(T)(T object) { return new Scoped!(T)(object); } class Foo { void foo() { ... } } void test() { Foo foo = scoped(new Foo()); foo.foo(); // foo is deleted here :) } void test2() { scoped(new Foo()).foo(); // Foo instance is deleted here too! :D } 3. Value class semantics is desired: const class Point { int x; int y; } Another (minor) suggestion is allowing method declarations without '()': class Foo: Bar { int foo { // no ambiguity here, consistent with 'this.Bar' definition return 5; } this.Bar { return bar; } private Bar bar; } Also, get rid of static opCall
Nov 14 2006
Boris Kolar wrote:Proposed extensions, that should solve most RAII (and other) problems: 1 Structs ========= Structs are a lot like classes, except they can NOT: - have virtual methods - override inherited methods (technically: they can't have VMT table)While in a certain sense true... I'd really like to avoid the C++ situation where the only difference is where they get allocated. I know that's not quite what you're trying for here, but one thing could lead to another... that said -- continue;1.1 Immutable structs --------------------- In addition to normal structs, immutable structs can be defined with: const struct Point { int x; int y; }Not a bad idea, although one could already accomplish this (I think) just by declaring the variable as const, rather than the type... which is notably more consistant.They can be constructed as: void test() { Point p = Point(10, 20); // x = 10, y = 20 Point p = Point(x: 10, y: 20); // same as above p.x = 30; // COMPILER ERROR: Point is immutable }If we can get static struct initializers into the open the same way we've gotten array literals out of static array initializers, then this wouldn't be needed. Instead we could just: Already works, so long as p is declared static/const.1.2 Structs can have constructor(s) and destructor -------------------------------------------------- Also, structs may have constructor(s), destructor: struct File { this() { printf("File.this"); } this(char[] name) { handle = openFile(name); // handle can be modified only in constructor } ~this() { closeFile(handle); } HANDLE handle; }I'm still undecided on this, to be honest. I don't think its a bad thing, per se, and certainly know of uses for it... but it makes me antsy for some reason. May just be unreasonable paranoia.Invocation is deterministic (at the beginning and end of variable scope): void test() { File f; // prints "File.this" (default constructor is invoked) // destructor of f is called here }As it likely should be.1.3 Inheritance and implicit conversions of structs --------------------------------------------------- Structs can inherit from one or more other structs: struct A { int a; } struct B { int b; } struct C: A, B { // inherited: int a; // inherited: int b; int c; }This I would like to see.Structs (and classes too) can define implicit conversions: // A may be struct, interface, class, ... struct D: A { // nothing is inherited because implicit conversion is defined this.A { return A(a: 10); } }If nothing else, it is an interesting syntax. It might make a nice alternative to the opCast() method we have now. Might even make opCast() obsolete (especially since opCast() can only provide conversion to a single type).Inheritance and implicit conversion test: void test() { C c; B b = c; // allowed D d; A a = d; // allowed }I assume that, given 'struct D: A' then the following: Or in other words, upon conversion, it actually /is/ an A, and no longer a D. Otherwise, this could potentially negate some uses of structs as direct maps into data files.2 Classes ========= 2.1 Explicit implementation of interfaces ----------------------------------------- Classes can explicitly implement interface methods or whole interfaces: interface IFoo { void foo(); } interface IBar { void bar(); } class Foo: IFoo, IBar { // explicitly implement IFoo interface methods void IFoo.foo() { } // explicitly implement interface IBar by delegation this.IBar { return getBar(); } }This I like. :)2.2 Value classes ----------------- Value classes are like ordinary classes, except: - only constructor or destructor can change class state - they can not have null value (at least default constructor is called) - they have deterministic finalization if they implement 'Local' Example: const class Foo: Local { this() { foo = 5; // foo can be modified (only) in constructor/destructor } ~this() { printf("Foo.~this"); } int foo; } void test() { Foo foo; // foo.foo = 5 (default constructor is invoked, foo can't be null) // prints "Foo.~this" and destroys foo here } Value classes can easily support deterministic finalization, because no cycles are possible (without hacking, anyway) and simple reference counting is sufficient.Hm. No opinion.2.3 Custom allocators --------------------- Custom allocators allow any allocation strategy: // in Phobos interface Allocator { void* allocate(Type type); void deallocate(Type type, void* mem); } // test application void test() { Foo foo = new(myAllocator) Foo(); // if Foo is value class and implements 'Local', then foo is deleted here // ... else foo is deleted when myAllocator is deleted }Not a bad idea. Not sure if I would use it, personally, but not a bad idea.3 Summary ========= It seems that scoped variables are unnecessary, because value classes that implement 'Local' interface, together with implicit conversions, are sufficient in all of the following scenarios: 1. Finalization is required: const class File: Local { ~this() { close; } }Sure. Currently achieved using 'auto'... no need to go into that mess all over again, of course.2. Garbage collection must be avoided: const class Scoped(T): T, Local { this(T object) { _object = object; } this.T { return _object; } private T _object; } Scoped(T) scoped(T)(T object) { return new Scoped!(T)(object); } class Foo { void foo() { ... } } void test() { Foo foo = scoped(new Foo()); foo.foo(); // foo is deleted here :) } void test2() { scoped(new Foo()).foo(); // Foo instance is deleted here too! :D }I'm not so sure I understand how this is "avoiding" GC... it seems to be /enforcing/ it. But its still a fascinating design concept.3. Value class semantics is desired: const class Point { int x; int y; }If I want value semantics, I'll generally use a struct. Just can't think of cases right off hand where I'd want this.Another (minor) suggestion is allowing method declarations without '()': class Foo: Bar { int foo { // no ambiguity here, consistent with 'this.Bar' definition return 5; } this.Bar { return bar; } private Bar bar; }Eh, maybe. I would probably still always type them in there. They don't take up much space, and I'm just too used to a pair of ()'s meaning, "Hey this is a function/method!" them in D, I don't need constant false hope. ;)Also, get rid of static opCallJust: no. Leave it be. -- Chris Nicholson-Sauls
Nov 14 2006
Chris Nicholson-Sauls wrote:The only difference between struct and class in C++ is the default protection level. In a struct memebers are public by default, for classes they're private by default. That's the only difference. And also the inheritance in structs is public by default, and private for classes. And that's why it's really annoying that you can't generically forward declare a class/struct without knowing which it is. ---foo.h---- class ForwardDeclared; class Foo { ForwardDeclared *f; }; ------------ This fails if ForwardDeclared turns out to be a struct. Grrr. Who cares which it is?! They're the same freaking thing! All you need to know, mr. dumb compiler, is that I've got a pointer, period. (Maybe typename fixes this? Does anyone know?). --bbStructs are a lot like classes, except they can NOT: - have virtual methods - override inherited methods (technically: they can't have VMT table)While in a certain sense true... I'd really like to avoid the C++ situation where the only difference is where they get allocated.
Nov 14 2006
== Quote from Chris Nicholson-Sauls (ibisbasenji gmail.com)'s article/enforcing/ it.2. Garbage collection must be avoided: const class Scoped(T): T, Local { this(T object) { _object = object; } this.T { return _object; } private T _object; } Scoped(T) scoped(T)(T object) { return new Scoped!(T)(object); } class Foo { void foo() { ... } } void test() { Foo foo = scoped(new Foo()); foo.foo(); // foo is deleted here :) } void test2() { scoped(new Foo()).foo(); // Foo instance is deleted here too! :D }I'm not so sure I understand how this is "avoiding" GC... it seems to beBut its still a fascinating design concept.Sorry, I expressed my "avoiding GC" idea very unclearly. What I meant was avoiding long GC runs, which occour when the system runs out of memory and a whole bunch of objects is checked for garbage. There are no guarantees about how long such a GC run may take. That's why real-time programs must avoid situations when system must GC unused objects. And by "real-time programs" I don't mean just mission-critical software that lives depend on, but also games and multimedia applications.If I want value semantics, I'll generally use a struct. Just can't think ofcases rightoff hand where I'd want this.Perhaps when you would need a "struct" to override some method. I'd like to see that the only difference between structs and classes is that structs don't have VMT table (and thereforce can't override methods). So, structs are in a sense 'lightweight' classes.them in D,I don't need constant false hope. ;)I like D-style properties much better :)Well, I meant replace it with constructor (for structs). Or it can stay, but no struct can define both constructor and opCall.Also, get rid of static opCallJust: no. Leave it be.
Nov 15 2006
Boris Kolar wrote:== Quote from Chris Nicholson-Sauls (ibisbasenji gmail.com)'s articleclass Foo { void delegate() m_bar; void delegate() bar() { return m_bar; } void func() { writefln( "..." ); } this() { m_bar = &func; } } void main() { Foo foo = new Foo(); foo.bar(); // call foo.bar, or return the delegate m_bar? } If you think of properties as member variables, then this does not behave as expected - foo.bar() returns the delegate, but does not call it. Thinking of foo.bar as a method that returns a delegate does cause the behaviour make sense, but then it's just shorthand for calling a method, and nothing more. No op*Assign. This is why we have to type array.length = array.length + 1; instead of array.length++; It's one more possible way to write code that just doesn't make sense. I suppose this isn't too bad since programmers tend to shoot for clarity, but I've run into it. writefln = sqrt = 4.0f; // what?!? ... So I see the current property syntax as nothing more than a shorthand for function/method calling. It does not provide a means to wrap code around the getting and setting of member variables or have member variables with inheritance properties, because properties are not member variables they are methods. I am a fast typer - I don't mind the extra 2 parens to call a function. However, being a fast typer does not solve the delegate ambiguity (a bit of thought can, but that's what properties are supposed to save IMO). problems there. Well that's my case. Could you explain why you prefer D-style properties, please? I'd like to know if there are any significant advantages to having it this way.them in D,I don't need constant false hope. ;)I like D-style properties much better :)
Nov 15 2006
== Quote from Chad J (gamerChad _spamIsBad_gmail.com)'s articleclass Foo { void delegate() m_bar; void delegate() bar() { return m_bar; } void func() { writefln( "..." ); } this() { m_bar = &func; } } void main() { Foo foo = new Foo(); foo.bar(); // call foo.bar, or return the delegate m_bar? } If you think of properties as member variables, then this does not behave as expected - foo.bar() returns the delegate, but does not call it. Thinking of foo.bar as a method that returns a delegate does cause the behaviour make sense, but then it's just shorthand for calling a method, and nothing more.You're right, but it seems to me that your example is more of a hypotheticalNo op*Assign. This is why we have to type array.length = array.length + 1; instead of array.length++;That convinced me. I remember now that I have stumbled on this problem as well. Still, a smart compiler might allow array.length++.It's one more possible way to write code that just doesn't make sense. I suppose this isn't too bad since programmers tend to shoot for clarity, but I've run into it. writefln = sqrt = 4.0f; // what?!?That's a good one :) Never thought of that. Although it's merely a bad style - I always assume there are already infinite number of ways to write program in a cryptic style.Well that's my case. Could you explain why you prefer D-style properties, please? I'd like to know if there are any significant advantages to having it this way.Well, I could never decide if a something is just a parameterless function, a property, or a field. In D, it's all used the same way. You can, for example, build an early prototype by using a field and then turn it into a property (that, for example, logs every call). Also, I like the fact that writing the parameterless function is property. Also, Eiffel and Wikipedia make some convincing arguments: http://www.eiffel.com/general/monthly_column/2005/Sept_October.html http://en.wikipedia.org/wiki/Uniform_access_principle
Nov 15 2006
Boris Kolar wrote:== Quote from Chad J (gamerChad _spamIsBad_gmail.com)'s articleIt's practical, I've been bitten by it. Otherwise I probably would have never thought about it.You're right, but it seems to me that your example is more of a hypotheticalA smart compiler won't save this. That's because it will make the language depend on Quality Of Implementation (QOI). If one were to write code while using said smart compiler, then the code gets moved to a 'dumb' compiler, the code will break if array.length++; was ever used. This trashes the ability to easily port code between compilers.No op*Assign. This is why we have to type array.length = array.length + 1; instead of array.length++;That convinced me. I remember now that I have stumbled on this problem as well. Still, a smart compiler might allow array.length++.able to call it like a function. IMO, calling a field is nonsensicle. It's right alongside assigning to a function/method.It's one more possible way to write code that just doesn't make sense. I suppose this isn't too bad since programmers tend to shoot for clarity, but I've run into it. writefln = sqrt = 4.0f; // what?!?That's a good one :) Never thought of that. Although it's merely a bad style - I always assume there are already infinite number of ways to write program in a cryptic style.Well that's my case. Could you explain why you prefer D-style properties, please? I'd like to know if there are any significant advantages to having it this way.Well, I could never decide if a something is just a parameterless function, a property, or a field. In D, it's all used the same way. You can, for example, build an early prototype by using a field and then turn it into a property (that, for example, logs every call).Also, I like the fact that writing the parameterless function is property.Also, Eiffel and Wikipedia make some convincing arguments: http://www.eiffel.com/general/monthly_column/2005/Sept_October.html http://en.wikipedia.org/wiki/Uniform_access_principleI think that D fails to acheive UAP with the current property syntax. foo.bar++; // implies field. This betrays whether bar is implemented through storage or computation - it is implied that bar is implemented through storage. I'm going to venture an educated guess that Eiffel does not have such opOperateApply type operators. Ditch the ++, --, +=, -=, *=, etc. and UAP is restored. Also: int a = foo.bar(); // implies method Now we know that bar is implemented through computation. One important feature of UAP seems to be that it allows you to change the implementation of any object member without breaking code that uses that member. D fails here, due to the above. Indeed, this is the part and IMO a much more important reason to ditch the current syntax than having to write opOperateAssign the longhand way. so in a very damaging way. Suppose you want to change a member from being a field, to being a method. Why? The reason I see is to add extra functionality to the field, as in logging, inheritance, program state update, etc. Another would be to use fields and methods prohibits it. Now, suppose you want to change a member from being a method to being a field. Why? I see two reasons. One is to reduce the code size of the method from small to slightly smaller (it was small already since you can reduce almost all functionality by simply writing func() { return m_val; }). The other is to use fields and methods interchangably. I don't see much value in the former, and am still is fine by me. keyword usage. This shouldn't be too difficult to fix. prop int getter() { return myval; } prop void setter( int toAssign ) { myval = toAssign; } Now it has been reduced to one extra keyword, 'prop'. Also, most of the current behaviour of D's properties is maintained. Indeed, these may not necessarily even be in classes or structs, but also modules and functions and other scopes, as they can be nowadays. It also seems to give the compiler all of the information it needs to determine usage in an easy and straightforward fashion. There was also a suggestion to allow methods without parens int foo { return 5; } void main() { writefln( foo ); // prints 5 } No new keyword, but it breaks for setters. hmmmm, maybe something like this for the setters: private int m_assignable; void foo[ int toAssign ] { m_assignable = toAssign; } Or other possibilities: void foo.( int toAssign ) {...} void foo!{ int toAssign } {...} void foo.{ int toAssign } {...} void foo.[ int toAssign ] {...} and so on... Or perhaps the paren-less suggestion above, with an implicit variable defined like in variadic functions. Let's call it _arg. (perhaps it could be prettier?) void foo { m_assignable = _arg; } Perhaps it should be mandated in the above case that the function does not have a return type, in order to help the compiler tell at first glance that it is indeed a setter. I'm sure there are many other possibilities, more than one of which are viable.
Nov 15 2006
Boris Kolar wrote:Proposed extensions, that should solve most RAII (and other) problems:Heh heh. That's a mighty big claim. :-)1 Structs ========= Structs are a lot like classes, except they can NOT: - have virtual methods - override inherited methods (technically: they can't have VMT table) 1.1 Immutable structs --------------------- In addition to normal structs, immutable structs can be defined with: const struct Point { int x; int y; } They can be constructed as: void test() { Point p = Point(10, 20); // x = 10, y = 20 Point p = Point(x: 10, y: 20); // same as above p.x = 30; // COMPILER ERROR: Point is immutable }I don't see much point in that really. hahahah get it? Not much Point. yuk yuk yuk yuk yuk yuk. I'll be here all week. But seriously const applied to instances seems sufficient to me. Why restrict the utility of the class in that way? At least you need to find a better example than Point to illustrate your case.1.2 Structs can have constructor(s) and destructor -------------------------------------------------- Also, structs may have constructor(s), destructor:I'd like this too -- at least constructors. But Walter is against destructors since (IIUC) it creates complications when passing structs as arguments or when they get created as implicit temporaries by the compiler. Something like that. Anyway, people use static opCall as a constructor now, but it's always annoying to write such a beast (or such beasts since you often write 3 or 4 different versions): static MyStruct opCall(S s, T t, R r) { MyStruct c; with (c) { m_svar = s; m_tvar = t; m_rvar = r; } return c; } That's about as minimal as it can be, but it's still two superfluous lines and a superfluous return type that you wouldn't need in a real constructor. And it may be slightly less efficient if the compiler doesn't optimize assignment well. It could mean a create & copy vs just one in-place creation. And it doesn't declare your intent clearly. It's just a convention. static opCall doesn't necessarily return a new instance of the struct. However, if you add constructors to structs what's the syntax for use going to be? Personally I can't think of anything more natural than MyStruct(a,b,c). So I think it would have to act just like a static opCall. The only difference is you'd be able to write this instead of the above with all it's extra cruft: this(S s, T t, R r) { m_svar = s; m_tvar = t; m_rvar = r; } Destructors I don't know about. The main use case I have is little sentinal structs that do "set_state" in the constructor "reset_state" in the destructor. (A lot of use for that in OpenGL programs). The thing is I think that paradigm is not so clear. The "fire-and-forget" nature of it is useful when programming { auto st = scopedTransform(trans); ... { auto sc = scopedColor(color); ... } } but it's easy for those ... parts to get very long, and it's easy for those scopeTransform thingy's to get buried somewhere in the middle of the scope. And then it's easy for someone to come along and see what looks like a superfluous block and decide to delete the extra {}, creating a hard to find bug. So I actually think something like this may be a better style for D: auto st = tempTransform(trans); scope(exit) st.restore; At least then the maintenance programmer can see clearly that there's a scope exit in the block and thereby know not to delete that extra {}. Plus that's currently valid D code.struct File {Something like a File shouldn't be a struct. If you're going to be doing file IO, then probably the speed hit of having to do one dynamic allocation is not important.1.3 Inheritance and implicit conversions of structs --------------------------------------------------- Structs can inherit from one or more other structs: struct A { int a; } struct B { int b; } struct C: A, B { // inherited: int a; // inherited: int b; int c; }Yeh, this has been suggested before. There was a discussion about it fairly recently. I don't see why this shouldn't be possible.Structs (and classes too) can define implicit conversions: // A may be struct, interface, class, ... struct D: A { // nothing is inherited because implicit conversion is defined this.A { return A(a: 10); } }Don't know about that. I think implicit conversion would only make sense for pointers to structs. But maybe I'm missing your point.2 Classes ========= 2.1 Explicit implementation of interfaces ----------------------------------------- Classes can explicitly implement interface methods or whole interfaces: interface IFoo { void foo(); } interface IBar { void bar(); } class Foo: IFoo, IBar { // explicitly implement IFoo interface methods void IFoo.foo() { } // explicitly implement interface IBar by delegation this.IBar { return getBar(); } }So this is just an alternative to 'override'? If so I like it. I find I always end up putting a comments in my code anyway like: /// These implement the IImplementable interface override int foo() {...} override int bar() {...} But if I move around methods those comments can get stale. int IImplementable.foo() { ... } int IImplementable.bar() { ... } would be clearer and eliminate the need for override in most cases. Problem is I think (even though rare) an override can override a method declared in multiple different interfaces.2.2 Value classes ----------------- Value classes are like ordinary classes, except: - only constructor or destructor can change class state - they can not have null value (at least default constructor is called) - they have deterministic finalization if they implement 'Local' Example: const class Foo: Local { this() { foo = 5; // foo can be modified (only) in constructor/destructor } ~this() { printf("Foo.~this"); } int foo; } void test() { Foo foo; // foo.foo = 5 (default constructor is invoked, foo can't be null) // prints "Foo.~this" and destroys foo here } Value classes can easily support deterministic finalization, because no cycles are possible (without hacking, anyway) and simple reference counting is sufficient.This is just different syntax for "auto class Foo" as far as I can tell.2.3 Custom allocators --------------------- Custom allocators allow any allocation strategy: // in Phobos interface Allocator { void* allocate(Type type); void deallocate(Type type, void* mem); } // test application void test() { Foo foo = new(myAllocator) Foo(); // if Foo is value class and implements 'Local', then foo is deleted here // ... else foo is deleted when myAllocator is deleted }I thought this was possible already.Another (minor) suggestion is allowing method declarations without '()':Eh, I don't that as much of a gain, and it would make grepping for function definitions a little bit harder. --bb
Nov 14 2006
== Quote from Bill Baxter (dnewsgroup billbaxter.com)'s article (immutable structs)But seriously const applied to instances seems sufficient to me. Why restrict the utility of the class in that way? At least you need to find a better example than Point to illustrate your case.Small utility structs should usually be immutable - it's simply a matter of good design. A few seconds on Google gives enough reasons for immutable structs/classes: http://www-128.ibm.com/developerworks/java/library/j-jtp02183.htmlI'd like this too -- at least constructors. But Walter is against destructors since (IIUC) it creates complications when passing structs as arguments or when they get created as implicit temporaries by the compiler. Something like that.C++ has no problems with destructors, therefore it should be possible to implement them in D as well.However, if you add constructors to structs what's the syntax for use going to be? Personally I can't think of anything more natural than MyStruct(a,b,c). So I think it would have to act just like a static opCall.Yes, exactly what I had in mind.Something like a File shouldn't be a struct. If you're going to be doing file IO, then probably the speed hit of having to do one dynamic allocation is not important.Of course. But this was not meant to be a real world example. Basically, I don't see much difference between structs and classes except that structs don't have VMT table. Not having VMT table can be (sometimes) usefull, especially if your struct mirrors layout of some other structure. And it makes them a bit "safer", because you can't accidently override struct's methods (which reminds me of another wish: compiler should at least warn when you override methods without explicit 'override').Don't know about that. I think implicit conversion would only make sense for pointers to structs. But maybe I'm missing your point.Implicit conversions make just as much sense as inheritance. Of course, indirect implicit conversions can be ambigous, but there are algorithms to detect this. For example, consider implicit conversions of "big" versions of numbers: BigCardinal -> BigInteger -> BigRational A relatively simple rule about implicit conversion should be: - implicit conversion is possible if the shortest conversion path to desired type is not ambigousSo this is just an alternative to 'override'? If so I like it. I find I always end up putting a comments in my code anyway like:Explicit implementation is more than just 'override'. You can, for example, implement two different interfaces with the "same" method, like that: interface Foo { int foo(); } interface Bar { char[] foo(); } class FooBar: Foo, Bar { int Foo.foo() { ... } char[] Bar.foo() { ... } } Also, you can implement all methods at once with delegation: class Foo: Bar { this.Bar { // will implement all Bar's methods return getBar(); } }Additionally, const classes are immutable, so no cyclic references are possible, therefore implementing deterministic finalization is much easier (for non-const classes, compiler would have to do escape analysis, which I suspect is not an easy task).Value classes can easily support deterministic finalization, because no cycles are possible (without hacking, anyway) and simple reference counting is sufficient.This is just different syntax for "auto class Foo" as far as I can tell.Yes, but you have to encode allocation strategy in class. So, in this case, Foo must redefine the 'new' operator. My suggestion was that allocation strategy can be redefined for all (including existing) classes.2.3 Custom allocators ... Foo foo = new(myAllocator) Foo();I thought this was possible already.Yes, not much gain. Since you can already omit '()' everywhere except in declarations, I thought it would be more consistent to simply state that all '()' are optional.Another (minor) suggestion is allowing method declarations without '()':Eh, I don't that as much of a gain, and it would make grepping for function definitions a little bit harder.
Nov 15 2006
Walter Bright wrote:Derek Parnell wrote:The auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope". The latter only has meaning for class objects, so let's look at the syntax. There are 4 cases:Bruno Medeiros wrote:Type inference and RAII are two distinct, unrelated and orthogonal concepts. Using one keyword in subtly different syntax permutations to indicate both concepts is just plain stupid.I *fully* agree. It comes a few days late, but I still wanted to say it. The irony and mischeviousness of the statement "The auto storage class currently is a *little fuzzy* in meaning" is teeth-grinding(or something). Walter, I hope that by judging the response in this thread you've seen that everyone agrees that these two language concepts should be well separated. There is really no discussion on that. The question to discuss is rather *how* that separations should be (which keywords, etc.).I fully agree that they should be made more clearly distinct in the code. But over the past few days I've also come to understand that there is some logic to the status quo. They aren't totally orthogonal concepts when considered in the context of a simple value-type automatic variable. 'auto' for type inference is really just 'auto' for declaring an automatic variable, and the type inference is due to lack of specific type. 'auto' for RAII can be thought of as saying "this thing acts like an automatic variable" in that it's cleaned up just a regular value type would be. int foo = expr(); leaves no traces behind after it's out of scope (because it's an automatic variable). The expression myint foo = expr(); looks like it might also leave no traces behind, but that wouldn't be the case if myint were a Class. So in that case auto myint foo = expr() is saying "Really I mean it! Treat this like a plain-old value-type automatic variable, no matter what it is -- class, struct, or typedef." That said, even though there is a certain kind of logic behind it, it would still be better for the people who have to *write* and *maintain* the code if the distinction were made a little more obvious. --bb
Nov 14 2006
Walter Bright escribió:The auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope". The latter only has meaning for class objects, so let's look at the syntax. There are 4 cases: class Class { } 1) auto c = new Class(); 2) auto Class c = new Class(); 3) auto c = some_expression(); 4) auto Class c = some_expression(); The ambiguity can be resolved by saying that if auto is used for type inference, i.e. cases (1) and (3), then it does not mean RAII. If it is not used for type inference, i.e. cases (2) and (4), then it does mean RAII. In the future, I'd like the following to work: 5) auto c = Class(); which would mean type inference *and* RAII.Is backward compatibility the main restriction that stops you from selecting two keywords distinct from "auto" (and a lot of other unclear stuff)? If it's that, what you can do is propose a final, clean syntax for version 1.0 and get the programmers to update their codes to v1.0. I guess they will do that, at least active projects: old, abandoned projects sure will fail, as probably they fail now with some last language modifications. I think no one but you want's to keep the "auto" keyword. -- Ary
Nov 11 2006
Walter Bright wrote:The auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope". The latter only has meaning for class objects, so let's look at the syntax. There are 4 cases: class Class { } 1) auto c = new Class(); 2) auto Class c = new Class(); 3) auto c = some_expression(); 4) auto Class c = some_expression(); The ambiguity can be resolved by saying that if auto is used for type inference, i.e. cases (1) and (3), then it does not mean RAII. If it is not used for type inference, i.e. cases (2) and (4), then it does mean RAII.Well, you know my view here: we need two separate keywords.In the future, I'd like the following to work: 5) auto c = Class(); which would mean type inference *and* RAII.Maybe, when both autotyping and scoped variables are commonplace, we'll eventually start wanting a single word to denote both. That word could be "auto". But in the meantime, two separate words, none of which is auto.
Nov 11 2006
"Walter Bright" <newshound digitalmars.com> wrote in message news:ej55ss$1g6m$1 digitaldaemon.com...The auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope". The latter only has meaning for class objects, so let's look at the syntax. There are 4 cases: class Class { } 1) auto c = new Class(); 2) auto Class c = new Class(); 3) auto c = some_expression(); 4) auto Class c = some_expression(); The ambiguity can be resolved by saying that if auto is used for type inference, i.e. cases (1) and (3), then it does not mean RAII. If it is not used for type inference, i.e. cases (2) and (4), then it does mean RAII. In the future, I'd like the following to work: 5) auto c = Class();No effing way, period. That is unclear as sin. That's like copy constructors in C++. My preference would be a separate keyword which would take the place of the type entirely. It would be treated by the compiler as a type, albeit one which is unknown until the initializer has been semantic'ed. For example, let's call it 'var': var x = 5; var y = "hello"; typeof(x) yields int and typeof(y) yields char[]. This has the nice property of being forward-compatible with more interesting things down the road. How about ATI specialization? var[] x = someFunc(); where x must be an array of any type, which is automatically inferred. It's probably not something that would be that necessary, but it's nice that something like this is possible. Failing a change for ATI, I'll stick with my previously-proposed change for RAII: to use 'scope' as a storage class for a declaration to indicate that it's RAII. scope A a = new A(); scope a2 = new A(); // use ATI since 'scope' functions as a storage class That, or both: scope var a2 = new A(); // RAII and ATI In any case, I think the replies to this thread (and, well, just about every other thread that has EVER been started about this topic) show that you are in a very, very small minority when it comes to ideas about how ATI and RAII should be represented by the syntax. Please do not pull a "just because C++ uses auto for ATI, D should too". D is not going to become a unique language by taking (mis)features from C++ just to appease the nitpicky C++ crowd (which, by now, you should know full well can NEVER be pleased).
Nov 11 2006
Walter Bright wrote:The auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope".As Don explained to me, 'auto' is a storage class in D and in C along with 'const' and 'static', so type inference doesn't occur because 'auto' is present so much as because a type is omitted. The presence of 'auto' merely serves to indicate that the statement is a declaration (since 'auto' is the default storage class and therefore otherwise optional). Type inference occurs with the other storage classes as well. I think this is an important distinction because it seems to be a common misconception that 'auto' means 'infer the type of this expression' and that a specific label is necessary for this feature.The latter only has meaning for class objects, so let's look at the syntax. There are 4 cases: class Class { } 1) auto c = new Class(); 2) auto Class c = new Class(); 3) auto c = some_expression(); 4) auto Class c = some_expression(); The ambiguity can be resolved by saying that if auto is used for type inference, i.e. cases (1) and (3), then it does not mean RAII. If it is not used for type inference, i.e. cases (2) and (4), then it does mean RAII.This is how I currently understand the syntax to work, and once understood it seems fairly clear. However, I don't like overloading the meaning of keywords if it can be avoided, particularly when both meanings apply to the same keyword used in the same context. Also, I'm not sure I like specifying scoped destruction by modifying the reference variable instead of the data. First, this confuses the idea of reference types in that the references themselves are scoped. Second, this doesn't allow for compilers to create referenced data on the stack as a QOI feature because the auto-destruction quality is attached to the reference, not the data. For example: class MyClass { this( char[] s ) { label = s; } ~this() { printf( "dtor: %.*s\n", label ); } char[] label; } void main() { { auto MyClass c = new MyClass( "a" ); c = new MyClass( "b" ); } printf( "done\n" ); } prints: dtor: b done dtor: a If the current syntax is to be preserved, I would suggest that auto references at least not be reassignable to prevent this behavior.In the future, I'd like the following to work: 5) auto c = Class(); which would mean type inference *and* RAII.I like this. It is consistent with the declaration of other types in D ('new' means dynamic, otherwise scoped), and it associates scoped destruction with the data rather than with the reference which is exactly as it should be. In fact, if I had any request related to this syntax it would be that the ctor aspect eventually be available for concrete types as well. Not an urgent request as it would be a new feature, but I thought I'd mention it anyway. Also, I don't see any reason to tie stack vs. heap construction to this new syntax. It could remain a QOI feature for compilers as far as I'm concerned. By the way, I assume this change would do away with: auto class MyClass {} as a valid declaration syntax as well? Just wanted to be clear on this. Sean
Nov 11 2006
Sean Kelly wrote:Walter Bright wrote:Interesting. That does kinda make sense when seen in that light. So it does just mean 'an automatic variable' in the traditional K&R sense. Still don't like it. I can understand that there is some logic behind the madness now, but the logic still doesn't seem like a good justification for confusing special cases. I mean given that meaning of auto, "auto Class c = foo()" should have no more implications than than that of "auto int c = foo()". It should mean stack memory is automatic. If you want to clean up the object too, then you need something else, like another 'auto'. So that would be int c = foo(); // automatic stack (normal) Class c = foo(); // automatic stack (normal) auto int c = foo() // automatic statck (normal) auto Class c = foo() // automatic stack (normal) auto c = foo() // automatic stack, type omitted so inferred auto auto Class c = foo() // automatic stack *and* automatic heap auto auto c = foo() // auto stack *and* auto heap *and* type omitted Throwing in the special case rule 'if the thing is an object then you can leave off one auto' just creates confusion.The auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope".As Don explained to me, 'auto' is a storage class in D and in C along with 'const' and 'static', so type inference doesn't occur because 'auto' is present so much as because a type is omitted. The presence of 'auto' merely serves to indicate that the statement is a declaration (since 'auto' is the default storage class and therefore otherwise optional).But it is ambiguous with static opCall. That doesn't bother you? This works now, but I don't see how it could with the above: ------ import std.stdio:writefln; class Class { static bool opCall() { return true; } this() { } } void main() { auto a = Class(); auto b = new Class(); writefln("typeof a: ", typeid(typeof(a))); writefln("typeof b: ", typeid(typeof(b))); } ------ --bbIn the future, I'd like the following to work: 5) auto c = Class(); which would mean type inference *and* RAII.I like this. It is consistent with the declaration of other types in D ('new' means dynamic, otherwise scoped), and it associates scoped destruction with the data rather than with the reference which is exactly as it should be.
Nov 11 2006
Bill Baxter wrote:Sean Kelly wrote:Agreed.Walter Bright wrote:Interesting. That does kinda make sense when seen in that light. So it does just mean 'an automatic variable' in the traditional K&R sense. Still don't like it. I can understand that there is some logic behind the madness now, but the logic still doesn't seem like a good justification for confusing special cases. I mean given that meaning of auto, "auto Class c = foo()" should have no more implications than than that of "auto int c = foo()". It should mean stack memory is automatic. If you want to clean up the object too, then you need something else, like another 'auto'.The auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope".As Don explained to me, 'auto' is a storage class in D and in C along with 'const' and 'static', so type inference doesn't occur because 'auto' is present so much as because a type is omitted. The presence of 'auto' merely serves to indicate that the statement is a declaration (since 'auto' is the default storage class and therefore otherwise optional).It does. But I'm not sure I prefer the only viable alternative in my mind: MyClass c = scoped MyClass(); (ie. replace 'new' with something else) SeanBut it is ambiguous with static opCall. That doesn't bother you?In the future, I'd like the following to work: 5) auto c = Class(); which would mean type inference *and* RAII.I like this. It is consistent with the declaration of other types in D ('new' means dynamic, otherwise scoped), and it associates scoped destruction with the data rather than with the reference which is exactly as it should be.
Nov 11 2006
Sean Kelly wrote:Walter Bright wrote:True. Consider that type inference works in these cases: static a = 3; // a is an int const b = '3'; // b is a char So auto doesn't actually ever mean "infer the type", it's just needed because one of the other storage class keywords isn't there.The auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope".As Don explained to me, 'auto' is a storage class in D and in C along with 'const' and 'static', so type inference doesn't occur because 'auto' is present so much as because a type is omitted. The presence of 'auto' merely serves to indicate that the statement is a declaration (since 'auto' is the default storage class and therefore otherwise optional). Type inference occurs with the other storage classes as well. I think this is an important distinction because it seems to be a common misconception that 'auto' means 'infer the type of this expression' and that a specific label is necessary for this feature.
Nov 12 2006
On Sun, 12 Nov 2006 12:24:35 +0200, Walter Bright = <newshound digitalmars.com> wrote:Sean Kelly wrote:n =Walter Bright wrote:The auto storage class currently is a little fuzzy in meaning, it ca=g =mean "infer the type" and/or "destruct at end of scope".As Don explained to me, 'auto' is a storage class in D and in C alon=with 'const' and 'static', so type inference doesn't occur because =='auto' is present so much as because a type is omitted. The presence=on =of 'auto' merely serves to indicate that the statement is a declarati=(since 'auto' is the default storage class and therefore otherwise =optional). Type inference occurs with the other storage classes as =e =well. I think this is an important distinction because it seems to b=a common misconception that 'auto' means 'infer the type of this ==expression' and that a specific label is necessary for this feature.True. Consider that type inference works in these cases: static a =3D 3; // a is an int const b =3D '3'; // b is a char So auto doesn't actually ever mean "infer the type", it's just needed =because one of the other storage class keywords isn't there.So according to this logic, auto should always mean RAII? E.g. auto c =3D new Class; //RAII If not, then one could argue that static a =3D 3; declares non-static variable, i.e. the static keyword is used for type = inference only (whenever the type is omited).
Nov 12 2006
Kristian Kilpi wrote:On Sun, 12 Nov 2006 12:24:35 +0200, Walter Bright <newshound digitalmars.com> wrote:Storage class specifiers are really only intended to indicate how the labeled variable (in this case a class reference/pointer) is stored. 'const' places the variable in a special read-only area, 'static' places the variable in static memory, and 'auto' places the variable on the stack. For RAII to apply, the behavior of class references would probably need to change so the referenced value is destroyed when the reference goes out of scope, and this would effectively eliminate any means of returning objects from functions since D objects cannot be passed by value.Sean Kelly wrote:So according to this logic, auto should always mean RAII? E.g. auto c = new Class; //RAIIWalter Bright wrote:True. Consider that type inference works in these cases: static a = 3; // a is an int const b = '3'; // b is a char So auto doesn't actually ever mean "infer the type", it's just needed because one of the other storage class keywords isn't there.The auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope".As Don explained to me, 'auto' is a storage class in D and in C along with 'const' and 'static', so type inference doesn't occur because 'auto' is present so much as because a type is omitted. The presence of 'auto' merely serves to indicate that the statement is a declaration (since 'auto' is the default storage class and therefore otherwise optional). Type inference occurs with the other storage classes as well. I think this is an important distinction because it seems to be a common misconception that 'auto' means 'infer the type of this expression' and that a specific label is necessary for this feature.If not, then one could argue that static a = 3; declares non-static variable, i.e. the static keyword is used for type inference only (whenever the type is omited).Not at all. This declares a type-inferred static variable. The type inference occurs because a type is omitted, but the storage class specifier still applies. The same goes for 'const'. Sean
Nov 12 2006
On Sun, 12 Nov 2006 19:02:18 +0200, Sean Kelly <sean f4.ca> wrote:Kristian Kilpi wrote:On Sun, 12 Nov 2006 12:24:35 +0200, Walter Bright ==<newshound digitalmars.com> wrote:Sean Kelly wrote:Walter Bright wrote:The auto storage class currently is a little fuzzy in meaning, it =can mean "infer the type" and/or "destruct at end of scope".As Don explained to me, 'auto' is a storage class in D and in C =along with 'const' and 'static', so type inference doesn't occur =e =because 'auto' is present so much as because a type is omitted. Th=a =presence of 'auto' merely serves to indicate that the statement is =e =declaration (since 'auto' is the default storage class and therefor==otherwise optional). Type inference occurs with the other storage =it =classes as well. I think this is an important distinction because =e =seems to be a common misconception that 'auto' means 'infer the typ==of this expression' and that a specific label is necessary for this=d =feature.True. Consider that type inference works in these cases: static a =3D 3; // a is an int const b =3D '3'; // b is a char So auto doesn't actually ever mean "infer the type", it's just neede==Storage class specifiers are really only intended to indicate how the =because one of the other storage class keywords isn't there.So according to this logic, auto should always mean RAII? E.g. auto c =3D new Class; //RAIIlabeled variable (in this case a class reference/pointer) is stored. ='const' places the variable in a special read-only area, 'static' plac=es =the variable in static memory, and 'auto' places the variable on the =stack. For RAII to apply, the behavior of class references would =probably need to change so the referenced value is destroyed when the ==reference goes out of scope, and this would effectively eliminate any ==means of returning objects from functions since D objects cannot be =passed by value.So 'auto' in "auto c =3D new Class;" means that 'c' (the variable, not t= he = object referenced by it) is stored in the stack? (That's of course the = case whenever 'static' is not used.) 'auto' has nothing to do when RAII = = should be applied to the referenced object (in princible)?pe =If not, then one could argue that static a =3D 3; declares non-static variable, i.e. the static keyword is used for ty==inference only (whenever the type is omited).Not at all. This declares a type-inferred static variable. The type =inference occurs because a type is omitted, but the storage class =specifier still applies. The same goes for 'const'. SeanYes, I was trying to point out that 'auto' works inlogically when compar= ed = to other store classes. :) 1a) auto c =3D new Class(); //non-RAII 2a) auto Class c =3D new Class(); //RAII 3a) auto c =3D some_expression(); //non-RAII 4a) auto Class c =3D some_expression(); //RAII Now, lets replace 'auto' with 'static': 1b) static c =3D new Class(); //static 2b) static Class c =3D new Class(); //static 3b) static c =3D some_expression(); //static 4b) static Class c =3D some_expression(); //static Because the cases 1b and 3b currently create static variables, so should= = the cases 1a and 3a create RAII objects. (But because auto does not actually mean RAII, well, it's still confusin= g.)
Nov 12 2006
Kristian Kilpi wrote:On Sun, 12 Nov 2006 19:02:18 +0200, Sean Kelly <sean f4.ca> wrote:Yes. auto MyClass c = new MyClass; currently overloads the meaning of 'auto' to specify that the object referenced by 'c' when 'c' goes out of scope will be deleted. Here, 'auto' isn't really a storage class specifier, although it looks like one.Kristian Kilpi wrote:So 'auto' in "auto c = new Class;" means that 'c' (the variable, not the object referenced by it) is stored in the stack? (That's of course the case whenever 'static' is not used.) 'auto' has nothing to do when RAII should be applied to the referenced object (in princible)?On Sun, 12 Nov 2006 12:24:35 +0200, Walter Bright <newshound digitalmars.com> wrote:Storage class specifiers are really only intended to indicate how the labeled variable (in this case a class reference/pointer) is stored. 'const' places the variable in a special read-only area, 'static' places the variable in static memory, and 'auto' places the variable on the stack. For RAII to apply, the behavior of class references would probably need to change so the referenced value is destroyed when the reference goes out of scope, and this would effectively eliminate any means of returning objects from functions since D objects cannot be passed by value.Sean Kelly wrote:So according to this logic, auto should always mean RAII? E.g. auto c = new Class; //RAIIWalter Bright wrote:True. Consider that type inference works in these cases: static a = 3; // a is an int const b = '3'; // b is a char So auto doesn't actually ever mean "infer the type", it's just needed because one of the other storage class keywords isn't there.The auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope".As Don explained to me, 'auto' is a storage class in D and in C along with 'const' and 'static', so type inference doesn't occur because 'auto' is present so much as because a type is omitted. The presence of 'auto' merely serves to indicate that the statement is a declaration (since 'auto' is the default storage class and therefore otherwise optional). Type inference occurs with the other storage classes as well. I think this is an important distinction because it seems to be a common misconception that 'auto' means 'infer the type of this expression' and that a specific label is necessary for this feature.Agreed.Yes, I was trying to point out that 'auto' works inlogically when compared to other store classes. :) 1a) auto c = new Class(); //non-RAII 2a) auto Class c = new Class(); //RAII 3a) auto c = some_expression(); //non-RAII 4a) auto Class c = some_expression(); //RAIIIf not, then one could argue that static a = 3; declares non-static variable, i.e. the static keyword is used for type inference only (whenever the type is omited).Not at all. This declares a type-inferred static variable. The type inference occurs because a type is omitted, but the storage class specifier still applies. The same goes for 'const'.Now, lets replace 'auto' with 'static': 1b) static c = new Class(); //static 2b) static Class c = new Class(); //static 3b) static c = some_expression(); //static 4b) static Class c = some_expression(); //static Because the cases 1b and 3b currently create static variables, so should the cases 1a and 3a create RAII objects. (But because auto does not actually mean RAII, well, it's still confusing.)Yes is is, which is why RAII semantics need to be nailed down before 1.0 in a way that makes sense. Sean
Nov 12 2006
Walter Bright wrote:Sean Kelly wrote:I think it's okay to "have a word" for "infer the type". Think about it like this: through years C folks have used for(int i=0; i<10; ++i) as the default loop construct, never suspecting how shallow their understanding of it really is. But only people with a deeper understanding could write something like for(Node p=list; p; p=p.next) out of their own head. Similarly, having "a word" for automatic type inference is okay, and it won't become any more a hindrance on your way to become a top programmer than the similar misconception about for. Once you've understood the language enough, you'll figure out that it's simply about not specifying a type and just needing a placeholder in the syntax if no other storage attribute happens to be needed. So, it should be no biggie. --- That would be, IMHO, a better solution than the current, where people instead run in circles chasing wild geese, and even highly admired D gurus like Sean have to ask Don about what the hell is going on here. (I know I should have asked Don!) THAT IS UNACCEPTABLE. It is imperative that the language be designed so that such massive confusion simply does not arise. (I know this post may seem self-contradictory at first reading. :-) )Walter Bright wrote:True. Consider that type inference works in these cases: static a = 3; // a is an int const b = '3'; // b is a char So auto doesn't actually ever mean "infer the type", it's just needed because one of the other storage class keywords isn't there.The auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope".As Don explained to me, 'auto' is a storage class in D and in C along with 'const' and 'static', so type inference doesn't occur because 'auto' is present so much as because a type is omitted. The presence of 'auto' merely serves to indicate that the statement is a declaration (since 'auto' is the default storage class and therefore otherwise optional). Type inference occurs with the other storage classes as well. I think this is an important distinction because it seems to be a common misconception that 'auto' means 'infer the type of this expression' and that a specific label is necessary for this feature.
Nov 12 2006
Walter Bright wrote:The auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope". The latter only has meaning for class objects, so let's look at the syntax. There are 4 cases: class Class { } 1) auto c = new Class(); 2) auto Class c = new Class(); 3) auto c = some_expression(); 4) auto Class c = some_expression(); The ambiguity can be resolved by saying that if auto is used for type inference, i.e. cases (1) and (3), then it does not mean RAII. If it is not used for type inference, i.e. cases (2) and (4), then it does mean RAII. In the future, I'd like the following to work: 5) auto c = Class(); which would mean type inference *and* RAII.No, I don't like it, it's awful. As others, I think two different keywords should be added to separate concepts (I do specially agree with Derek). The 'scope' keyword would be nice for raii ('local' could also work but not so clearly with raii classes). For type inference I like 'infer' as it has been suggested. Regards, -- Tom;
Nov 11 2006
Walter Bright wrote:The auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope". The latter only has meaning for class objects, so let's look at the syntax. There are 4 cases: class Class { } 1) auto c = new Class(); 2) auto Class c = new Class(); 3) auto c = some_expression(); 4) auto Class c = some_expression(); The ambiguity can be resolved by saying that if auto is used for type inference, i.e. cases (1) and (3), then it does not mean RAII. If it is not used for type inference, i.e. cases (2) and (4), then it does mean RAII.C'mon man, just introduce the "var" keyword and make everyone happy! <g>In the future, I'd like the following to work: 5) auto c = Class(); which would mean type inference *and* RAII.eeeh .. ? no no, that's awful!! why would a RAII declaration have no "new"? Is it because it's going to be on the stack? Why don't you instead introduce a special case for "new" to make it allocate on the stack, i.e. var c = new(stack) Class(); //or newStack Class(); //or something else which is a clean straight-forward version of: http://digitalmars.com/d/memory.html#stackclass
Nov 11 2006
Walter Bright wrote:The auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope". The latter only has meaning for class objects, so let's look at the syntax. There are 4 cases: class Class { } 1) auto c = new Class(); 2) auto Class c = new Class(); 3) auto c = some_expression(); 4) auto Class c = some_expression(); The ambiguity can be resolved by saying that if auto is used for type inference, i.e. cases (1) and (3), then it does not mean RAII. If it is not used for type inference, i.e. cases (2) and (4), then it does mean RAII.What I would prefer is if you introduced a new keyword that meant "declare". Just that. auto is currently used for type inference not because it MEANS "infer the type" but because it's the default storage class. Currently, declarations look like this: [storage class] [type] [name] We can omit the type if we supply the storage class, or we can omit the storage class if we supply the type. But there's no way to omit both. So I propose that you add a new keyword so that declarations become the following: [declaration] [storage class] [type] [name] This way, we can omit [declaration] if we supply either [storage class] or [type], omit [storage class] if we supply [declaration] or [type], and can omit [type] if we supply [declaration] or [storage type]. Let's say the keyword is chosen to be "def" (being short for "define"). This gives us:Class c = new Class(); // normal decl. def Class c = new Class(); // as above auto Class c = new Class(); // RAII decl. def auto Class c = new Class(); // as above auto c = new Class(); // RAII with type inference def auto c = new Class(); // as above def c = new Class(); // type inference with no RAIIAnother keyword choice could be "let" (which allows you to "read" the declaration out loud). "var" makes no sense since you could conceivably put it before a "const", and that doesn't make any sense:var const x = foo; // Is it a constant or a variable??This will let you keep the "auto" keyword, whilst still giving us what we want -- everybody wins!In the future, I'd like the following to work: 5) auto c = Class(); which would mean type inference *and* RAII.Please, no. It breaks static opCall (which I *do* use), and makes no sense. Everywhere else in D requires the "new" keyword; why not for this one particular case? On a related note, I don't suppose I could ask you to take a second look at my old proposal on allowing auto objects to be returned from functions, could I? :P It is one of the very, very few things I'd still like to see in D 1.0. <http://www.digitalmars.com/d/archives/digitalmars/D/38329.html> -- Daniel -- Unlike Knuth, I have neither proven or tried the above; it may not even make sense. v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Nov 11 2006
Daniel Keep wrote:On a related note, I don't suppose I could ask you to take a second look at my old proposal on allowing auto objects to be returned from functions, could I? :P It is one of the very, very few things I'd still like to see in D 1.0. <http://www.digitalmars.com/d/archives/digitalmars/D/38329.html>It's an interesting proposal. What I was thinking of eventually for 'auto' is to generalize that it means that the value cannot escape its scope. An auto class member could then be destructed when the class was destructed; an auto function parameter cannot escape the function call, etc. But I haven't really thought about it very far.
Nov 12 2006
On Sun, 12 Nov 2006 08:50:51 +0200, Daniel Keep <daniel.keep.lists gmail.com> wrote: [snip]On a related note, I don't suppose I could ask you to take a second look at my old proposal on allowing auto objects to be returned from functions, could I? :P It is one of the very, very few things I'd still like to see in D 1.0. <http://www.digitalmars.com/d/archives/digitalmars/D/38329.html> -- DanielI especially liked the the 'auto members'. It's not uncommon that member variables of an object are only used by the object (they are binded together forming a compact entity), and they should be destroyed with the object. Currently you have to explicitly delete the member variables in the object's destructor, right? Sometimes I miss value types. They are created and destroyed with the parent object automatically. And basically you're trying to create value types here? Objects are destroyed at the end of scopes, and they are cloned/dublicated in assingments. In reference counting the objects themselves are cloned, the data is refenced. Well, actually the reference counts must be updated in assignments. So, what we actually need for reference counting is an ability to override the assignment operators.
Nov 12 2006
"Daniel Keep" <daniel.keep.lists gmail.com> wrote in message news:ej6g8l$2g20$1 digitaldaemon.com...What I would prefer is if you introduced a new keyword that meant "declare". Just that. auto is currently used for type inference not because it MEANS "infer the type" but because it's the default storage class. ... Let's say the keyword is chosen to be "def" (being short for "define").I think this is a good suggestion. Although "infer" is good because it says exactly what it's doing, it just sounds a bit odd for a keyword. I like "def" . I agree with the notion that there should be two different keywords. I think "auto" isn't the most descriptive keyword because, as Ary Manzana pointed out, "automatic what?". Using "scope" or "local" for RIAA is probable better for clarity. But if it had to stay as "auto", it wouldn't be the end of the world, either. :) Regarding the original post: Walter Bright wrote:The auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope". The latter only has meaning for class objects, so let's look at the syntax. There are 4 cases: class Class { } 1) auto c = new Class(); 2) auto Class c = new Class(); 3) auto c = some_expression(); 4) auto Class c = some_expression(); The ambiguity can be resolved by saying that if auto is used for type inference, i.e. cases (1) and (3), then it does not mean RAII. If it is not used for type inference, i.e. cases (2) and (4), then it does mean RAII.I'm not sure people would like having to remember this rule every time they tried to figure out which variables will have their destructors called. Why should explicitly declaring the type of a variable have anything to do with whether it's destructor is called? If I decide to modify my code to "turn on" type inference, I might inadvertently "turn off" the destructor call. Perhaps this came about in an effort to conserve keywords, which is a good goal. That's partly why I asked in my other post if type inference is important: because most people believe it should require another keyword. If you intend to avoid adding another keyword, then perhaps it would be better better for type inference be left out rather than to have the "auto" keyword overloaded as above. (Not that I'm opposed to type inference; I'm not.) Jim
Nov 14 2006
Walter Bright wrote:The auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope". The latter only has meaning for class objects, so let's look at the syntax. There are 4 cases: class Class { } 1) auto c = new Class(); 2) auto Class c = new Class(); 3) auto c = some_expression(); 4) auto Class c = some_expression(); The ambiguity can be resolved by saying that if auto is used for type inference, i.e. cases (1) and (3), then it does not mean RAII. If it is not used for type inference, i.e. cases (2) and (4), then it does mean RAII. In the future, I'd like the following to work: 5) auto c = Class(); which would mean type inference *and* RAII.I add my vote to the many others who want 'scope' for all cases of RAII.
Nov 12 2006
On Sat, 11 Nov 2006 20:48:00 +0200, Walter Bright = <newshound digitalmars.com> wrote:The auto storage class currently is a little fuzzy in meaning, it can ==mean "infer the type" and/or "destruct at end of scope". The latter on=ly =has meaning for class objects, so let's look at the syntax. There are =4 =cases: class Class { } 1) auto c =3D new Class(); 2) auto Class c =3D new Class(); 3) auto c =3D some_expression(); 4) auto Class c =3D some_expression(); The ambiguity can be resolved by saying that if auto is used for type ==inference, i.e. cases (1) and (3), then it does not mean RAII. If it i=s =not used for type inference, i.e. cases (2) and (4), then it does mean==RAII. In the future, I'd like the following to work: 5) auto c =3D Class(); which would mean type inference *and* RAII.I, too, think that we should have new keywords for type inference and RA= II. I like 'var' for type inference. For RAII, I guess 'scope' is ok, even i= f = it's a bit 'funny'; 'scoped' would be better. 'local' would be nice too:= = it's adjective. For example (I use 'scoped' here): var a =3D 1; var int b =3D 2; var c =3D new Class; scoped d =3D new Class; //RAII scoped var e =3D new Class; //RAII What if a RAII keyword could be used with 'new' too? var a =3D new scoped Class; //RAII var b =3D scoped Class; //RAII Well, I think 'auto' would be useful with 'RAII classes' and 'RAII membe= r = variables', if they are implemented in the future. (If a better word = cannot be invented, of course.) E.g. class Foo { auto Bar b; //'b' is automatically destroyed with 'Foo' }
Nov 12 2006
I also am voting the majority, two different words - neither of which are auto, 'var' for inference ( as is used allot in modern C family languages ) , and 'scope' for RAII.5) auto c = Class();Oh the horror!!! Charlie Walter Bright wrote:The auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope". The latter only has meaning for class objects, so let's look at the syntax. There are 4 cases: class Class { } 1) auto c = new Class(); 2) auto Class c = new Class(); 3) auto c = some_expression(); 4) auto Class c = some_expression(); The ambiguity can be resolved by saying that if auto is used for type inference, i.e. cases (1) and (3), then it does not mean RAII. If it is not used for type inference, i.e. cases (2) and (4), then it does mean RAII. In the future, I'd like the following to work: 5) auto c = Class(); which would mean type inference *and* RAII.
Nov 12 2006
Walter Bright wrote:The auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope". The latter only has meaning for class objects, so let's look at the syntax. There are 4 cases: class Class { } 1) auto c = new Class(); 2) auto Class c = new Class(); 3) auto c = some_expression(); 4) auto Class c = some_expression(); The ambiguity can be resolved by saying that if auto is used for type inference, i.e. cases (1) and (3), then it does not mean RAII. If it is not used for type inference, i.e. cases (2) and (4), then it does mean RAII. In the future, I'd like the following to work: 5) auto c = Class(); which would mean type inference *and* RAII.I'd like to see 'auto' remain as it is except for RAII. RAII only makes sense for classes and dynamic arrays, for these 'auto' would only be useful for automatic type inference. E.g: 'auto C c = new C;' is useless and the same as 'C c = new C;' I'd like to see 'scoped' as a new storage class for classes and dynamic arrays. Using it for anything else should be an error. This would mean that 'auto class' would become 'scoped class' too. I'd hate to see 'var', 'let', 'def' etc. introduced as new keywords! Typing time differences for 3-6 letters is in the milliseconds for most coders (I would think) I hope I haven't missed something fundamental, and would be extremely pleased if D 1.0 turns out like this :) *shivers* by the thought of 'var'
Nov 12 2006
Tomas Lindquist Olsen wrote:Walter Bright wrote:I'd like to see 'scoped' as a new storage class for classes and dynamic arrays. Using it for anything else should be an error. This would mean that 'auto class' would become 'scoped class' too.I think scoped int a = expr; should be ok. Allowing that enables you to treat value types and classes uniformly in some template usages. { scoped T a = make_temp_var(); ... } // a has been cleaned up here, whether it was a class or not I don't have a specific use case in mind, but it seems there's no reason to not allow it, since a basic value type acts like it's scoped anyway. --bb
Nov 12 2006
Bill Baxter wrote:Tomas Lindquist Olsen wrote:I think you are right. Hadn't thought of this.Walter Bright wrote:I'd like to see 'scoped' as a new storage class for classes and dynamic arrays. Using it for anything else should be an error. This would mean that 'auto class' would become 'scoped class' too.I think scoped int a = expr; should be ok. Allowing that enables you to treat value types and classes uniformly in some template usages. { scoped T a = make_temp_var(); ... } // a has been cleaned up here, whether it was a class or not I don't have a specific use case in mind, but it seems there's no reason to not allow it, since a basic value type acts like it's scoped anyway. --bb
Nov 13 2006
Tomas Lindquist Olsen wrote:*shivers* by the thought of 'var'I knew that somehow I couldn't be the only one <g>.
Nov 13 2006
"Walter Bright" <newshound digitalmars.com> wrote in message news:ej9acb$1sac$2 digitaldaemon.com...Tomas Lindquist Olsen wrote:I don't see much wrong with 'var'. It has the nice connotation that it represents a variable, at least. As for RAII, just using a keyword alone doesn't seem to cut it. If references are to be automatically deleted at the end of a scope, that infers that a scope is actually introduced, which to me is signified by a matching pair of curly brackets. I'd like to be able to specify the extent of the scope, perhaps like this: void drawBox(Rectangle rect, Colour colour) { scope (DrawingContext dc = createDrawingContext()) { scope (Pen pen = new Pen(colour)) { dc.drawRectangle(pen, rect); } // pen is freed here } // dc is freed here } Used this way, 'scope' as the RAII keyword makes sense.*shivers* by the thought of 'var'I knew that somehow I couldn't be the only one <g>.
Nov 13 2006
JC wrote:void drawBox(Rectangle rect, Colour colour) { scope (DrawingContext dc = createDrawingContext()) { scope (Pen pen = new Pen(colour)) { dc.drawRectangle(pen, rect); } // pen is freed here } // dc is freed here } Used this way, 'scope' as the RAII keyword makes sense.I prefer usual C++ - like RAII style. -- AKhropov
Nov 13 2006
Andrey Khropov wrote:JC wrote:Ugh yes. Please don't force any more extra indentation levels on us! Its bad enough with 'with' already. If you want a new indentation level for every single scoped variable then feel free to make scopes for them all, void drawBox(Rectangle rect, Colour colour) { { scope DrawingContext dc = createDrawingContext(); { scope Pen pen = new Pen(colour); dc.drawRectangle(pen, rect); } // pen is freed here } // dc is freed here } but don't force everyone to do that. --bbvoid drawBox(Rectangle rect, Colour colour) { scope (DrawingContext dc = createDrawingContext()) { scope (Pen pen = new Pen(colour)) { dc.drawRectangle(pen, rect); } // pen is freed here } // dc is freed here } Used this way, 'scope' as the RAII keyword makes sense.I prefer usual C++ - like RAII style.
Nov 13 2006
JC wrote:"Walter Bright" <newshound digitalmars.com> wrote in message news:ej9acb$1sac$2 digitaldaemon.com...My issue with 'var' is that it looks ugly and doesn't really tell you that RAII is in action.Tomas Lindquist Olsen wrote:I don't see much wrong with 'var'.*shivers* by the thought of 'var'I knew that somehow I couldn't be the only one <g>.It has the nice connotation that it represents a variable, at least.The other storage classes work for variables too!As for RAII, just using a keyword alone doesn't seem to cut it. If references are to be automatically deleted at the end of a scope, that infers that a scope is actually introduced, which to me is signified by a matching pair of curly brackets. I'd like to be able to specify the extent of the scope, perhaps like this: void drawBox(Rectangle rect, Colour colour) { scope (DrawingContext dc = createDrawingContext()) { scope (Pen pen = new Pen(colour)) { dc.drawRectangle(pen, rect); } // pen is freed here } // dc is freed here } Used this way, 'scope' as the RAII keyword makes sense.*Please* no!
Nov 13 2006
== Quote from Tomas Lindquist Olsen (tomas famolsen.dk)'s articleJC wrote:But I think 'var' would mean type inference, not RAII."Walter Bright" <newshound digitalmars.com> wrote in message news:ej9acb$1sac$2 digitaldaemon.com...My issue with 'var' is that it looks ugly and doesn't really tell you that RAII is in action.Tomas Lindquist Olsen wrote:I don't see much wrong with 'var'.*shivers* by the thought of 'var'I knew that somehow I couldn't be the only one <g>.[...]
Nov 13 2006
On Mon, 13 Nov 2006 19:24:21 +0200, Tomas Lindquist Olsen = <tomas famolsen.dk> wrote:JC wrote:"Walter Bright" <newshound digitalmars.com> wrote in message ==news:ej9acb$1sac$2 digitaldaemon.com...My issue with 'var' is that it looks ugly and doesn't really tell you =Tomas Lindquist Olsen wrote:I don't see much wrong with 'var'.*shivers* by the thought of 'var'I knew that somehow I couldn't be the only one <g>.that RAII is in action.Well that's the point because 'var' isn't used with RAII but with type = inference only. ;) 'var' just tells you that this is a variable declaration, and that's why= I = like it for TI.It has the nice connotation that it represents a variable, at least.The other storage classes work for variables too!As for RAII, just using a keyword alone doesn't seem to cut it. If =t =references are to be automatically deleted at the end of a scope, tha=by =infers that a scope is actually introduced, which to me is signified ==a matching pair of curly brackets. I'd like to be able to specify the=Also I don't like this syntax. All variables should always be declared a= t = the begining of blocks.extent of the scope, perhaps like this: void drawBox(Rectangle rect, Colour colour) { scope (DrawingContext dc =3D createDrawingContext()) { scope (Pen pen =3D new Pen(colour)) { dc.drawRectangle(pen, rect); } // pen is freed here } // dc is freed here } Used this way, 'scope' as the RAII keyword makes sense.*Please* no!
Nov 13 2006
Kristian Kilpi wrote:On Mon, 13 Nov 2006 19:24:21 +0200, Tomas Lindquist Olsen <tomas famolsen.dk> wrote:Okay seems I misunderstood. Though I dont see why this makes it better. 'auto' as a storage class currently does everything 'var' would do. Only reason this would make sense was if 'auto' was completely removed! Still don't like the look of 'var' though...JC wrote:Well that's the point because 'var' isn't used with RAII but with type inference only. ;) 'var' just tells you that this is a variable declaration, and that's why I like it for TI."Walter Bright" <newshound digitalmars.com> wrote in message news:ej9acb$1sac$2 digitaldaemon.com...My issue with 'var' is that it looks ugly and doesn't really tell you that RAII is in action.Tomas Lindquist Olsen wrote:I don't see much wrong with 'var'.*shivers* by the thought of 'var'I knew that somehow I couldn't be the only one <g>.Also I don't like this syntax. All variables should always be declared at the begining of blocks.It has the nice connotation that it represents a variable, at least.The other storage classes work for variables too!As for RAII, just using a keyword alone doesn't seem to cut it. If references are to be automatically deleted at the end of a scope, that infers that a scope is actually introduced, which to me is signified by a matching pair of curly brackets. I'd like to be able to specify the extent of the scope, perhaps like this: void drawBox(Rectangle rect, Colour colour) { scope (DrawingContext dc = createDrawingContext()) { scope (Pen pen = new Pen(colour)) { dc.drawRectangle(pen, rect); } // pen is freed here } // dc is freed here } Used this way, 'scope' as the RAII keyword makes sense.*Please* no!
Nov 13 2006
"Kristian Kilpi" <kjkilpi gmail.com> wrote in message news:op.tiyvn2xqusumhd mist...It has the nice connotation that it represents a variable, at least.The other storage classes work for variables too!As for RAII, just using a keyword alone doesn't seem to cut it. If references are to be automatically deleted at the end of a scope, that infers that a scope is actually introduced, which to me is signified by a matching pair of curly brackets. I'd like to be able to specify the extent of the scope, perhaps like this: void drawBox(Rectangle rect, Colour colour) { scope (DrawingContext dc = createDrawingContext()) { scope (Pen pen = new Pen(colour)) { dc.drawRectangle(pen, rect); } // pen is freed here } // dc is freed here } Used this way, 'scope' as the RAII keyword makes sense.*Please* no!Also I don't like this syntax. All variables should always be declared at the begining of blocks.According to whom? That's a style thing, not a rule.
Nov 13 2006
On Mon, 13 Nov 2006 20:40:23 +0200, JC <johnch_atms hotmail.com> wrote:"Kristian Kilpi" <kjkilpi gmail.com> wrote in message news:op.tiyvn2xqusumhd mist...It has the nice connotation that it represents a variable, at least.=atThe other storage classes work for variables too!As for RAII, just using a keyword alone doesn't seem to cut it. If references are to be automatically deleted at the end of a scope, th=byinfers that a scope is actually introduced, which to me is signified=ea matching pair of curly brackets. I'd like to be able to specify th=d =extent of the scope, perhaps like this: void drawBox(Rectangle rect, Colour colour) { scope (DrawingContext dc =3D createDrawingContext()) { scope (Pen pen =3D new Pen(colour)) { dc.drawRectangle(pen, rect); } // pen is freed here } // dc is freed here } Used this way, 'scope' as the RAII keyword makes sense.*Please* no!Also I don't like this syntax. All variables should always be declare=Yes, that was just my humble opinion. :) I just think that it would be consistent if all the variables will be = declared in the same place. In addition, that would add an extra level o= f = indentation. I would like to write: void func() { int a; scoped file =3D new File; ... } instead of: void func() { int a; scope(file =3D new File) { ... } } And it gets complicated when more than one scoped variable will be used,= = IMHO.at the begining of blocks.According to whom? That's a style thing, not a rule.
Nov 13 2006
Kristian Kilpi wrote:On Mon, 13 Nov 2006 20:40:23 +0200, JC <johnch_atms hotmail.com> wrote:You're free to have your opinion, but the C++ books I've read disagree with you. The ones I've read advocate declaring variables as close to the point of usage as possible. (Can't remember which books exactly, but probably Stroustrup and/or Meyers' books.) --bbYes, that was just my humble opinion. :) I just think that it would be consistent if all the variables will be declared in the same place.Also I don't like this syntax. All variables should always be declared at the begining of blocks.According to whom? That's a style thing, not a rule.
Nov 13 2006
On Mon, 13 Nov 2006 21:17:32 +0200, Bill Baxter <wbaxter gmail.com> wrote:Kristian Kilpi wrote:Hehheh. Ok, I think I understant the point behind that. Well, I guess both the styles have their own advantages and disadvantages. The style where one declares (almost) all the variables at the begining of the (main) block works for me. Sorry for assuming that this style is the Correct Way(TM)... ;)On Mon, 13 Nov 2006 20:40:23 +0200, JC <johnch_atms hotmail.com> wrote:You're free to have your opinion, but the C++ books I've read disagree with you. The ones I've read advocate declaring variables as close to the point of usage as possible. (Can't remember which books exactly, but probably Stroustrup and/or Meyers' books.) --bbYes, that was just my humble opinion. :) I just think that it would be consistent if all the variables will be declared in the same place.Also I don't like this syntax. All variables should always be declared at the begining of blocks.According to whom? That's a style thing, not a rule.
Nov 13 2006
Kristian Kilpi wrote:On Mon, 13 Nov 2006 21:17:32 +0200, Bill Baxter <wbaxter gmail.com> wrote:It used to be the only way that worked. Early C compilers couldn't cope with variables declared elsewhere. That restriction is long gone, now.Kristian Kilpi wrote:Hehheh. Ok, I think I understant the point behind that. Well, I guess both the styles have their own advantages and disadvantages. The style where one declares (almost) all the variables at the begining of the (main) block works for me. Sorry for assuming that this style is the Correct Way(TM)... ;)On Mon, 13 Nov 2006 20:40:23 +0200, JC <johnch_atms hotmail.com> wrote:You're free to have your opinion, but the C++ books I've read disagree with you. The ones I've read advocate declaring variables as close to the point of usage as possible. (Can't remember which books exactly, but probably Stroustrup and/or Meyers' books.) --bbYes, that was just my humble opinion. :) I just think that it would be consistent if all the variables will be declared in the same place.Also I don't like this syntax. All variables should always be declared at the begining of blocks.According to whom? That's a style thing, not a rule.
Nov 13 2006
"Tomas Lindquist Olsen" <tomas famolsen.dk> wrote in message news:eja9o7$2sd4$1 digitaldaemon.com...JC wrote:Ugliness is in the eye of the beholder. And 'var' was never proposed for RAII."Walter Bright" <newshound digitalmars.com> wrote in message news:ej9acb$1sac$2 digitaldaemon.com...My issue with 'var' is that it looks ugly and doesn't really tell you that RAII is in action.Tomas Lindquist Olsen wrote:I don't see much wrong with 'var'.*shivers* by the thought of 'var'I knew that somehow I couldn't be the only one <g>.
Nov 13 2006
JC wrote:"Tomas Lindquist Olsen" <tomas famolsen.dk> wrote in message news:eja9o7$2sd4$1 digitaldaemon.com...I realise (and was pointed out already that I misunderstood). Ugliness is definitely in the eye of the beholder. For me 'var' makes D look like a dynamically typed language, though I'm obviously biased!JC wrote:Ugliness is in the eye of the beholder. And 'var' was never proposed for RAII."Walter Bright" <newshound digitalmars.com> wrote in message news:ej9acb$1sac$2 digitaldaemon.com...My issue with 'var' is that it looks ugly and doesn't really tell you that RAII is in action.Tomas Lindquist Olsen wrote:I don't see much wrong with 'var'.*shivers* by the thought of 'var'I knew that somehow I couldn't be the only one <g>.
Nov 13 2006
Another argument for using 'auto' for ATI can be making it consistent with how it currently works for classes in DMD: class A { static { auto x = 2; auto y = 42; } auto z = 27; } This works. x and y are static!
Nov 13 2006
Tomas Lindquist Olsen wrote:Another argument for using 'auto' for ATI can be making it consistent with how it currently works for classes in DMD: class A { static { auto x = 2; auto y = 42; } auto z = 27; } This works. x and y are static!I think this works everywhere, as you're free to chain storage classes to your heart's delight: // what is this?? auto const static const static auto x = 5; Sean
Nov 13 2006
Sean Kelly wrote:Tomas Lindquist Olsen wrote:That does not work: scopetest.d(29): redundant storage class 'const' scopetest.d(29): redundant storage class 'static' scopetest.d(29): redundant storage class 'auto'Another argument for using 'auto' for ATI can be making it consistent with how it currently works for classes in DMD: class A { static { auto x = 2; auto y = 42; } auto z = 27; } This works. x and y are static!I think this works everywhere, as you're free to chain storage classes to your heart's delight: // what is this?? auto const static const static auto x = 5; Sean
Nov 13 2006
Tomas Lindquist Olsen wrote:Sean Kelly wrote:Oh, so you can just do: auto const static x = 5; Could be worse, I suppose. SeanTomas Lindquist Olsen wrote:That does not work: scopetest.d(29): redundant storage class 'const' scopetest.d(29): redundant storage class 'static' scopetest.d(29): redundant storage class 'auto'Another argument for using 'auto' for ATI can be making it consistent with how it currently works for classes in DMD: class A { static { auto x = 2; auto y = 42; } auto z = 27; } This works. x and y are static!I think this works everywhere, as you're free to chain storage classes to your heart's delight: // what is this?? auto const static const static auto x = 5; Sean
Nov 13 2006
Sean Kelly wrote:Tomas Lindquist Olsen wrote:It is definitely a bit weird. I would like to see all combinations of these fail. they dont make any sense together. all provide ATI if present. the only problem I can see is if you want to put a constant inside a static block. but maybe that is handled differently? IMHO this would make sense: Invalid: --------- static const x = 5; const static x = 5; const { static x = 5; } any combination of auto and const/static Valid: --------- const x = 5; static x = 5; static { const x = 5; auto x = 5; } const { auto x = 5; } Did I forget any?Sean Kelly wrote:Oh, so you can just do: auto const static x = 5; Could be worse, I suppose. SeanTomas Lindquist Olsen wrote:That does not work: scopetest.d(29): redundant storage class 'const' scopetest.d(29): redundant storage class 'static' scopetest.d(29): redundant storage class 'auto'Another argument for using 'auto' for ATI can be making it consistent with how it currently works for classes in DMD: class A { static { auto x = 2; auto y = 42; } auto z = 27; } This works. x and y are static!I think this works everywhere, as you're free to chain storage classes to your heart's delight: // what is this?? auto const static const static auto x = 5; Sean
Nov 13 2006
Tomas Lindquist Olsen wrote:Sean Kelly wrote: It is definitely a bit weird. I would like to see all combinations of these fail. they dont make any sense together. all provide ATI if present. the only problem I can see is if you want to put a constant inside a static block. but maybe that is handled differently? IMHO this would make sense: Invalid: --------- static const x = 5;What's wrong with static and const together? One says this is actually store with globals not on the stack, the other says the value isn't going to change. Nothing inconsistent about having those two together.
Nov 13 2006
Bill Baxter wrote:Tomas Lindquist Olsen wrote:Does it really make sense to have the programmer decide this distinction? A global const will definitely have static storage. But why not let the compiler decide? I just don't see where having this choice is useful!Sean Kelly wrote: It is definitely a bit weird. I would like to see all combinations of these fail. they dont make any sense together. all provide ATI if present. the only problem I can see is if you want to put a constant inside a static block. but maybe that is handled differently? IMHO this would make sense: Invalid: --------- static const x = 5;What's wrong with static and const together? One says this is actually store with globals not on the stack, the other says the value isn't going to change. Nothing inconsistent about having those two together.
Nov 13 2006
Tomas Lindquist Olsen wrote:Bill Baxter wrote:In a function? In a class? --bbTomas Lindquist Olsen wrote:Does it really make sense to have the programmer decide this distinction? A global const will definitely have static storage. But why not let the compiler decide? I just don't see where having this choice is useful!Sean Kelly wrote: It is definitely a bit weird. I would like to see all combinations of these fail. they dont make any sense together. all provide ATI if present. the only problem I can see is if you want to put a constant inside a static block. but maybe that is handled differently? IMHO this would make sense: Invalid: --------- static const x = 5;What's wrong with static and const together? One says this is actually store with globals not on the stack, the other says the value isn't going to change. Nothing inconsistent about having those two together.
Nov 13 2006
Bill Baxter wrote:Tomas Lindquist Olsen wrote:a static in a class is well defined. so is a const. for me 'static const' reads as having the 'static' redundant. a 'const' in D is by definition static. It cannot change, as only a compile-time constant will qualify, and thus will be the same to all classes of whatever reads it. a function 'const' is very much the same. I fail to come up with a scenario where choosing the storage model for a constant makes any sense! Can you post an example of why we need 'static const' ?Bill Baxter wrote:In a function? In a class? --bbTomas Lindquist Olsen wrote:Does it really make sense to have the programmer decide this distinction? A global const will definitely have static storage. But why not let the compiler decide? I just don't see where having this choice is useful!Sean Kelly wrote: It is definitely a bit weird. I would like to see all combinations of these fail. they dont make any sense together. all provide ATI if present. the only problem I can see is if you want to put a constant inside a static block. but maybe that is handled differently? IMHO this would make sense: Invalid: --------- static const x = 5;What's wrong with static and const together? One says this is actually store with globals not on the stack, the other says the value isn't going to change. Nothing inconsistent about having those two together.
Nov 13 2006
Tomas Lindquist Olsen wrote:Can you post an example of why we need 'static const' ?int foo(int x) { static const i = x; // error, x is not const const j = x; // ok, j is const for duration of foo() call }
Nov 13 2006
Walter Bright wrote:Tomas Lindquist Olsen wrote:Confusing.. I thought const in D meant really 'constant'. If a const in a function can have different values across calls, then I suppose a const for a class can have different value for different instances too? L.Can you post an example of why we need 'static const' ?int foo(int x) { static const i = x; // error, x is not const const j = x; // ok, j is const for duration of foo() call }
Nov 13 2006
Lionello Lunesu wrote:Confusing.. I thought const in D meant really 'constant'. If a const in a function can have different values across calls, then I suppose a const for a class can have different value for different instances too?Yes.
Nov 14 2006
Walter Bright wrote:Lionello Lunesu wrote:Where is this documented? I've tried finding it in the spec but to no luck. I think a section going into details on all storage classes would be a good thing! The main problem I have with the D spec is that a lot of stuff is very spread out, and finding the place where the detail you're looking for is, is often pretty hard.Confusing.. I thought const in D meant really 'constant'. If a const in a function can have different values across calls, then I suppose a const for a class can have different value for different instances too?Yes.
Nov 14 2006
Tomas Lindquist Olsen wrote:The main problem I have with the D spec is that a lot of stuff is very spread out, and finding the place where the detail you're looking for is, is often pretty hard.Agreed. I recommend using the comment page [click the button on the upper right of the spec page] to add cross references to things, and other findings about things that aren't clearly documented. For instance on the operator overload page it doesn't mention opApply, which I think is the natural place you'd go to look for it. But I added a link to where it can be found (statements, under 'foreach') on the comment page. In general I think people should make more use of those comment pages. It's a very nice thing that Walter has added those links to every page of the spec. --bb
Nov 14 2006
Bill Baxter wrote:Tomas Lindquist Olsen wrote:Thanx for pointing this out, I had missed that button. I will definitely start using it, and in cases where I find something added appropriate, I will put it in the wiki! Thanx again for the heads up :)The main problem I have with the D spec is that a lot of stuff is very spread out, and finding the place where the detail you're looking for is, is often pretty hard.Agreed. I recommend using the comment page [click the button on the upper right of the spec page] to add cross references to things, and other findings about things that aren't clearly documented. For instance on the operator overload page it doesn't mention opApply, which I think is the natural place you'd go to look for it. But I added a link to where it can be found (statements, under 'foreach') on the comment page. In general I think people should make more use of those comment pages. It's a very nice thing that Walter has added those links to every page of the spec. --bb
Nov 15 2006
Walter Bright wrote:Tomas Lindquist Olsen wrote:I get "main.d(4): non-constant expression x", with such code: int foo(int x) { //static const i = x; const j = x; // non-constant expression x return 1; } -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#DCan you post an example of why we need 'static const' ?int foo(int x) { static const i = x; // error, x is not const const j = x; // ok, j is const for duration of foo() call }
Nov 14 2006
Tomas Lindquist Olsen wrote:a static in a class is well defined. so is a const. for me 'static const' reads as having the 'static' redundant. a 'const' in D is by definition static. It cannot change, as only a compile-time constant will qualify, and thus will be the same to all classes of whatever reads it. a function 'const' is very much the same. I fail to come up with a scenario where choosing the storage model for a constant makes any sense! Can you post an example of why we need 'static const' ?Much like "auto", D's "const" is ambiguous, it represents two different concepts: compile time constant. You get the first with something like: const int foo = 2; // compile time constant You get the second with: const int foo; this() { foo = 2; } that is, the final-like-const variable (foo here) must be initialized in the constructor of the class/struct or module where it is a member of. So, the compile-time-const does not make sense with "static", but the final-like-const does: --- module test; static const int foo; static this() { foo = 42; } void test() { int a = foo; // Ok foo = 2; // Error "can only initialize const foo inside constructor" // AKA foo is final } -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Nov 14 2006
Walter Bright wrote:The auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope". The latter only has meaning for class objects, so let's look at the syntax. There are 4 cases: class Class { } 1) auto c = new Class(); 2) auto Class c = new Class(); 3) auto c = some_expression(); 4) auto Class c = some_expression(); The ambiguity can be resolved by saying that if auto is used for type inference, i.e. cases (1) and (3), then it does not mean RAII. If it is not used for type inference, i.e. cases (2) and (4), then it does mean RAII. In the future, I'd like the following to work: 5) auto c = Class(); which would mean type inference *and* RAII.I'm going to chime in with the people who don't like (5). I'd much prefer reusing 'scope' or some such.
Nov 12 2006
On Mon, 13 Nov 2006 01:58:21 -0500, Chad J wrote:Walter Bright wrote:Has anyone worked out how to grep for instances of RAII and/or TI using this proposed syntax? I mean if I wanted to locate all the places where I was using (only) RAII, what would be the regular expression to do that? The same with TI? I'm sure it can be done but I'm no RE guru. -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocrity!" 13/11/2006 6:26:08 PMThe auto storage class currently is a little fuzzy in meaning, it can mean "infer the type" and/or "destruct at end of scope". The latter only has meaning for class objects, so let's look at the syntax. There are 4 cases: class Class { } 1) auto c = new Class(); 2) auto Class c = new Class(); 3) auto c = some_expression(); 4) auto Class c = some_expression(); The ambiguity can be resolved by saying that if auto is used for type inference, i.e. cases (1) and (3), then it does not mean RAII. If it is not used for type inference, i.e. cases (2) and (4), then it does mean RAII. In the future, I'd like the following to work: 5) auto c = Class(); which would mean type inference *and* RAII.I'm going to chime in with the people who don't like (5). I'd much prefer reusing 'scope' or some such.
Nov 12 2006