digitalmars.D - Worst ideas/features in programming languages?
- Atila Neves (8/8) Oct 11 2021 I'm brainstorming about what I'll talk about at DConf, and during
- FeepingCreature (26/34) Oct 11 2021 Objectively worst feature: mutability/referenceability by
- russhy (13/54) Oct 11 2021 - features that require a GC (associative array)
- James Blachly (8/19) Oct 11 2021 100%. I am really loving Ilya's `mir.algebraic` for my sumtype needs:
- Paul Backus (5/9) Oct 11 2021 The real missing piece here IMO is DIP 1038 [1]. Once it is fully
- Nick Treleaven (4/7) Oct 12 2021 Could you explain how @nodiscard would help with sum types?
- Paul Backus (6/13) Oct 12 2021 Currently, the big advantage exceptions have over sum types is
- max haughton (5/20) Oct 12 2021 One idea I had when bumping into this problem was something like
- Paul Backus (21/25) Oct 12 2021 You can technically do this already with `foreach` and `opApply`,
- max haughton (3/25) Oct 12 2021 I hate this and I hate you!
- 9il (3/9) Oct 12 2021 Maybe you mean that one?
- Johan (12/17) Oct 11 2021 Two things that immediately come to mind:
- jmh530 (4/9) Oct 11 2021 Nothing prevents you from pulling out the unittests (except maybe
- jfondren (64/70) Oct 11 2021 Indirect method notation in Perl:
- Dukc (22/29) Oct 11 2021 - Some C standard library functions. `gets` is the worst one, but
- russhy (29/32) Oct 11 2021 It's been a while i haven't used anything other than D, so i
- 12345swordy (4/7) Oct 11 2021 WHY!?
- 12345swordy (5/8) Oct 11 2021 WHY!?
- russhy (15/22) Oct 11 2021 it is not GC phobia, i use the GC for some projects and i'm ok
- Nicholas Wilson (3/5) Oct 11 2021 try a `@nogc` main() function. Yes this doesn't handle module
- russhy (9/16) Oct 12 2021 because, as other said, it is hard to differentiate from struct
- 12345swordy (6/19) Oct 13 2021 It is not an issue if you have a functional IDE that does the
- Atila Neves (14/18) Oct 14 2021 The enum thing works now:
- Dr Machine Code (12/29) Nov 14 2021 This unscoped enums is one of the worst features in C/C++, imho.
- russhy (28/58) Nov 15 2021 It's not unscoped, it type checked, it just removes the need to
- H. S. Teoh (18/33) Nov 15 2021 [...]
- kdevel (13/25) Nov 15 2021 Nice. What about
- H. S. Teoh (17/46) Nov 15 2021 [...]
- russhy (9/55) Nov 15 2021 that's not what i am asking
- russhy (9/40) Nov 17 2021 I don't understand your point, that is exactly what i said, a
- bachmeier (32/36) Oct 11 2021 C's pointer notation is too stupid for words. (I understand how
- drug (5/49) Oct 11 2021 I would say that `x` is a pointer to int and `*x` is a dereferenced
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (10/19) Oct 24 2021 Yes, it is cultural debt, that came from a desire to express
- SealabJaster (5/14) Oct 24 2021 I imagine && and || stem from & and |. You could probably have
- SealabJaster (5/8) Oct 24 2021 Adding onto that, a "pineapple on pizza" sort of thing is that
- Ola Fosheim =?UTF-8?B?R3LDuHN0YQ==?= (9/12) Oct 24 2021 That was why C used it, but it leads to uneccessary problems with
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (12/16) Oct 24 2021 Sorry for all the typos (ipad)...
- SealabJaster (14/18) Oct 24 2021 This has sent me through a slightly on topic yet mostly off topic
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (36/46) Oct 24 2021 Yes, and all those really grow out of C++ (except JavaScript that
- claptrap (10/16) Oct 24 2021 Because boolean algebra was already a thing and it was symbolic
- Imperatorn (8/25) Oct 24 2021 This might be a good reason actually.
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (17/25) Oct 24 2021 I think "not being childish" is a sign of fashion-elitism if it
- claptrap (18/40) Oct 24 2021 I dont think it does make code less legible. I mean the whole
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (14/24) Oct 24 2021 The only reason for doing it is that C used it. If there is any
- claptrap (36/61) Oct 25 2021 I'm saying it probably initially came from boolean algebra in
- bauss (3/7) Oct 25 2021 Math, sure. Electronics, doubt; considering Algorithm for the
- ClapTrap (7/15) Oct 25 2021 What I'm getting at is that whoever designed B, C or whatever
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (14/28) Oct 25 2021 Yes, and that has been evolving as well. Often times they had to
- ClapTrap (22/46) Oct 25 2021 Well probably they had their own notation on actual pen and
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (25/39) Oct 25 2021 Why personal attacks? If you read old math writings you will see
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (20/33) Oct 25 2021 So, to bring this discussion to an end: I am not saying that
- ClapTrap (14/39) Oct 25 2021 I dont think it is a personal attack to say you dont seem to
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (13/22) Oct 25 2021 Fair enough, let us say only libraries and frameworks extend the
- ClapTrap (8/14) Oct 26 2021 Is it ad hominen to point out that you seem to jump to certain
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (6/11) Oct 26 2021 Yes. You are making assumptions from arbitrary examples. Don't do
- ClapTrap (9/14) Oct 26 2021 When keep using terms like elitist, fashionista, wanabee, to
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (10/13) Oct 26 2021 Good grief. What people? I am making up arbitrary examples
- ClapTrap (13/26) Oct 26 2021 You literally said there's no rational reason to choose "&&" over
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (14/24) Oct 26 2021 Uhm. I most certainly enjoyed how cool my Husqvarna 242G was when
- ClapTrap (21/43) Oct 26 2021 "It us equally puzzeling why prople want "&&" instead of "and" or
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (32/54) Oct 26 2021 Yes, nothing about "elitist blowhard". Why are you obsessing over
- ClapTrap (22/43) Oct 27 2021 Exactly!! If they are technically comparable then you would
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (39/52) Oct 27 2021 Hm, I don't think anyone are making high speed chainsaws anymore
- Guillaume Piolat (8/14) Oct 25 2021 Like genetic random drift, those boolean operators are mostly
- ClapTrap (4/18) Oct 25 2021 Pascal has shr, shl, begin, end, maybe other wordy stuff, where
- Guillaume Piolat (2/4) Oct 25 2021 baby vs bathwater
- ClapTrap (4/10) Oct 25 2021 I know the idiom but I dont understand what you mean in this
- Guillaume Piolat (3/14) Oct 26 2021 Er sorry. I was just meaning that Pascal did have good ideas that
- Basile B. (25/27) Oct 26 2021 The line is simply the style consistency.
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (8/11) Oct 26 2021 No, to be consistent with other infix operators for integers +*/-
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (5/7) Oct 27 2021 Please note that the original Pascal did not have bit operations
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (13/13) Oct 27 2021 FWIW, from Stefik and Sibert, «An Empirical Investigation into
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (10/13) Oct 27 2021 Another paper, Altadmri and Brown, «37 Million Compilations:
- Basile B. (9/22) Oct 27 2021 I'm a bit surprised by the results of these studies. I'd say that
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (34/43) Oct 27 2021 My phrasing may have been a bit imprecise. The students were
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (5/14) Oct 27 2021 May also add that the number of years they had used C++ did
- Basile B. (3/9) Oct 28 2021 Yeah, that's a point of agreement.
- Dom DiSc (7/19) Oct 28 2021 As with all statistics the answers are heavily biased by the
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (3/6) Oct 28 2021 "v" was available, but I don't think they got unicode
- jfondren (5/11) Oct 28 2021 https://tryapl.org/
- Dom DiSc (4/7) Oct 28 2021 Only that ^ atm is used as xor, not and :-(
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (4/7) Oct 28 2021 I think you would have to write to the authors to find out all
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (8/16) Oct 28 2021 Ok, so I read the article again and they did and they were ranked
- Abdulhaq (4/16) Oct 28 2021 In case anyone is unfamiliar with it, Notation As A Tool Of
- Guillaume Piolat (7/8) Oct 11 2021 1 - WebAssembly support in druntime. By far #1 for me.
- Adam D Ruppe (15/18) Oct 11 2021 Well not a feature per se, but the idea that number of keywords
- Adam D Ruppe (2/4) Oct 11 2021 err there is NO simple metric here.
- Dr Machine Code (2/20) Nov 14 2021 could you give an example on how those features would be like?
- RazvanN (4/12) Oct 11 2021 Worst features:
- 12345swordy (13/27) Oct 11 2021 Yes! This right here is the worst feature as it is a source of
- jmh530 (2/9) Oct 11 2021 Interfaces can have final methods, you just can't overwrite them.
- 12345swordy (3/15) Oct 11 2021 Did you not read the file that I linked?
- jmh530 (2/8) Oct 11 2021 I skimmed it.
- monkyyy (13/16) Oct 11 2021 * nontrivial namespace collisions when importing std
- jfondren (14/15) Oct 11 2021 Are these still around? This compiles now:
- monkyyy (2/17) Oct 12 2021 The one that annoyed me was stdio and file, write
- Atila Neves (3/14) Oct 14 2021 Interesting. What is it about safe by default that would worry
- Paul Backus (8/13) Oct 14 2021 I've interacted with monkyyy a bunch in the community Discord.
- jfondren (13/27) Oct 14 2021 The emphasis there should be on "sword of damocles" (uncertainty
- monkyyy (2/24) Oct 30 2021 verbosity
- apz28 (17/21) Oct 11 2021 Attribute soup
- max haughton (20/28) Oct 11 2021 __traits should've died years ago. Its continued existence shows
- Nicholas Wilson (19/34) Oct 11 2021 I think a big problem from an exploratory perspective is that
- Nicholas Wilson (3/7) Oct 11 2021 real, specifically fp80 real. Its slow, its almost always
- SealabJaster (41/44) Oct 11 2021 Autodecoding. Autodecoding. Autodecoding.
- surlymoor (10/13) Oct 11 2021 I just want to be able to have a returned value be implicitly
- James Blachly (2/9) Oct 13 2021 Hear, hear
- bauss (4/6) Oct 11 2021 I agree with this so much, like why couldn't it have been made so
- Steven Schveighoffer (4/14) Oct 12 2021 Just FYI, the `abc => {}` syntax is just recently deprecated.
- bauss (6/22) Oct 12 2021 Yeah, but I would rather that it was still allowed and that the
- Steven Schveighoffer (6/30) Oct 12 2021 What would you change it to?
- Paul Backus (10/18) Oct 12 2021 IMO the actual answer here is to deprecate the `{ /* ... */ }`
- Steven Schveighoffer (11/31) Oct 12 2021 It's not a terrible idea. But I think there are hacks all over the place...
- Paul Backus (10/19) Oct 12 2021 This syntax is cute, but it's also extremely opaque, and
- user1234 (6/17) Oct 12 2021 But you are do it explicitly, use the more verbose syntax:
- zjh (27/29) Oct 11 2021 What I want to change:
- Paulo Pinto (17/25) Oct 11 2021 - Null terminated strings without length validation
- Kagamin (14/14) Oct 12 2021 Usage of unsigned integers as positive numbers.
- Superstar64 (15/23) Oct 12 2021 Not necessarily a feature, but I think the absence of hindley
- rikki cattermole (4/8) Oct 12 2021 Hey hey hey, ML strikes again!
- Imperatorn (2/10) Oct 12 2021 foreach_reverse - worst "feature" mankind has produced
- Dr Machine Code (2/15) Nov 14 2021 why is it that bad? lol
- Imperatorn (3/19) Nov 14 2021 It's just so ugly 😅
- tsbockman (4/11) Nov 14 2021 The keyword isn't pretty, but it's useful, easy to understand,
- Imperatorn (3/15) Nov 15 2021 Well, obviously :)
- Timon Gehr (7/25) Nov 15 2021 The reason it exists is that reverse iteration over unsigned types is
- Imperatorn (2/16) Nov 15 2021 What's wrong about retro? Too retro :D
- Paul Backus (3/4) Nov 15 2021 std.range.retro is honestly just a bad name. It should have been
- Basile B. (19/24) Nov 15 2021 That reverser thing could have been a builtin property e.g
- deadalnix (5/10) Dec 17 2021 ```
- Timon Gehr (7/24) Nov 15 2021 My post was literally a description of drawbacks of retro. There's
- Steven Schveighoffer (8/34) Nov 15 2021 Although it's fallen mostly out of style, the reason I hated
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (3/5) Nov 15 2021 Pinkie?
- Adam D Ruppe (5/7) Nov 15 2021 ~/arsd$ grep foreach_reverse *.d | wc
- Quirin Schroll (8/14) Dec 18 2021 Maybe this is older. When I came to D around 2015, I learned that
- Steven Schveighoffer (23/37) Dec 21 2021 You can foreach an appropriately typed delegate too.
- H. S. Teoh (90/97) Oct 12 2021 - C:
- Paul Backus (34/50) Oct 12 2021 You can get about 90% of the way to better constraint errors with
- russhy (10/61) Oct 12 2021 templates doesn't work with DCD/DSymbol because it doesn't do
- Paul Backus (5/11) Oct 12 2021 If anyone wants to work on a DIP and implementation for built-in
- max haughton (3/15) Oct 12 2021 I think such a feature would benefit from having tuple syntax and
- russhy (19/31) Oct 13 2021 it worth doing the extra kilometer to avoid having the situation
- Paul Backus (15/26) Oct 13 2021 Sometimes the difference is not between "easy" and "hard", but
- SealabJaster (4/8) Oct 13 2021 Possibly, in a parallel universe. I guess that kind of goes for
- jmh530 (15/35) Oct 12 2021 I've become more sympathetic to this. The main argument against
- Timon Gehr (75/79) Oct 12 2021 This is likely to be incomplete or overly abstract, but here's my
- surlymoor (3/4) Oct 12 2021 Is the issue default initialization or that the property is named
- Timon Gehr (9/13) Oct 12 2021 Uninitialized variables are not an option, so default initialization
- Q. Schroll (4/8) Nov 15 2021 The fact that the default value of a type `T` is `T.init` and
- Timon Gehr (3/12) Nov 15 2021 That's not close to all the problems and at least you can `@disable enum...
- Timon Gehr (3/5) Oct 12 2021 - local imports that implicitly hide symbols from outer scopes in
- user1234 (3/19) Oct 12 2021 Please mention the language for each point. I think that
- Walter Bright (2/3) Oct 15 2021 It's already implemented for @live.
- Timon Gehr (8/12) Nov 09 2021 Specifically, I would like it to influence scoping.
- Stefan Koch (2/14) Nov 10 2021 That would be a good start. I would support that.
- Sebastiaan Koppe (2/14) Nov 10 2021 Yeah, that would be lovely.
- H. S. Teoh (5/20) Nov 10 2021 That would allow a better implementation of ownership tracking.
- Stefan Koch (3/24) Nov 10 2021 Other way around.
- H. S. Teoh (8/28) Nov 10 2021 That's what I meant. :D If the compiler has this tracking, then it
- Walter Bright (6/21) Dec 28 2021 @live currently does that for pointers, but not for non-pointers. What's...
- Petar Kirov [ZombineDev] (22/38) Dec 29 2021 The typestate [1] design pattern. In languages that support some
- Walter Bright (2/23) Jan 07 2022 Thanks, I did not know that.
- Timon Gehr (14/41) Jan 03 2022 It removes the variable from the scope? (And anyway, @live is a function...
- Walter Bright (10/40) Jan 07 2022 @live applies to all the contents of the function.
- Timon Gehr (11/63) Jan 09 2022 The language can't know what's designed to act like a pointer.
- Timon Gehr (3/7) Nov 14 2021 (Also, I want it based on the types of the involved values, not based on...
- Atila Neves (8/19) Nov 05 2021 For what types? It doesn't compile for pointers, for instance,
- victoroak (28/33) Nov 05 2021 Well, I can't answer for him but `void` initialization and
- H. S. Teoh (8/52) Nov 05 2021 @safe does not mean enforcing type constraints. It means *memory*
- victoroak (6/10) Nov 05 2021 `.init` was not mentioned as breaking `@safe` just as a bad
- Paul Backus (3/17) Nov 05 2021 ...which is one of the reasons we need @system variables:
- Atila Neves (6/44) Nov 08 2021 Interesting. Adding an invariant causes compilation to fail:
- Timon Gehr (5/59) Nov 09 2021 Well, that makes some sense, but a struct can have an invariant without
- Atila Neves (6/22) Nov 09 2021 IMHO -release mode really shouldn't be used, but since contracts
- Timon Gehr (5/30) Nov 10 2021 "Add an empty invariant to your types for maximum type safety", "we have...
- deadalnix (3/8) Dec 17 2021 This is unfortunately true. This is pervasive in D and by far the
- Timon Gehr (54/89) Nov 10 2021 The goal of construction is to create an instance that usually should
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (6/15) Nov 11 2021 I don't see how ```.init``` is related to null as long as you can
- Dr Machine Code (9/94) Nov 14 2021 example?
- Timon Gehr (105/171) Nov 14 2021 auto (a,b) = (1,2);
- Arjan (4/22) Nov 15 2021 Just WOW.
- Timon Gehr (9/24) Nov 15 2021 Some reassurance that it won't be shot down for stupid reasons would go
- Patrick Schluter (6/31) Nov 17 2021 The proposition at that time was stalled because it collided with
- Atila Neves (3/19) Nov 23 2021 I don't see any good reason to shut it down, never mind stupid
- Timon Gehr (3/22) Nov 23 2021 There are some details such as ABI and sizeof(()). I'll probably get
- Arjan (4/13) Nov 24 2021 That will be highly appreciated.
- Walter Bright (3/10) Dec 28 2021 Actually, I agree with the need for tuples, and am very open to a good d...
- Tejas (6/18) Dec 28 2021 Sorry if this sounds very naive, but if we can't use the `struct`
- Walter Bright (3/5) Dec 28 2021 I'd like to see something that unified arrays, structs, argument lists (...
- Dukc (29/34) Dec 29 2021 I think we should unify static arrays and tuples, and call it a
- Timon Gehr (6/12) Jan 02 2022 I would like to do that, but I think it would break code like this:
- Timon Gehr (5/21) Jan 02 2022 And there is also this:
- Walter Bright (3/10) Jan 03 2022 With such implicit conversions, the language would just descend into cha...
- Timon Gehr (16/27) Jan 03 2022 It's not an implicit conversion. I am mostly trying to figure out what
- Walter Bright (4/39) Jan 03 2022 That isn't what I meant. I mean that there are easy ways to convert from...
- Timon Gehr (8/26) Jan 03 2022 If `foo(int, int)` is defined to be literally the same as `foo(int[2])`,...
- Walter Bright (5/14) Jan 03 2022 Currently, tuples can map right on to argument lists, there is no conver...
- Paul Backus (9/13) Jan 04 2022 "Destructuring" means binding members of a tuple to separate
- Walter Bright (1/1) Jan 07 2022 Thanks, I know what that was, I just didn't know the jargon for it.
- Timon Gehr (31/50) Jan 04 2022 But in the example above, those so-called "tuples" would expand right
- Walter Bright (3/64) Jan 07 2022 I don't know. I'll have to look at your proposals.
- Walter Bright (9/9) Jan 07 2022 I'm concerned about what would happen to the following.
- Timon Gehr (10/23) Jan 09 2022 x is equivalent to (x). (Always, and a design that changes that is broke...
- Timon Gehr (4/8) Jan 09 2022 (Technically, I guess if `a, b or c` is an expression/expanded tuple of
- Walter Bright (17/33) Jan 03 2022 Not exactly, since the ABI won't permit it. For example,
- Timon Gehr (23/64) Jan 03 2022 My DIP draft extends "alias this" to allow this (which should work anywa...
- Timon Gehr (6/12) Jan 03 2022 (I understand that there is something in the DMD source code already
- rikki cattermole (6/11) Jan 03 2022 Actually this is kinda what I want.
- Timon Gehr (3/19) Jan 03 2022 My point was not that you don't want this, it was that calling it a
- Timon Gehr (3/23) Jan 03 2022 (Also, having only the expanding variety of this is just not very useful...
- Walter Bright (2/16) Jan 08 2022 Yes, and reconciling this will be the problem.
- Timon Gehr (25/42) Jan 09 2022 I agree. This is what I had in mind:
- zjh (4/4) Jan 09 2022 On Sunday, 9 January 2022 at 10:35:03 UTC, Timon Gehr wrote:
- zjh (4/4) Jan 09 2022 On Sunday, 9 January 2022 at 10:35:03 UTC, Timon Gehr wrote:
- max haughton (2/6) Jan 09 2022 D does have it
- zjh (9/10) Jan 09 2022 folding expression `...`,like this:
- Walter Bright (6/27) Jan 04 2022 I confess, this makes me uneasy. `alias this` produced a lot of unintend...
- Timon Gehr (6/40) Jan 04 2022 How about something like opArgs, dealing specifically with this case?
- Timon Gehr (4/17) Jan 04 2022 (This would apply symmetrically at the call site, so that if we define a...
- Paul Backus (14/18) Jan 05 2022 This mechanism seems too powerful to me; for example, one could
- Timon Gehr (3/26) Jan 05 2022 Why is that a surprise? You could similarly do something like:
- Paul Backus (14/29) Jan 05 2022 Perhaps this is a better illustration:
- Timon Gehr (7/30) Jan 06 2022 No, it's the same thing. I understand what you are saying, I just don't
- Timon Gehr (13/29) Jan 06 2022 BTW, it should work like this:
- Paul Backus (20/32) Jan 06 2022 Actually I think you were on the right track in [your earlier
- Max Samukha (3/4) Jan 08 2022 While you are correct, it is likely to be a breaking change.
- Timon Gehr (2/8) Jan 09 2022 True.
- Tejas (14/34) Jan 05 2022 Yeah, and what does "exactly once" mean here?
- Paul Backus (16/27) Jan 05 2022 I assume it means "once per argument"; i.e., the rewrite is not
- bauss (10/30) Jan 05 2022 You could just make sure that the root type is always used if an
- Timon Gehr (5/42) Jan 06 2022 No, if you want the root type, add a trailing comma to the declaration:
- Timon Gehr (3/15) Jan 06 2022 (But in general, yes, using `alias this` was my initial proposal and I
- Paul Backus (10/38) Jan 06 2022 Sure. You could make overload resolution consider a call that
- Walter Bright (2/6) Jan 08 2022 Sounds like a promising idea.
- Paul Backus (12/20) Jan 05 2022 Is this really necessary or even desirable? Tuples do not
- Timon Gehr (20/46) Jan 05 2022 This is not about auto-expanding. Conceptually, functions with multiple
- ryuukk_ (9/11) Dec 29 2021 Yes please! some love for tuples is very much needed, recently
- Nick Treleaven (28/92) Nov 15 2021 Yes please.
- Walter Bright (7/10) Dec 28 2021 `alias this` suffers from being under-specified. In an attempt to fix th...
- 12345swordy (12/14) Dec 28 2021 I am in strong favor of being replaced rather than redesigned.
- Timon Gehr (3/4) Nov 22 2021 Another thing I have sometimes wished for, but forgot to include:
- bauss (23/28) Nov 23 2021 What do you mean by that?
- Timon Gehr (5/42) Nov 23 2021 Yes, something like this. Thanks for clarifying! This is a module
- Stefan Koch (8/38) Nov 23 2021 I think that is what he means.
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (4/7) Nov 23 2021 IIRC, Bjarne Stroustrup was advised to use the less problematic
- Tejas (3/8) Nov 23 2021 You mean showing the `static this()` to accept parameters? That'd
- Tejas (2/12) Nov 23 2021 Not showing, I meant 'allowing'
- sarn (48/56) Oct 12 2021 Go's implicit duck-typing of structs to interfaces. Things don't
- Jacob Carlborg (76/79) Oct 13 2021 I can't believe no one has mentioned this yet: PHP register
- Imperatorn (4/10) Oct 13 2021 "Native tuples with destruction", are you sure you don't want
- Jacob Carlborg (4/6) Oct 13 2021 Yes, that's what I meant.
- bauss (37/40) Oct 14 2021 This would be better if the identifier was tied to the type.
- bauss (2/44) Oct 14 2021 Ofc. these are supposed to be writefln and not writeln.
- deadalnix (9/15) Oct 13 2021 It's a hard one. Variables implicitly declared as global in JS
- JN (36/44) Oct 14 2021 Worst features in a non-toy language. This is going to be
- bauss (67/75) Oct 14 2021 You can somewhat hack your way to it, by generating static
- IGotD- (18/19) Oct 14 2021 This is not a feature but a language design question. One of the
- Nicholas Wilson (7/17) Oct 14 2021 they added `if constexpr` not `static if`, which is another thing
- Stefan Koch (11/18) Oct 15 2021 Actually that avoids many tricky problems in the compiler
- Antonio (63/71) Oct 15 2021 About Wrong D features:
- IGotD- (7/8) Oct 15 2021 Rust has GC, i.e. reference counting. This is also often required
- Antonio (21/31) Oct 15 2021 Hi IGotD- really fast response :-)
- Imperatorn (3/10) Oct 15 2021 I'm not sure what you mean by your gc/nogc comment. Could you
- bauss (3/17) Oct 15 2021 I think that's his problem. D doesn't have a specific philosophy
- deadalnix (6/8) Oct 15 2021 This is fine. But here is the deal: that means D cannot have a
- russhy (10/18) Oct 15 2021 using allocators aware APIs solves all of this, look at zig!
- Paul Backus (3/8) Oct 15 2021 This is just bad naming--`isNull` should be called `empty`. It
- russhy (2/15) Oct 15 2021 Now let's break code again and rename it!
- deadalnix (8/22) Oct 15 2021 Many D construct assume a GC. Which kinda is the point. Either
- SomeGuy (9/13) Oct 15 2021 This problem could still be solved by making the GC just another
- Imperatorn (2/18) Oct 15 2021 Bring back new and make it configurable 😎
- Dylan Graham (2/17) Oct 15 2021 Maybe I can make LWDR do this.
- IGotD- (13/22) Oct 15 2021 The biggest obstacle is that D has no fat pointers. It has only
- Araq (4/18) Oct 15 2021 Er, that's not how Nim's "fat pointers" work and the term is
- IGotD- (2/5) Oct 15 2021 So how do they work then, when you have set the GC to default ORC?
- SomeGuy (35/47) Oct 15 2021 Yeah, what I was proposing is not actually for adding custom GC
- deadalnix (23/28) Oct 15 2021 You kind have to, the alternative being that the library aren't
- SealabJaster (6/8) Oct 15 2021 Is there anything we can do to start addressing this, and the
- deadalnix (70/78) Oct 15 2021 Well at some point we need to make choices about the invariant we
- russhy (18/101) Oct 15 2021 What is your plan to make GC incremental? what about latency
- deadalnix (10/13) Oct 16 2021 I asserted to write an elaborated answered and then decided to
- Imperatorn (2/7) Oct 16 2021 Hence the solution is to improve the GC 😎
- deadalnix (4/14) Oct 16 2021 No.
- Imperatorn (2/17) Oct 16 2021 I inserted the emoji there but it didn't work 😑
- FeepingCreature (3/22) Oct 17 2021 Works fine here. I just think that it wasn't clear whatever you
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (16/19) Oct 18 2021 Well, yes, malloc is only the default, when people want speed in
- deadalnix (7/9) Oct 18 2021 It doesn't matter. These allocator need memory from the system
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (2/4) Oct 18 2021 Yes, but often times they don't release it until program exit.
- deadalnix (3/7) Oct 18 2021 That still doesn't change anything to the point made.
- russhy (29/52) Oct 18 2021 and then you freeze all threads and must scan all allocated
- russhy (32/40) Oct 15 2021 In the end, i think it doesn't really matter to be honest, as
- deadalnix (3/6) Oct 16 2021 That really doesn't work in practice, as it prevent libraries
- russhy (3/19) Oct 15 2021 Yes i agree with you, that would make everyone happy and would be
- Paulo Pinto (3/22) Oct 15 2021 Except safety, using Zig is no better than Modula-2, as it
- Imperatorn (2/20) Oct 15 2021 Oh, I see 😎
- Andrei Alexandrescu (2/2) Oct 15 2021 I have one!
- 12345swordy (5/7) Oct 15 2021 Context: Andrei is expressing his frustration with noreturn in
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (18/21) Oct 15 2021 Difficult to say, features may not be bad in isolation, but turn
- Rumbu (31/39) Oct 15 2021 I work mostly in c#
- bauss (8/9) Oct 19 2021 Finally got one for D.
- Andrea Fontana (7/13) Oct 20 2021 Old but still nice:
- Imperatorn (4/18) Oct 20 2021 This has been worked on several times. The community has trouble
- SealabJaster (6/8) Oct 20 2021 If there's one feature that shows the severe split between "BUT
- IGotD- (3/7) Oct 20 2021 Why are many using D using printf to begin with and not the D
- SealabJaster (10/12) Oct 20 2021 In the case of the string interpolation DIP, from what I remember
- harakim (25/33) Oct 30 2021 It's not a big one, but I find C#'s enumeration type to be almost
- glis-glis (28/31) Nov 01 2021 Python: Assign operator meaning different things in different
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (9/13) Nov 01 2021 You could replace "if" with "?", "??" or "¿" and use "⟳" for
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (7/11) Nov 06 2021 Worst line of reasoning for not having a feature is Go that
- Paulo Pinto (9/21) Nov 06 2021 Go has exceptions, although they don't call them as such
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (7/12) Nov 06 2021 They discourage using it for regular errors, and Go programmers
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (3/8) Nov 06 2021 I meant "very noisy"…
- Paulo Pinto (4/16) Nov 06 2021 Have a look here,
- Atila Neves (7/30) Nov 08 2021 I thought Rust error handling wasn't easy by default until they
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (5/11) Nov 08 2021 Looks like syntactical sugar to me, but I am no Rust expert. It
- bauss (43/49) Nov 09 2021 It propagates the error to the caller, so you don't lose context,
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (8/23) Nov 09 2021 As a library author you don't know what the application is
- bauss (4/28) Nov 09 2021 Yeah, it's definitely a quick hack. It was added to just remove
- Atila Neves (10/22) Nov 09 2021 Correct, but then again, anything other than machine code is
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (13/17) Nov 09 2021 No, syntactical sugar has nothing to do with the machine. It is
- Atila Neves (6/15) Nov 09 2021 If there are no exceptions and one is returning regular values,
- Timon Gehr (3/21) Nov 09 2021 Having a stack trace with line numbers is a big deal in case the
- Atila Neves (2/15) Nov 09 2021 Good point. I hadn't thought of that.
- Dukc (6/10) Nov 09 2021 Not a big deal IMO. Stack traces are not the main feature of
- arco (6/30) Nov 23 2021 Actually, Rust also has exceptions but like Go, it's ashamed to
- forkit (3/11) Nov 09 2021 I'd say being able to do the same thing, multiple ways.
- bauss (19/29) Nov 15 2021 I don't think I've answered yet, even tho I have responded to a
- H. S. Teoh (9/15) Nov 15 2021 +1. We've a lot of unfinished/incomplete things: shared,
- Q. Schroll (29/29) Nov 15 2021 * Worst features implemented in a non-toy language?
- arco (14/16) Nov 23 2021 * C: zero-terminated strings
- zjh (3/3) Nov 23 2021 On Wednesday, 24 November 2021 at 06:28:35 UTC, arco wrote:
- Igor (10/12) Dec 17 2021 I am a bit late to this party :) but after reading all 29 pages
- Tejas (2/14) Dec 17 2021 You must love the `to` template in `std.conv` then :P
- user1234 (4/21) Dec 17 2021 That's indeed a good way to have cast as postfix expressions
- Tejas (2/10) Dec 17 2021 Those are not good things?
- Rumbu (4/16) Dec 17 2021 In sql you can write ```cast(field as type)```.
- Quirin Schroll (16/23) Dec 18 2021 I feel the same about writing. But you have to consider how code
- Era Scarecrow (10/11) Dec 28 2021 I did some programming at a tech company in 2011, and was
- data pulverizer (12/20) Dec 29 2021 For me there are two main ones:
- data pulverizer (10/21) Jan 08 2022 One more thing, native string interpolation similar to f-strings
- sighoya (17/20) Apr 23 2022 - C Preprocessor
- rikki cattermole (3/6) Apr 23 2022 Signatures are OOP.
I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy language * Worst features (in your opinion) in D * Features you'd like to see in D Ideas? Examples? Thanks!
Oct 11 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy language * Worst features (in your opinion) in D * Features you'd like to see in D Ideas? Examples? Thanks!Objectively worst feature: mutability/referenceability by default. It takes away *so* much optimization potential and introduces so many opportunities for state changes. `var = value` should be opt-in. Just as importantly, `&var` should be opt-in. My D hobbyhorse, of course, is `__traits(compiles)` (see my last DConf talk) and the SFINAE-like mess that it enables but doesn't give us the tools to address. "Why did the template not instantiate?" Who knows~ That syntax error got suppressed five instantiations down. And there's obvious stuff like the half-baked `immutable` that works in about half the stdlib and a smaller fraction of libraries. D2 const was a mistake, cmv. (Nonreferenceability allows safe reassignment of immutable struct member fields, btw!) But I'm actually convinced that the worst thing is the lack of implicit construction for sumtypes. Because when you try to actually use sumtypes, you end up with stuff like `Nullable!MySumType(MySumType(MemberType("Hello World")))`. *All over the place.* And it adds no value! The whole point of `MySumType` is that it's "one of n types, including `MemberType`". Writing out the full type of a nested container type like that adds nothing of value. Sumtypes should be built-in, and they should implicitly construct from its member types. PS: But staring at this post interface, what I want the most *right now* - a "Discard all drafts" button. :)
Oct 11 2021
On Monday, 11 October 2021 at 16:12:59 UTC, FeepingCreature wrote:On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:- features that require a GC (associative array) - class (reference type)I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy language * Worst features (in your opinion) in D * Features you'd like to see in D Ideas? Examples? Thanks!Objectively worst feature: mutability/referenceability by default. It takes away *so* much optimization potential and introduces so many opportunities for state changes. `var = value` should be opt-in. Just as importantly, `&var` should be opt-in. My D hobbyhorse, of course, is `__traits(compiles)` (see my last DConf talk) and the SFINAE-like mess that it enables but doesn't give us the tools to address. "Why did the template not instantiate?" Who knows~ That syntax error got suppressed five instantiations down. And there's obvious stuff like the half-baked `immutable` that works in about half the stdlib and a smaller fraction of libraries. D2 const was a mistake, cmv. (Nonreferenceability allows safe reassignment of immutable struct member fields, btw!) But I'm actually convinced that the worst thing is the lack of implicit construction for sumtypes. Because when you try to actually use sumtypes, you end up with stuff like `Nullable!MySumType(MySumType(MemberType("Hello World")))`. *All over the place.* And it adds no value! The whole point of `MySumType` is that it's "one of n types, including `MemberType`". Writing out the full type of a nested container type like that adds nothing of value. Sumtypes should be built-in, and they should implicitly construct from its member types. PS: But staring at this post interface, what I want the most *right now* - a "Discard all drafts" button. :)Sumtypes should be built-in, and they should implicitly construct from its member types.I 100% agree with you Tagged union SHOULD be built in, telling people to import a package and use them like templates is the best way to discourage people from getting interested in the language When other "modern" languages don't have the problem since it's built in feature The positive side of std.sumtype is it showcase the capabilities of the language to implement new features on user land, BUT, for sumtype, nobody should have to go that road.. Same for Nullable/Optional in my opinion
Oct 11 2021
On 10/11/21 1:35 PM, russhy wrote:On Monday, 11 October 2021 at 16:12:59 UTC, FeepingCreature wrote:100%. I am really loving Ilya's `mir.algebraic` for my sumtype needs: http://mir-core.libmir.org/mir_algebraic.htmlOn Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote: Sumtypes should be built-in, and they should implicitly construct from its member types.I 100% agree with youSame for Nullable/Optional in my opinionLikewise mir algebraic has Nullable. But what it (and D overall as a builtin) is really missing is Result type (with Ok and Err tags) -- will be eagerly checking out Chaloupka's `expected` package soon. PS:https://run.dlang.io/is/XUtxwm :)But I'm actually convinced that the worst thing is the lack of implicit construction for sumtypes. Because when you try to actually use sumtypes, you end up with stuff like `Nullable!MySumType(MySumType(MemberType("Hello World")))`.
Oct 11 2021
On Monday, 11 October 2021 at 20:41:33 UTC, James Blachly wrote:Likewise mir algebraic has Nullable. But what it (and D overall as a builtin) is really missing is Result type (with Ok and Err tags) -- will be eagerly checking out Chaloupka's `expected` package soon.The real missing piece here IMO is DIP 1038 [1]. Once it is fully accepted and implemented, defining a Result type will be trivial. [1] https://github.com/dlang/DIPs/blob/b30b94d40bd76b513d31509f8e40f7c38d111929/DIPs/DIP1038.md
Oct 11 2021
On Monday, 11 October 2021 at 21:21:21 UTC, Paul Backus wrote:The real missing piece here IMO is DIP 1038 [1]. Once it is fully accepted and implemented, defining a Result type will be trivial.Could you explain how nodiscard would help with sum types? Presumably it won't help to implicitly convert a subtype into the wrapper sum type?
Oct 12 2021
On Tuesday, 12 October 2021 at 16:19:42 UTC, Nick Treleaven wrote:On Monday, 11 October 2021 at 21:21:21 UTC, Paul Backus wrote:Currently, the big advantage exceptions have over sum types is that you cannot accidentally ignore an exception. Either you catch it, or it crashes your program. With ` nodiscard`, we can eliminate this advantage, and put sum types and exceptions on an equal playing field.The real missing piece here IMO is DIP 1038 [1]. Once it is fully accepted and implemented, defining a Result type will be trivial.Could you explain how nodiscard would help with sum types? Presumably it won't help to implicitly convert a subtype into the wrapper sum type?
Oct 12 2021
On Tuesday, 12 October 2021 at 16:26:33 UTC, Paul Backus wrote:On Tuesday, 12 October 2021 at 16:19:42 UTC, Nick Treleaven wrote:One idea I had when bumping into this problem was something like a with statement but you give it some kind of composition operator, and then it joins the statements up implicitly a la do notation in HaskellOn Monday, 11 October 2021 at 21:21:21 UTC, Paul Backus wrote:Currently, the big advantage exceptions have over sum types is that you cannot accidentally ignore an exception. Either you catch it, or it crashes your program. With ` nodiscard`, we can eliminate this advantage, and put sum types and exceptions on an equal playing field.The real missing piece here IMO is DIP 1038 [1]. Once it is fully accepted and implemented, defining a Result type will be trivial.Could you explain how nodiscard would help with sum types? Presumably it won't help to implicitly convert a subtype into the wrapper sum type?
Oct 12 2021
On Tuesday, 12 October 2021 at 17:25:52 UTC, max haughton wrote:One idea I had when bumping into this problem was something like a with statement but you give it some kind of composition operator, and then it joins the statements up implicitly a la do notation in HaskellYou can technically do this already with `foreach` and `opApply`, although the result ends up looking kind of goofy: ```d foreach (b; a) foreach (c; b) foreach (d; c) e; ``` Desugars to: ```d a.opApply(b => b.opApply(c => c.opApply(d => e))); ``` ...which is almost the same thing as Haskell's `do` notation, if you replace `>>=` with `opApply` and `x <- y` with `foreach (x, y)`. This similarity is perhaps why Scala uses the `for` keyword for [its version of `do` notation][1]. [1]: https://docs.scala-lang.org/tour/for-comprehensions.html
Oct 12 2021
On Tuesday, 12 October 2021 at 17:48:04 UTC, Paul Backus wrote:On Tuesday, 12 October 2021 at 17:25:52 UTC, max haughton wrote:I hate this and I hate you! Nice trick though, wouldn't have thought to do that.[...]You can technically do this already with `foreach` and `opApply`, although the result ends up looking kind of goofy: ```d foreach (b; a) foreach (c; b) foreach (d; c) e; ``` Desugars to: ```d a.opApply(b => b.opApply(c => c.opApply(d => e))); ``` ...which is almost the same thing as Haskell's `do` notation, if you replace `>>=` with `opApply` and `x <- y` with `foreach (x, y)`. This similarity is perhaps why Scala uses the `for` keyword for [its version of `do` notation][1]. [1]: https://docs.scala-lang.org/tour/for-comprehensions.html
Oct 12 2021
On Monday, 11 October 2021 at 20:41:33 UTC, James Blachly wrote:Maybe you mean that one? https://run.dlang.io/is/zw1Ekqhttps://run.dlang.io/is/XUtxwm :)But I'm actually convinced that the worst thing is the lack of implicit construction for sumtypes. Because when you try to actually use sumtypes, you end up with stuff like `Nullable!MySumType(MySumType(MemberType("Hello World")))`.
Oct 12 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy language * Worst features (in your opinion) in DTwo things that immediately come to mind: - `unittest`. Clutters code reading, discourages extensive testing (because of said clutter), discourages testing inside a user's module, complicates runtime and compiler, framework cannot be developed separate from language runtime, ... - Implicit pointer/reference type of classes. While I think the forced reference type of classes is a good idea (when passing as function argument), I think it was a very bad idea to remove the `*` from notation. It makes code impossible to interpret without looking up a user-defined type. -Johan
Oct 11 2021
On Monday, 11 October 2021 at 17:06:38 UTC, Johan wrote:[snip] - `unittest`. Clutters code reading, discourages extensive testing (because of said clutter), discourages testing inside a user's module, complicates runtime and compiler, framework cannot be developed separate from language runtime, ...Nothing prevents you from pulling out the unittests (except maybe documented ones) and putting them in a separate file or folder structure. In fact, it should probably be more commonly done...
Oct 11 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy languageIndirect method notation in Perl: https://stackoverflow.com/questions/11695110/why-is-this-program-valid-i-was-trying-to-create-a-syntax-error/11695310#11695310 wantarray in Perl, where e.g. reverse() either reverses its list of arguments (a list of one argument $a in the following program--a noop) or it reverses the joined string of its list of arguments (the single string $a in the following the program) , depending on what the caller wants: ```perl sub foo { my ($a) = _; reverse $a; } my $changed = foo("changed"); ``` Aliasing subroutine parameters in Perl: `sub foo { my $arg = shift; }` is not the same thing as `sub foo { my ($arg) = _; }` and I can no longer remember why it's super critically important that you use the second form by default. Autovivification in Perl - usually desirable, and D has it to an extent in AAs. But then there's this: ```perl sub add { my ($table, $key) = _; $table->{$key} = 1; } within add() die "that silently did nothing" if exists $table{one}; print $table{two}; ``` Overriding 'built in' functions. Does `stat()` return the list of fields enumerated in 'perldoc -f stat' or does it return an object? Better check and see if the program you're maintaining used File::stat or not. $_ as the default argument in Perl. Literally once a month I write this code: ```perl open my $f, '<', 'open some file to read' or die "Tried to open 'some file to read' and failed : $!"; while (defined(my $line = <$f>)) { next unless /oh goddamnit this regex is applying to $_ and not $line/; do_stuff; } ``` Perl has a lot of "wow, that was a horrible idea! Let's fix it by adding a new syntax, encouraging people to use that instead, and then leaving this horrible idea in the language forever." misfeatures. The separate '<' in the previous example is some new syntax for opening files. The old syntax lets you write tools that will truncate /etc/passwd or spawn arbitrary subprocesses if given a malicious filename. At least those dangerous tools never stopped working due to the language updating and breaking them, right?* Worst features (in your opinion) in D * Features you'd like to see in DMaybe it's not surprising by this point of this post, but I'm pretty happy with D. I would like some easy way to make sure I haven't accidentally used 80-bit floats in a D program.
Oct 11 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy language- Some C standard library functions. `gets` is the worst one, but `atof` and `atoi` are pretty useless too. - The feature of some early C compilers that only the first 7 characters of an identifier are significant. - C casting and C++ template syntaxes.* Worst features (in your opinion) in D- Integer promotion without at least letting to assign the result back to original width without a cast - Autodecoding. It would not be as bad if string literals were of some sort of wrapper type over the data, but autodecoding a plain array type just sucks.* Features you'd like to see in D- The Phobos versioning scheme that is already in the works. - Some way to enable preview/revert switches per module as opposed to per compilation. And same for autodecoding if possible. - More compatibility between compiler / standard library versions in general.Ideas? Examples?- Perhaps we should have a common agreement on what compiler versions should be used when long-term support for code is the goal. For example, we could agree on 2.084, 2.090, 2.096, 2.102 etc.
Oct 11 2021
Worst features implemented in a non-toy languageIt's been a while i haven't used anything other than D, so i don't have much to say, i'll need to research to remember first On top of my head, i think the worst feature in any language is C/C++ header system Sometimes, in rare occasions it can be handy, but most of the time it is a pain in the buttWorst features (in your opinion) in D- class (reference type) - GC as a feature - !() for templates (not really a feature, more like a syntax issue, way to similar to functions) - being abot to use ! with optional parentheses, countless times i got bit by: ``Array!int* array;`` but i wanted ``Array!(int)* array;`` instead..Features you'd like to see in D- tagged union (built in, not as std/lib) - interface / signature for structs (built in, not as std/lib) - alternatively, reintroduce the * for classes - enum literals (being able to omit the enum name) ex: ```d enum MyEnum { A, B, C} MyEnum e = :A; my_function(:A); switch (e) { case :A: break; } // could be :, ., $, ! but that is not the point '''
Oct 11 2021
On Monday, 11 October 2021 at 18:27:29 UTC, russhy wrote:This GC phobia is hurting the d language.Worst features implemented in a non-toy language- GC as a feature- class (reference type)WHY!? -Alex
Oct 11 2021
On Monday, 11 October 2021 at 18:27:29 UTC, russhy wrote:This GC phobia is hurting the d language.Worst features implemented in a non-toy language- GC as a feature- class (reference type)WHY!? -Alex Fix formating
Oct 11 2021
On Monday, 11 October 2021 at 20:48:47 UTC, 12345swordy wrote:On Monday, 11 October 2021 at 18:27:29 UTC, russhy wrote:it is not GC phobia, i use the GC for some projects and i'm ok with it it just is when you don't need it, you need to be careful with nogc, and there is no way to globally enforce a nogc behavior these issues would be solved if GC was introduced as a library, or as a toggleable feature without having to resort to -betterC GC, even thought i don't like the comparison myself, D still is a system language Countless hours wasted working aroung GC limitations with Unity If they had went with D, they wouldn't have to be this careful with their language! an area D should have won market share (engine code + scripting code at the same time!)This GC phobia is hurting the d language.Worst features implemented in a non-toy language- GC as a feature- class (reference type)WHY!? -Alex
Oct 11 2021
On Monday, 11 October 2021 at 21:38:17 UTC, russhy wrote:it just is when you don't need it, you need to be careful with nogc, and there is no way to globally enforce a nogc behaviortry a ` nogc` main() function. Yes this doesn't handle module global and thread constructors, but its global enough.
Oct 11 2021
On Monday, 11 October 2021 at 20:48:47 UTC, 12345swordy wrote:On Monday, 11 October 2021 at 18:27:29 UTC, russhy wrote:because, as other said, it is hard to differentiate from struct (values), you always have to check the symbol signature, wich is just annoying ``void pass(MyType* type) {}`` ``void pass(MyType type) {}`` you can't know what is a type or the pointer of a reference type, having to guess / context switch to go check symbol signature is a painThis GC phobia is hurting the d language.Worst features implemented in a non-toy language- GC as a feature- class (reference type)WHY!? -Alex
Oct 12 2021
On Wednesday, 13 October 2021 at 01:56:06 UTC, russhy wrote:On Monday, 11 October 2021 at 20:48:47 UTC, 12345swordy wrote:It is not an issue if you have a functional IDE that does the heavy lifting for you. This isn't a language issue here. You are doing something very wrong if you find yourself typingOn Monday, 11 October 2021 at 18:27:29 UTC, russhy wrote:because, as other said, it is hard to differentiate from struct (values), you always have to check the symbol signature, wich is just annoyingThis GC phobia is hurting the d language.Worst features implemented in a non-toy language- GC as a feature- class (reference type)WHY!? -Alexvoid pass(Mytype* type) {}where Mytype is a class. This is not c++ here. -Alex
Oct 13 2021
On Monday, 11 October 2021 at 18:27:29 UTC, russhy wrote:The enum thing works now: ``` enum MyEnum { A, B, C} with(MyEnum) { auto e = A; myFunction(A); switch(e) { case A: break; default: } } ```[...]It's been a while i haven't used anything other than D, so i don't have much to say, i'll need to research to remember first [...]
Oct 14 2021
On Monday, 11 October 2021 at 18:27:29 UTC, russhy wrote: [...]This unscoped enums is one of the worst features in C/C++, imho. I loved when I switch to languages that the enum got its scopre but D you got both, you can also do: ```D enum A = 0; enum B = 1; // ... ``` if you dislike to set their initial values manually, I think you can write a template function to create enum valuesFeatures you'd like to see in D- tagged union (built in, not as std/lib) - interface / signature for structs (built in, not as std/lib) - alternatively, reintroduce the * for classes - enum literals (being able to omit the enum name) ex: ```d enum MyEnum { A, B, C} MyEnum e = :A; my_function(:A); switch (e) { case :A: break; } // could be :, ., $, ! but that is not the point '''
Nov 14 2021
On Sunday, 14 November 2021 at 18:41:10 UTC, Dr Machine Code wrote:On Monday, 11 October 2021 at 18:27:29 UTC, russhy wrote: [...]It's not unscoped, it type checked, it just removes the need to be verbose and repetitive ```D MyAbility ability; switch (ability) { case MyAbility.SOMETHING_1: break; case MyAbility.SOMETHING_2: break; case MyAbility.SOMETHING_3: break; case MyAbility.SOMETHING_4: break; case MyAbility.SOMETHING_5: break; } ``` What this repetition solves? ```D void use_ability(MyAbility ability){} use_ability(MyAbility.SOMETHING_1); ``` Imagine if you had to prefix the type of everything ```D void use_my_int(int a) {} use_my_int(int.4545846846); ``` Compiler can be smarter Languages that allow removing the prefix for enums are popular it helps a lot with readabilityThis unscoped enums is one of the worst features in C/C++, imho. I loved when I switch to languages that the enum got its scopre but D you got both, you can also do: ```D enum A = 0; enum B = 1; // ... ``` if you dislike to set their initial values manually, I think you can write a template function to create enum valuesFeatures you'd like to see in D- tagged union (built in, not as std/lib) - interface / signature for structs (built in, not as std/lib) - alternatively, reintroduce the * for classes - enum literals (being able to omit the enum name) ex: ```d enum MyEnum { A, B, C} MyEnum e = :A; my_function(:A); switch (e) { case :A: break; } // could be :, ., $, ! but that is not the point '''
Nov 15 2021
On Mon, Nov 15, 2021 at 05:25:35PM +0000, russhy via Digitalmars-d wrote: [...]```D MyAbility ability; switch (ability) { case MyAbility.SOMETHING_1: break; case MyAbility.SOMETHING_2: break; case MyAbility.SOMETHING_3: break; case MyAbility.SOMETHING_4: break; case MyAbility.SOMETHING_5: break; } ``` What this repetition solves?[...] Why can't you just write: MyAbility ability; switch (ability) with(MyAbility) { case SOMETHING_1: break; case SOMETHING_2: break; case SOMETHING_3: break; case SOMETHING_4: break; case SOMETHING_5: break; } ? The `with` keyword was designed specifically for this purpose. T -- They pretend to pay us, and we pretend to work. -- Russian saying
Nov 15 2021
On Monday, 15 November 2021 at 17:48:35 UTC, H. S. Teoh wrote: [...]Why can't you just write: MyAbility ability; switch (ability) with(MyAbility) { case SOMETHING_1: break; case SOMETHING_2: break; case SOMETHING_3: break; case SOMETHING_4: break; case SOMETHING_5: break; } ? The `with` keyword was designed specifically for this purpose.Nice. What about import std.stdio; enum SAB { a = 1, } void main () { with (SAB) if (a == 1) writeln ("true"); with (SAB) void foo () { writeln (a); } // no complaints! foo(); // Error: undefined identifier `foo` }
Nov 15 2021
On Mon, Nov 15, 2021 at 09:10:51PM +0000, kdevel via Digitalmars-d wrote:On Monday, 15 November 2021 at 17:48:35 UTC, H. S. Teoh wrote: [...][...] That's because `with` introduces a scope. So you should have written instead: void foo () { with (SAB) writeln (a); } Or, for that matter: void main () { with (SAB) { if (a == 1) writeln ("true"); void foo () { writeln (a); } foo(); // Now this works } } T -- Being able to learn is a great learning; being able to unlearn is a greater learning.Why can't you just write: MyAbility ability; switch (ability) with(MyAbility) { case SOMETHING_1: break; case SOMETHING_2: break; case SOMETHING_3: break; case SOMETHING_4: break; case SOMETHING_5: break; } ? The `with` keyword was designed specifically for this purpose.Nice. What about import std.stdio; enum SAB { a = 1, } void main () { with (SAB) if (a == 1) writeln ("true"); with (SAB) void foo () { writeln (a); } // no complaints! foo(); // Error: undefined identifier `foo` }
Nov 15 2021
On Monday, 15 November 2021 at 21:23:56 UTC, H. S. Teoh wrote:On Mon, Nov 15, 2021 at 09:10:51PM +0000, kdevel via Digitalmars-d wrote:that's not what i am asking - now you leak SAB scope everywhere - now you have to indent everything - there is no differenciation between SAB.a and a variable called a Why make things complicated and bloated when it can be simple? Also why making me want to want something that is not what i asked? it's quite the opposite!On Monday, 15 November 2021 at 17:48:35 UTC, H. S. Teoh wrote: [...][...] That's because `with` introduces a scope. So you should have written instead: void foo () { with (SAB) writeln (a); } Or, for that matter: void main () { with (SAB) { if (a == 1) writeln ("true"); void foo () { writeln (a); } foo(); // Now this works } } TWhy can't you just write: MyAbility ability; switch (ability) with(MyAbility) { case SOMETHING_1: break; case SOMETHING_2: break; case SOMETHING_3: break; case SOMETHING_4: break; case SOMETHING_5: break; } ? The `with` keyword was designed specifically for this purpose.Nice. What about import std.stdio; enum SAB { a = 1, } void main () { with (SAB) if (a == 1) writeln ("true"); with (SAB) void foo () { writeln (a); } // no complaints! foo(); // Error: undefined identifier `foo` }
Nov 15 2021
On Monday, 15 November 2021 at 17:48:35 UTC, H. S. Teoh wrote:On Mon, Nov 15, 2021 at 05:25:35PM +0000, russhy via Digitalmars-d wrote: [...]I don't understand your point, that is exactly what i said, a nice use of with There is a problem here, you don't listen to what i say, therefore you don't understand the problem what about ALL OTHER problems? ;) MyAbility ability switch ability with MyAbility use Ability maybe we should have a with instead of with, that'll solve the problem? /s```D MyAbility ability; switch (ability) { case MyAbility.SOMETHING_1: break; case MyAbility.SOMETHING_2: break; case MyAbility.SOMETHING_3: break; case MyAbility.SOMETHING_4: break; case MyAbility.SOMETHING_5: break; } ``` What this repetition solves?[...] Why can't you just write: MyAbility ability; switch (ability) with(MyAbility) { case SOMETHING_1: break; case SOMETHING_2: break; case SOMETHING_3: break; case SOMETHING_4: break; case SOMETHING_5: break; } ? The `with` keyword was designed specifically for this purpose. T
Nov 17 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy languageC's pointer notation is too stupid for words. (I understand how it works. I've been using it for decades. Please no explanations.) Writing functions like this is horrible: ``` int timesTwo(int *x) { return 2 * *x; } ``` When you learn C, you ask what the `*x` is. It's an int. That makes sense. That's why it's `int *x`. Okay, let's call that function: ``` int main() { printf("%d\n", timesTwo(4)); return 0; } ``` `expected ‘int *’ but argument is of type ‘int’` Okay, let's try this: ``` int main() { int z = 4; printf("%d\n", timesTwo(&z)); return 0; } ``` `8` So `*x` is an int, but you have to pass `&z`, which is not an int, as the argument. The only way this can't be confusing to someone learning it for the first time is if they're memorizing syntax.
Oct 11 2021
On 11.10.2021 22:15, bachmeier wrote:On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:I would say that `x` is a pointer to int and `*x` is a dereferenced pointer to int. 4 is an int value and it can not be treated as a dereferenced pointer to int. So you need to create an int value, take the pointer to it and then pass it to the function.I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy languageC's pointer notation is too stupid for words. (I understand how it works. I've been using it for decades. Please no explanations.) Writing functions like this is horrible: ``` int timesTwo(int *x) { return 2 * *x; } ``` When you learn C, you ask what the `*x` is. It's an int. That makes sense. That's why it's `int *x`. Okay, let's call that function: ``` int main() { printf("%d\n", timesTwo(4)); return 0; } ``` `expected ‘int *’ but argument is of type ‘int’` Okay, let's try this: ``` int main() { int z = 4; printf("%d\n", timesTwo(&z)); return 0; } ``` `8` So `*x` is an int, but you have to pass `&z`, which is not an int, as the argument. The only way this can't be confusing to someone learning it for the first time is if they're memorizing syntax.
Oct 11 2021
On Monday, 11 October 2021 at 19:15:51 UTC, bachmeier wrote:On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:Yes, it is cultural debt, that came from a desire to express types such as a 'pointer to a pointer to an int' with a notation for keyboards with a limited set of easily accessible symbols. The cost is quite high, but people are used to. It us equally puzzeling why prople want "&&" instead of "and" or "||" instead of "or". There is no rational explanation, I think people like to feel that they are using something advanced and that a syntax that that is associated with advanced usage makes them feel more skilled? Kinda like fashion...I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy languageC's pointer notation is too stupid for words. (I understand how it works. I've been using it for decades. Please no explanations.)
Oct 24 2021
On Sunday, 24 October 2021 at 08:42:54 UTC, Ola Fosheim Grøstad wrote:Yes, it is cultural debt, that came from a desire to express types such as a 'pointer to a pointer to an int' with a notation for keyboards with a limited set of easily accessible symbols. The cost is quite high, but people are used to. It us equally puzzeling why prople want "&&" instead of "and" or "||" instead of "or". There is no rational explanation, I think people like to feel that they are using something advanced and that a syntax that that is associated with advanced usage makes them feel more skilled? Kinda like fashion...I imagine && and || stem from & and |. You could probably have something like "and" and "band", "or" and "bor" but to me that doesn't seem as comfortable.
Oct 24 2021
On Sunday, 24 October 2021 at 09:04:16 UTC, SealabJaster wrote:I imagine && and || stem from & and |. You could probably have something like "and" and "band", "or" and "bor" but to me that doesn't seem as comfortable.Adding onto that, a "pineapple on pizza" sort of thing is that some people like to write things like `a&b|c` instead of `a & b | c`, the former I don't think is possible with keywords, but is with operators.
Oct 24 2021
On Sunday, 24 October 2021 at 09:04:16 UTC, SealabJaster wrote:I imagine && and || stem from & and |. You could probably have something like "and" and "band", "or" and "bor" but to me that doesn't seem as comfortable.That was why C used it, but it leads to uneccessary problems with typos, too many meanings for the symbols and overall less legible code. In terms of modelling, "&&" is used for reasoning about control flow and "&" is used for low level trickery. There is no usabilty advantage in mixing those levels visually. Also, the semantics are different as "&&" shortcuts, a point newbies tend to overlook...
Oct 24 2021
On Sunday, 24 October 2021 at 08:42:54 UTC, Ola Fosheim Grøstad wrote:instead of "or". There is no rational explanation, I think people like to feel that they are using something advanced and that a syntax that that is associated with advanced usage makes them feel more skilled? Kinda like fashion...Sorry for all the typos (ipad)... Anyway cultural impact on syntax is intersting. In the 70s/80s screens were quite limited so it made sense to write more terse code. Quite prevalent for systems work, either low level or scripting. Python did a good job of cleaning up syntax in professional programming, which is a factor in its popularity. I think elitism has a lot to do with fashions in language syntax. Like, even when BASIC would be the best tool for a job, I think many would rather not use it as it would imply being a less sophisticated programmer...
Oct 24 2021
On Sunday, 24 October 2021 at 09:08:56 UTC, Ola Fosheim Grøstad wrote:I think elitism has a lot to do with fashions in language syntax. Like, even when BASIC would be the best tool for a job, I think many would rather not use it as it would imply being a less sophisticated programmer...This has sent me through a slightly on topic yet mostly off topic train of thought. enough and mainstream enough that there are programmers who only know those singular languages to a decent degree. Meanwhile there are the more comparatively fringe languages like D, Nim, I guess Rust, and so on, that likely consist of so-called polyglot programmers - those that are proficient in multiple languages. It's hard to express my thoughts, but I wonder what affect this has on these fringe languages in general, compared to the more mainstream ones.
Oct 24 2021
On Sunday, 24 October 2021 at 13:59:42 UTC, SealabJaster wrote:large enough and mainstream enough that there are programmers who only know those singular languages to a decent degree.Yes, and all those really grow out of C++ (except JavaScript that is closer to Self IIRC) both in terms of syntax and semantics. So that is in essence captures what "programming" is to most programmers, I would think.Meanwhile there are the more comparatively fringe languages like D, Nim, I guess Rust, and so on, that likely consist of so-called polyglot programmers - those that are proficient in multiple languages. It's hard to express my thoughts, but I wonder what affect this has on these fringe languages in general, compared to the more mainstream ones.That is an interesting perspective. I think D and Nim might have roughly two types of programmers: those that do programming on multiple projects and are polyglot, and those that use the language as a tool in some other process (including hobbyists) and who focus on one language. Then you have those that would want a niche language that is really good at one task, like a very efficient tool for something specific. On the other hand you have those that want one language that covers everything (but then you have to sacrifice being really good at something specific). And that is where niche languages are struggling, for a polyglot programmer it is much easier to defend adopting yet-another-language if it is a very narrow specialty tool (e.g. the best option for DSP, 3D or something like that). Yet polyglot programmers might have much stronger opinions on what features the language lacks also (in comparison to other languages). As a result the process might be a bit self-defeating. The polyglots might push the language to be less attractive for polyglot programmers looking for the best narrow tool for a task. And the non-polyglot programmers don't really have a lot of reason to push back on adding more features that makes the language cover more ground for them (as they haven't seen the consequences in other languages). I think Rust is a bit different. It plays up to "erudite programmers" by giving a sense of being "theory-based" and "academic", and the syntax is reminiscent of more academic languages. I perceive the "marketing surface" of Rust and Haskell to have some common traits, but Rust is easier to deal with for most programmers in a commercial setting. (I am not saying that Rust is academic in nature, only that it is positioned as being more academic than other languages.)
Oct 24 2021
On Sunday, 24 October 2021 at 08:42:54 UTC, Ola Fosheim Grøstad wrote:It us equally puzzeling why prople want "&&" instead of "and" or "||" instead of "or". There is no rational explanation, I think people like to feel that they are using something advanced and that a syntax that that is associated with advanced usage makes them feel more skilled? Kinda like fashion...Because boolean algebra was already a thing and it was symbolic in nature. So making it wordy would probably seem a bit odd, maybe childish to some people. It'd be like writing arithmetic expressions like this... 1 plus 1 equals 2 If you can understand why people wouldn't want to write arithmetic expressions like that, surely you can understand why some people wouldn't want wordy boolean expressions?
Oct 24 2021
On Sunday, 24 October 2021 at 10:21:22 UTC, claptrap wrote:On Sunday, 24 October 2021 at 08:42:54 UTC, Ola Fosheim Grøstad wrote:This might be a good reason actually. Coming from logic I at first thought that of course "or" would be ∨ and "and" would be ∧ etc, but then, where are those signs on my keyboard 😭 (I actually have an apl keyboard but that's another thing) So made sense in a way to reuse & and | since they are pretty close as alternative representations, ie ∥ VS || for example.It us equally puzzeling why prople want "&&" instead of "and" or "||" instead of "or". There is no rational explanation, I think people like to feel that they are using something advanced and that a syntax that that is associated with advanced usage makes them feel more skilled? Kinda like fashion...Because boolean algebra was already a thing and it was symbolic in nature. So making it wordy would probably seem a bit odd, maybe childish to some people. It'd be like writing arithmetic expressions like this... 1 plus 1 equals 2 If you can understand why people wouldn't want to write arithmetic expressions like that, surely you can understand why some people wouldn't want wordy boolean expressions?
Oct 24 2021
On Sunday, 24 October 2021 at 10:21:22 UTC, claptrap wrote:Because boolean algebra was already a thing and it was symbolic in nature. So making it wordy would probably seem a bit odd, maybe childish to some people. It'd be like writing arithmetic expressions like this... 1 plus 1 equals 2 If you can understand why people wouldn't want to write arithmetic expressions like that, surely you can understand why some people wouldn't want wordy boolean expressions?I think "not being childish" is a sign of fashion-elitism if it makes code less legible. Many languages that predated C++'s uptake did use more intuitive syntax and had a less noisy appearance. C++ does provide "and" and "or" as keywords though, but people probably don't want to appear as being "not proficient" so I don't actually see it in published code. I have found that using them makes my own code slightly faster to read, so I have recently started to use them. Makes sense to me that "if", "while", "or", "and" ties to flow control, and "&", "|", "+", "/" ties to calculating expressions. I find it slightly easier to read such code when I skim over it (without digging into the specifics). The line noise does of course make programs look more impressive to non-coders: "Whoa, that looks complex, you must be very clever".
Oct 24 2021
On Sunday, 24 October 2021 at 14:47:48 UTC, Ola Fosheim Grøstad wrote:On Sunday, 24 October 2021 at 10:21:22 UTC, claptrap wrote:I dont think it does make code less legible. I mean the whole point of using symbolic expressions is that they make it easier to express things. It's not fashion, and it's not elitism. If you're writing a ton of boolean expressions over and over using a symbol instead of a word to express a concept will make it easier. It may increase the learning curve for people coming to it fresh, but that doesn't mean that is reason for doing it.Because boolean algebra was already a thing and it was symbolic in nature. So making it wordy would probably seem a bit odd, maybe childish to some people. It'd be like writing arithmetic expressions like this... 1 plus 1 equals 2 If you can understand why people wouldn't want to write arithmetic expressions like that, surely you can understand why some people wouldn't want wordy boolean expressions?I think "not being childish" is a sign of fashion-elitism if it makes code less legible. Many languages that predated C++'s uptake did use more intuitive syntax and had a less noisy appearance.I have found that using them makes my own code slightly faster to read, so I have recently started to use them.So you find them slightly faster to read, and anyone who doesn't use them must be showing off?Makes sense to me that "if", "while", "or", "and" ties to flow control, and "&", "|", "+", "/" ties to calculating expressions.But they are not part of control flow, they are part of expressions.The line noise does of course make programs look more impressive to non-coders: "Whoa, that looks complex, you must be very clever".Yeah cause programmers go around showing their code to non coders to try and impress them. In fact it's my number one way to chat up women, show em some over complicated code till they fall swooning into my arms. What are you smoking mate?
Oct 24 2021
On Sunday, 24 October 2021 at 20:46:01 UTC, claptrap wrote:If you're writing a ton of boolean expressions over and over using a symbol instead of a word to express a concept will make it easier. It may increase the learning curve for people coming to it fresh, but that doesn't mean that is reason for doing it.The only reason for doing it is that C used it. If there is any difference in typing speed then it would favour letters over symbols.So you find them slightly faster to read, and anyone who doesn't use them must be showing off?No, I made rational argument for why there are no advantages to using "&&" and "||" over "and" and "or". It is entirely cultural.But they are not part of control flow, they are part of expressions.Yes, 99% of them in conditional expressions as selectors in control flow. Why being pedantic?Yeah cause programmers go around showing their code to non coders to try and impress them.No, you don't get the main point. Culture and identity affects preferences and evolution of language, that is a human trait. It is pretty pervasive and well established. There is no reason to assume that programmers are different from other human beings. There is no reason to be offended by this. It should be obvious, I think?
Oct 24 2021
On Sunday, 24 October 2021 at 21:26:25 UTC, Ola Fosheim Grøstad wrote:On Sunday, 24 October 2021 at 20:46:01 UTC, claptrap wrote:I'm saying it probably initially came from boolean algebra in maths. Or maybe even electronics, there was a history of boolean logic being expressed with symbols before programming languages even existed. So that's the root. So then you have bitwise operations with symbols because math. Then you need to differentiate between bitwise and boolean logic so && and || makes more sense than using keywords. It's consistent with the already existing bitwise ops.If you're writing a ton of boolean expressions over and over using a symbol instead of a word to express a concept will make it easier. It may increase the learning curve for people coming to it fresh, but that doesn't mean that is reason for doing it.The only reason for doing it is that C used it. If there is any difference in typing speed then it would favour letters over symbols.See above.So you find them slightly faster to read, and anyone who doesn't use them must be showing off?No, I made rational argument for why there are no advantages to using "&&" and "||" over "and" and "or". It is entirely cultural.if (num % 3) if (ptr == null) Are arithmetic and pointers now control flow? And anything you can put in the brackets after an if or while now becomes control flow? It's not pedantic to call that argument nonsense.But they are not part of control flow, they are part of expressions.Yes, 99% of them in conditional expressions as selectors in control flow. Why being pedantic?Programming languages and natural languages have vastly different evolution. People are not subtly changing programming language syntax all the time as a means of self expression. It's designed once and then (for obvious reasons) pretty much stuck that way for ever at least within a given language. And then there's a kind of inertia across languages I think because familiar syntax is seen as a benefit for a new language. I mean how long have && and || been in use? 50 years? That's not evolution and it's not fashion. When someone designs a new programming language I dont think they are asking themselves how can I design the syntax to make themselves look cool, they are either choosing syntax because it is what they are used to, or for some other technical reason. That's the issue I have with what you're saying, I dont think language designers are making syntax choices in order to look cool. In order to suggest that i think you have to have a fundamental misunderstanding of what motivates people to design their own programming language.Yeah cause programmers go around showing their code to non coders to try and impress them.No, you don't get the main point. Culture and identity affects preferences and evolution of language, that is a human trait. It is pretty pervasive and well established. There is no reason to assume that programmers are different from other human beings.
Oct 25 2021
On Monday, 25 October 2021 at 10:55:43 UTC, claptrap wrote:I'm saying it probably initially came from boolean algebra in maths. Or maybe even electronics, there was a history of boolean logic being expressed with symbols before programming languages even existed.Math, sure. Electronics, doubt; considering Algorithm for the Analytical Engine was designed in 1883.
Oct 25 2021
On Monday, 25 October 2021 at 11:38:16 UTC, bauss wrote:On Monday, 25 October 2021 at 10:55:43 UTC, claptrap wrote:What I'm getting at is that whoever designed B, C or whatever came before that probably had a math and or electronics background, so that's why they chose symbolic expressions for bitwise / boolean ops. I doubt Babages engine had any influence on modern programming syntax.I'm saying it probably initially came from boolean algebra in maths. Or maybe even electronics, there was a history of boolean logic being expressed with symbols before programming languages even existed.Math, sure. Electronics, doubt; considering Algorithm for the Analytical Engine was designed in 1883.
Oct 25 2021
On Monday, 25 October 2021 at 10:55:43 UTC, claptrap wrote:I'm saying it probably initially came from boolean algebra in maths. Or maybe even electronics, there was a history of boolean logic being expressed with symbols before programming languages even existed.Yes, and that has been evolving as well. Often times they had to make do with what the typograph had available when setting their papers. (Like turning an "A" or "E" upside down.)Programming languages and natural languages have vastly different evolution. People are not subtly changing programming language syntax all the time as a means of self expression.I don't think this is true. Programming language syntax evolve at a higher pace than natural language, and programmers bend the syntax whenever they get a chance to suit their own taste (self expression).When someone designs a new programming language I dont think they are asking themselves how can I design the syntax to make themselves look cool, they are either choosing syntax because it is what they are used to, or for some other technical reason.It is a mix, it is also a strategic choice, making assumptions about what would make it look appealing to existing programmers.That's the issue I have with what you're saying, I dont think language designers are making syntax choices in order to look cool.The designers don't decide which ones of the languages that catch on. What programmers adopt determines the direction of language evolution. There are thousands of programming languages. That is why culture and identity is a force in this evolution process.
Oct 25 2021
On Monday, 25 October 2021 at 12:22:51 UTC, Ola Fosheim Grøstad wrote:On Monday, 25 October 2021 at 10:55:43 UTC, claptrap wrote:Well probably they had their own notation on actual pen and paper. But the fact that when coming to type setting they preferred an upside down 'E' over writing a word makes it look like there is something appealing in writing the expressions symbolically that you just don't seem to grasp.I'm saying it probably initially came from boolean algebra in maths. Or maybe even electronics, there was a history of boolean logic being expressed with symbols before programming languages even existed.Yes, and that has been evolving as well. Often times they had to make do with what the typograph had available when setting their papers. (Like turning an "A" or "E" upside down.)They are adding about 1000 new words to the English dictionary each year and many of those are new meanings for existing words. And that's just the stuff that makes it in. Programming languages are not even in the same race. I am constantly having to ask my kids (18 & 22) and their friends what some word or phrase means, (and sometimes I wish I hadn't asked.)Programming languages and natural languages have vastly different evolution. People are not subtly changing programming language syntax all the time as a means of self expression.I don't think this is true. Programming language syntax evolve at a higher pace than natural language, and programmers bend the syntax whenever they get a chance to suit their own taste (self expression).Do programmers really think to themselves "I'm not using Pascal because i'll look like a douchebag writing my boolean expressions that way"? I dont see it. I can see people being swayed by language syntax, (I personally dont like overly wordy languages like pascal), but I dont see people making that choice based on what they assume other people will think of them. I mean the only other people who will likely see your code will be people using the same language, so like who cares?That's the issue I have with what you're saying, I dont think language designers are making syntax choices in order to look cool.The designers don't decide which ones of the languages that catch on. What programmers adopt determines the direction of language evolution. There are thousands of programming languages. That is why culture and identity is a force in this evolution process.
Oct 25 2021
On Monday, 25 October 2021 at 22:05:06 UTC, ClapTrap wrote:Well probably they had their own notation on actual pen and paper. But the fact that when coming to type setting they preferred an upside down 'E' over writing a word makes it look like there is something appealing in writing the expressions symbolically that you just don't seem to grasp.Why personal attacks? If you read old math writings you will see that they did actually write out math with plain words. Compact short forms came later and mathematicians still don't agree on one common syntax. So there is indeed a personal aspect to writing mathematics. This become obvious if you read proofs, there are many different styles. Clearly strong personal preferences at display.They are adding about 1000 new words to the English dictionary each year and many of those are new meanings for existing words.That's more like a library. You don't change the grammar when you add new words.Programming languages are not even in the same race.Exactly, they are extended at a far higher pace. 347000 Java repos in the past 2 months. How many new "words" do you think that is?I am constantly having to ask my kids (18 & 22) and their friends what some word or phrase means, (and sometimes I wish I hadn't asked.)Right, and it is a challenge to stay up to date with the constant stream of new versions of programming frameworks.Do programmers really think to themselves "I'm not using Pascal because i'll look like a douchebag writing my boolean expressions that way"?Oh, I think many would shy away from Pascal, Fortran, Ada and other languages that are "old" or "grey beard" without knowing anything about the languages at all!! There is a clear Fashionista element to both programming languages and programming frameworks. Which ties into identity and "being current". Just like there are young wanna-become-programmers that start out with C++ (which is a particularly bad choice) because it is used in AAA-games and they identify themselves as soon to become kickass game-programmers (because that is where their heros/passion are).
Oct 25 2021
On Monday, 25 October 2021 at 22:24:40 UTC, Ola Fosheim Grøstad wrote:On Monday, 25 October 2021 at 22:05:06 UTC, ClapTrap wrote:So, to bring this discussion to an end: I am not saying that people should not use symbols and formalisms. I am saying that using "&&" over "and" is not giving a usability advantage, and I believe that can be both argued and in theory measured (although difficult). If you read mathematical proofs you'll see that proofs that only use formalisms can be very difficult to follow for a human being (although easy to verify for a computer). So written proofs tend to use words where emphasis and understanding is important. When language designers talk about their languages they often emphasis aesthetic dimensions. So language design is just as much art as it is engineering. Which ties to culture, identity and in essence philosophy. Mathematicians talk about beauty in relation to proofs, programmers talk about beauty in relation to coding. Again, influenced by culture and identity. In essence this is a good thing. If language design was all about engineering then we wouldn't have so many options to choose from! :-DWell probably they had their own notation on actual pen and paper. But the fact that when coming to type setting they preferred an upside down 'E' over writing a word makes it look like there is something appealing in writing the expressions symbolically that you just don't seem to grasp.Why personal attacks? If you read old math writings you will see that they did actually write out math with plain words. Compact short forms came later and mathematicians still don't agree on one common syntax. So there is indeed a personal aspect to writing mathematics. This become obvious if you read proofs, there are many different styles. Clearly strong personal preferences at display.
Oct 25 2021
On Monday, 25 October 2021 at 22:24:40 UTC, Ola Fosheim Grøstad wrote:Why personal attacks? If you read old math writings you will see that they did actually write out math with plain words.I dont think it is a personal attack to say you dont seem to grasp something.If everything written in Java is extending the language, then everything written in English is extending that too. So which is growing faster now?Programming languages are not even in the same race.Exactly, they are extended at a far higher pace. 347000 Java repos in the past 2 months. How many new "words" do you think that is?Or keep up with every book / article / blog post written?I am constantly having to ask my kids (18 & 22) and their friends what some word or phrase means, (and sometimes I wish I hadn't asked.)Right, and it is a challenge to stay up to date with the constant stream of new versions of programming frameworks.I worked with Delphi for about 10 years, i know plenty about it, it was very productive but I wasn't keen on the overly wordy syntax. Fast compile times, strings that just worked, and an amazing IDE were probably the highlights.Do programmers really think to themselves "I'm not using Pascal because i'll look like a douchebag writing my boolean expressions that way"?Oh, I think many would shy away from Pascal, Fortran, Ada and other languages that are "old" or "grey beard" without knowing anything about the languages at all!! There is a clear Fashionista element to both programming languages and programming frameworks. Which ties into identity and "being current".Just like there are young wanna-become-programmers that start out with C++ (which is a particularly bad choice) because it is used in AAA-games and they identify themselves as soon to become kickass game-programmers (because that is where their heros/passion are).You seem to have a bit of a thing about people who are trying to be cool and fashionable.
Oct 25 2021
On Tuesday, 26 October 2021 at 01:06:31 UTC, ClapTrap wrote:If everything written in Java is extending the language, then everything written in English is extending that too. So which is growing faster now?Fair enough, let us say only libraries and frameworks extend the language. :-)I worked with Delphi for about 10 years, i know plenty about it, it was very productive but I wasn't keen on the overly wordy syntax. Fast compile times, strings that just worked, and an amazing IDE were probably the highlights.Nobody said that everything should be keywords... Have you tried to make everything symbols? I have experimented with unicode syntax in the past few years, and have found that replacing "if" and "while" leads to less legible code, no matter how it is done. And I have tried many options. You can do it if you go fully graphical and leave text editing altogether, but with not with text editing.You seem to have a bit of a thing about people who are trying to be cool and fashionable.Why all the ad hominems? No, I am trying to show you that the dynamic forces include more factors than rational engineering,
Oct 25 2021
On Tuesday, 26 October 2021 at 04:12:36 UTC, Ola Fosheim Grøstad wrote:On Tuesday, 26 October 2021 at 01:06:31 UTC, ClapTrap wrote:Is it ad hominen to point out that you seem to jump to certain explanations of why people do something? Personally i don't think it's relevant, I mean I'm sure it exists, but i dont think kids who wannabee leet programmers drive the adoption of C++. I dont think having "&&" over "and" drives it either.You seem to have a bit of a thing about people who are trying to be cool and fashionable.Why all the ad hominems? No, I am trying to show you that the dynamic forces include more factors than rational engineering,
Oct 26 2021
On Tuesday, 26 October 2021 at 09:17:18 UTC, ClapTrap wrote:Is it ad hominen to point out that you seem to jump to certain explanations of why people do something?Yes. You are making assumptions from arbitrary examples. Don't do that.Personally i don't think it's relevant, I mean I'm sure it exists, but i dont think kids who wannabee leet programmers drive the adoption of C++.There is no singular group that keeps C++ relevant. Among those that pick up C++ as a hobby you'll have a rather young audience. It is a language that requires a lot of patience and dedication.
Oct 26 2021
On Tuesday, 26 October 2021 at 09:33:51 UTC, Ola Fosheim Grøstad wrote:On Tuesday, 26 October 2021 at 09:17:18 UTC, ClapTrap wrote:When keep using terms like elitist, fashionista, wanabee, to describe people who make choices you disagree with it makes you look like you have a chip on your shoulder. Its not ad hominem to point that out IMO. Labelling whole groups of people with derogatory (implied by context) terms is probably more of an ad hominem (or hominems i guess).Is it ad hominen to point out that you seem to jump to certain explanations of why people do something?Yes. You are making assumptions from arbitrary examples. Don't do that.
Oct 26 2021
On Tuesday, 26 October 2021 at 11:06:55 UTC, ClapTrap wrote:When keep using terms like elitist, fashionista, wanabee, to describe people who make choices you disagree with it makes you look like you have a chip on your shoulder.Good grief. What people? I am making up arbitrary examples describing common traits of most human beings, it describes nobody in particular and everybody in general. I wrote machine language in my teens, not because it was practical, but because I wanted to master the hardware. That is a clear identity motif. There is no reason to be offended by the obvious: humans are strongly affected by culture, identity and emotional aspects. Programmers included.
Oct 26 2021
On Tuesday, 26 October 2021 at 11:27:50 UTC, Ola Fosheim Grøstad wrote:On Tuesday, 26 October 2021 at 11:06:55 UTC, ClapTrap wrote:You literally said there's no rational reason to choose "&&" over "and" so those people who do so must be elitist blowhards.When keep using terms like elitist, fashionista, wanabee, to describe people who make choices you disagree with it makes you look like you have a chip on your shoulder.Good grief. What people? I am making up arbitrary examples describing common traits of most human beings, it describes nobody in particular and everybody in general.I wrote machine language in my teens, not because it was practical, but because I wanted to master the hardware. That is a clear identity motif.Err ok, you did something because you wanted to.There is no reason to be offended by the obvious: humans are strongly affected by culture, identity and emotional aspects. Programmers included.I don't dispute that, what I dispute is that it's relevant when people are choosing tools. People arn't thinking about how cool they will look holding it when they go shopping for a chainsaw, they are thinking about whether it will make the job faster, better or easier. I think the idea that fashion or wanting to appear cool or whatever has anything more than a negligible effect on language adoption is pure BS to be honest.
Oct 26 2021
On Tuesday, 26 October 2021 at 21:44:33 UTC, ClapTrap wrote:You literally said there's no rational reason to choose "&&" over "and" so those people who do so must be elitist blowhards.No. Stop making up stuff.I don't dispute that, what I dispute is that it's relevant when people are choosing tools. People arn't thinking about how cool they will look holding it when they go shopping for a chainsaw, they are thinking about whether it will make the job faster, better or easier.Uhm. I most certainly enjoyed how cool my Husqvarna 242G was when I reved it up to 15000 RPM and sliced trunks like butter. I still feel pretty darn cool when I use it, far more so than when using the electric saw. There is plenty of coolness factors in marketing and design of forestry and agriculture equipment. Especially tractors. Just take a look at the visual appearance of modern Valtra and Ferrari tractors.I think the idea that fashion or wanting to appear cool or whatever has anything more than a negligible effect on language adoption is pure BS to be honest.Were you around when C++ and Java lauched commercially? People navigate socially. Hype works. I never mentioned anything about appearance. I mentioned identity and culture. Basically: who do you want to be and which group do feel that you belong to?
Oct 26 2021
On Tuesday, 26 October 2021 at 22:11:29 UTC, Ola Fosheim Grøstad wrote:On Tuesday, 26 October 2021 at 21:44:33 UTC, ClapTrap wrote:"It us equally puzzeling why prople want "&&" instead of "and" or "||" instead of "or". There is no rational explanation, I think people like to feel that they are using something advanced and that a syntax that that is associated with advanced usage makes them feel more skilled? Kinda like fashion"You literally said there's no rational reason to choose "&&" over "and" so those people who do so must be elitist blowhards.No. Stop making up stuff.Is that why you bought it? So you can feel cool? I have a bunch of Stihl gear, a Kombi tool, couple of chainsaws. I bought them simply because they are exceptionally good are the job they are designed to do, and they are extremely reliable. Fashion, or thinking how they tie into my ego, didn't factor into the decision to buy them.I don't dispute that, what I dispute is that it's relevant when people are choosing tools. People arn't thinking about how cool they will look holding it when they go shopping for a chainsaw, they are thinking about whether it will make the job faster, better or easier.Uhm. I most certainly enjoyed how cool my Husqvarna 242G was when I reved it up to 15000 RPM and sliced trunks like butter. I still feel pretty darn cool when I use it, far more so than when using the electric saw.There is plenty of coolness factors in marketing and design of forestry and agriculture equipment. Especially tractors. Just take a look at the visual appearance of modern Valtra and Ferrari tractors.Farmers will still look at whether the tractor actually has the features they need before considering whether it looks cool or not.Hype works, but I dont see the hype used used to push programming languages as being of the kind you think it is. It's hype about features, about how it'll make your programs faster, safer, easier. It's not hype plays into peoples ideas about themselves. It's not "Learn Java and be cool", its "Write once run anywhere".I think the idea that fashion or wanting to appear cool or whatever has anything more than a negligible effect on language adoption is pure BS to be honest.Were you around when C++ and Java lauched commercially? People navigate socially. Hype works.
Oct 26 2021
On Tuesday, 26 October 2021 at 23:59:34 UTC, ClapTrap wrote:On Tuesday, 26 October 2021 at 22:11:29 UTC, Ola Fosheim Grøstad wrote:Yes, nothing about "elitist blowhard". Why are you obsessing over this point?On Tuesday, 26 October 2021 at 21:44:33 UTC, ClapTrap wrote:"It us equally puzzeling why prople want "&&" instead of "and" or "||" instead of "or". There is no rational explanation, I think people like to feel that they are using something advanced and that a syntax that that is associated with advanced usage makes them feel more skilled? Kinda like fashion"You literally said there's no rational reason to choose "&&" over "and" so those people who do so must be elitist blowhards.No. Stop making up stuff.Is that why you bought it? So you can feel cool?What do you mean? Stihl and Husqvarna are technically comparable, but I prefer Husqvarna, which is nordic and looks and feels better. Basically an identity issue.I have a bunch of Stihl gear, a Kombi tool, couple of chainsaws. I bought them simply because they are exceptionally good are the job they are designed to do, and they are extremely reliable. Fashion, or thinking how they tie into my ego, didn't factor into the decision to buy them.Nobody thinks about identity issues, but they are there for sure. How can you know that one tool is better than any other tool, or what is good enough? You dont know until it breaks. So you navigate by some external source. You cannot learn all languages and make a rational choice, you have to make a choice based on some limited information. Or go with what you are used to or comfortable with (ties into identity).It's not hype plays into peoples ideas about themselves. It's not "Learn Java and be cool", its "Write once run anywhere".I dont agree. Programmers often put more emphasis on performance than is rational for the software they are going to write. That ties into identity. Same thing with cars, when people feel that they need a more powerful engine or faster car than you can make good use of in a city. People like to feel empowered beyond what they need. End users want the full edition of software even when the lite edition covers their needs and is less confusing to use. I would prefer the pro line Husqvarna saw even though the hobby saw works just as well, meaning I might pay double price for getting a heated handle that has a more sturdy feel. That makes me feel ready for professional work, which is a good feeling. What makes us feel empowered isnt entirely rational, but that feeling is something we seek. I am fully aware that PhP is sufficient for webwork, but I don't feel empowered when using it. It does not feel like a professional tool, and that has a lot to do with syntax. From a rational point of view, you might argue that PhP is just as good as any other tool. But it does not fit with my identity.
Oct 26 2021
On Wednesday, 27 October 2021 at 01:05:22 UTC, Ola Fosheim Grøstad wrote:On Tuesday, 26 October 2021 at 23:59:34 UTC, ClapTrap wrote:Exactly!! If they are technically comparable then you would choose the one that looks more nordic. If this identity nonsense comes in it only does so after technical requirements are met. And chainsaws are pretty simple machines, I mean in terms of design they are pretty much all at the same place. So you can probably find very similarly specced machines by all the big manufacturers. Programming languages are not like that, they're not technically comparable, you pick any two languages you can find a shed load of technical reasons to chose one over the other.On Tuesday, 26 October 2021 at 22:11:29 UTC, Ola Fosheim Grøstad wrote: Is that why you bought it? So you can feel cool?What do you mean? Stihl and Husqvarna are technically comparable, but I prefer Husqvarna, which is nordic and looks and feels better. Basically an identity issue.You read up on the web, or you ask someone you think will be able to help. But you don't go and ask them "I need a chainsaw, which is the most nordic?". Or maybe you do? :)Fashion, or thinking how they tie into my ego, didn't factor into the decision to buy them.Nobody thinks about identity issues, but they are there for sure. How can you know that one tool is better than any other tool, or what is good enough? You dont know until it breaks. So you navigate by some external source.Saying PhP is just as good as any other tool is not a rational point of view. And if you use statements like that in your reasoning then you end up in stupid places where you cant dislike like something just because it's crap. It has to be because it doesn't fit your identity.It's not hype plays into peoples ideas about themselves. It's not "Learn Java and be cool", its "Write once run anywhere".I am fully aware that PhP is sufficient for webwork, but I don't feel empowered when using it. It does not feel like a professional tool, and that has a lot to do with syntax. From a rational point of view, you might argue that PhP is just as good as any other tool. But it does not fit with my identity.
Oct 27 2021
On Wednesday, 27 October 2021 at 21:31:05 UTC, ClapTrap wrote:And chainsaws are pretty simple machines, I mean in terms of design they are pretty much all at the same place. So you can probably find very similarly specced machines by all the big manufacturers.Hm, I don't think anyone are making high speed chainsaws anymore (I think they max out at 11000RPM now). Only matters slightly when delimbing really. RPM goes down real fast when you enter anything with thickness (it is a thinning saw, so not very powerful, but easy handling).Programming languages are not like that, they're not technically comparable, you pick any two languages you can find a shed load of technical reasons to chose one over the other.Most people tend to go with what-other-people-are-going-with. For instance, C++ is pretty much a lonely king-on-the-hill for graphics and audio. You go with the group that you identify with is using. Java for business applications. And so on. I don't actually think average developers look for new opportunities when picking a language. When they pick a framework, they might. For language choice, I think average programmers go with something that makes them feel safe.You read up on the web, or you ask someone you think will be able to help. But you don't go and ask them "I need a chainsaw, which is the most nordic?". Or maybe you do? :)Heh, when I was young I totally wanted the Jonsered 20xx TURBO. That "TURBO" made it seem totally awesome (but probably was no better, clever marketing ;^). All the pro saws in stores were either Husqvarna or Jonsered back then (Swedish brands) IIRC. I doubt I would have considered any other brands, just assumed other brands were crap. And I still feel/assume that Husqvarna is better than Stihl in handling and build quality, and would not consider other brands than those two. Taking down windfalls can be dangerous, I don't want the saw to fail on me. As I said, you don't know if a tool is robust until it fails.Saying PhP is just as good as any other tool is not a rational point of view.The syntax isn't great, but the semantics in "modern" Php is good enough. I personally don't feel the package is up to a professional standard, although people obviously use it in a pro setting. So it is a feeling, more than a dissection. If I am going to spend a lot of time focusing on a language I want an aesthetics I like, so that I can write code I from time-to-time feel is beautiful. Can you be truly satisfied with a language if you don't like the looks of the code at the end of the day? I doubt it, but then we are in a very subjective landscape! It is kinda like why I want the pro line Husqvarna, I want the top handle to be in metal. It gives me a better feeling and I can focus more on the work (and forget about the tool). It is kinda subjective though, whether one feels a metal handle is better than a plastic handle.
Oct 27 2021
On Sunday, 24 October 2021 at 08:42:54 UTC, Ola Fosheim Grøstad wrote:It us equally puzzeling why prople want "&&" instead of "and" or "||" instead of "or". There is no rational explanation, I think people like to feel that they are using something advanced and that a syntax that that is associated with advanced usage makes them feel more skilled? Kinda like fashion...Like genetic random drift, those boolean operators are mostly because C won over Pascal. The boolean operators in Pascal and Ada are more readable in my opinion. So I guess the majority of people in the native just never experienced those other operators.
Oct 25 2021
On Monday, 25 October 2021 at 10:01:35 UTC, Guillaume Piolat wrote:On Sunday, 24 October 2021 at 08:42:54 UTC, Ola Fosheim Grøstad wrote:Pascal has shr, shl, begin, end, maybe other wordy stuff, where do you draw the line? Or rather where do you write "line"? :)It us equally puzzeling why prople want "&&" instead of "and" or "||" instead of "or". There is no rational explanation, I think people like to feel that they are using something advanced and that a syntax that that is associated with advanced usage makes them feel more skilled? Kinda like fashion...Like genetic random drift, those boolean operators are mostly because C won over Pascal. The boolean operators in Pascal and Ada are more readable in my opinion. So I guess the majority of people in the native just never experienced those other operators.
Oct 25 2021
On Monday, 25 October 2021 at 12:00:09 UTC, ClapTrap wrote:Pascal has shr, shl, begin, end, maybe other wordy stuff, where do you draw the line? Or rather where do you write "line"? :)baby vs bathwater
Oct 25 2021
On Monday, 25 October 2021 at 13:23:57 UTC, Guillaume Piolat wrote:On Monday, 25 October 2021 at 12:00:09 UTC, ClapTrap wrote:I know the idiom but I dont understand what you mean in this context.Pascal has shr, shl, begin, end, maybe other wordy stuff, where do you draw the line? Or rather where do you write "line"? :)baby vs bathwater
Oct 25 2021
On Monday, 25 October 2021 at 22:06:25 UTC, ClapTrap wrote:On Monday, 25 October 2021 at 13:23:57 UTC, Guillaume Piolat wrote:Er sorry. I was just meaning that Pascal did have good ideas that have suffered from its demise.On Monday, 25 October 2021 at 12:00:09 UTC, ClapTrap wrote:I know the idiom but I dont understand what you mean in this context.Pascal has shr, shl, begin, end, maybe other wordy stuff, where do you draw the line? Or rather where do you write "line"? :)baby vs bathwater
Oct 26 2021
On Monday, 25 October 2021 at 12:00:09 UTC, ClapTrap wrote:Pascal has shr, shl, begin, end, maybe other wordy stuff, where do you draw the line? Or rather where do you write "line"? :)The line is simply the style consistency. - `and` and `or` are named operators - `&&` and `||` are symbolic operators Named operators cause problems for the sustainability of a language over time. A language should be consistent, so when new operators have to be added, pascal-like languages must stick to the tradition. A few years back there was a discussion on the freepascal forums about [the conditional expressions](https://www.mail-archive.com/fpc-pascal lists.freepascal org/msg41242.html). To keep the language coherant (i.e dont start to use _symbolic operators_) the final proposition was an intrinsic `IfThen`. It's easier to create new operators if the _symbolic_ style is used. To go back to `&&` and `||`... There are just the shortcut versions of `&` and `|` ... Pascal can use `and` and `or` for both logical and bitwise arithmetic expressions for the sole and unique reason that **there is no implicit conversion** from `Boolean` to the integer types and and no implicit boolean evalation of integer types. So... in `if e1 and e2 then ...`, to compile `and` has to be a shortcut logical and. dot. (`e3 := e1 and e2; if e3 then...` is not rewritten `if e3 <> 0 then...`.) You see that finally this has nothing to do with the hype or whatever. In both case the style and the semantic are perfectly coherant.
Oct 26 2021
On Wednesday, 27 October 2021 at 01:18:47 UTC, Basile B. wrote:You see that finally this has nothing to do with the hype or whatever. In both case the style and the semantic are perfectly coherant.No, to be consistent with other infix operators for integers +*/- you would use symbols for bit manipulation. If you resuse integer operators for booleans, then conditional expressions get more difficult to read when they contain both. Which is bad for usability. Side note: Simula had or, or else, and, and then. So, both with and without short circuit.
Oct 26 2021
On Wednesday, 27 October 2021 at 06:58:13 UTC, Ola Fosheim Grøstad wrote:Side note: Simula had or, or else, and, and then. So, both with and without short circuit.Please note that the original Pascal did not have bit operations IIRC. The p-code machine had only 5 math operators. It was a simplified expression of ideas from Algol.
Oct 27 2021
FWIW, from Stefik and Sibert, «An Empirical Investigation into Programming Language syntax», _ACM Transactions on Computing Education_, vol. 13, No. 2, 2013: Both programmers and non-programmers had their preference for *boolean and* ordered as: x and y, x&y, x&&y. With a dip in interest for the && version. Which isn't surprising. For *boolean or* there was more deviance. Non-programmers preferred: x or y, either x or y, x and y (!). Non-programmers seemed to have problem grasping the concept of logical or. Programmers preferred: x or y, either x or y, x||y. For *string concatenation* programmers had a preference for: +, &, _ and a dislike for: -, ?, $ (The authors list many other constructs.)
Oct 27 2021
On Wednesday, 27 October 2021 at 14:07:42 UTC, Ola Fosheim Grøstad wrote:FWIW, from Stefik and Sibert, «An Empirical Investigation into Programming Language syntax», _ACM Transactions on Computing Education_, vol. 13, No. 2, 2013:Another paper, Altadmri and Brown, «37 Million Compilations: Investigating Novice Programming Mistakes in LargeScale Student Data», *SIGCSE’15*. They point out that using "&" instead of "&&" is a mistake that it takes a long time to fix since it does not lead to a compilation error. It occured a bit more often than having a mismatch between a function return type and the type of the variable it assigns to.
Oct 27 2021
On Wednesday, 27 October 2021 at 16:54:07 UTC, Ola Fosheim Grøstad wrote:On Wednesday, 27 October 2021 at 14:07:42 UTC, Ola Fosheim Grøstad wrote:I'm a bit surprised by the results of these studies. I'd say that what people prefer actually does not matter because they dont necessarily have in mind the consistency criterion mentioned earlier. (side note: there's actually a proglang, Quorum, that has part of the design bassed on surveys !) What's important is that the compiler should prevent reasoning errors, just like when AssignExp is rejected if used as condition.FWIW, from Stefik and Sibert, «An Empirical Investigation into Programming Language syntax», _ACM Transactions on Computing Education_, vol. 13, No. 2, 2013:Another paper, Altadmri and Brown, «37 Million Compilations: Investigating Novice Programming Mistakes in LargeScale Student Data», *SIGCSE’15*. They point out that using "&" instead of "&&" is a mistake that it takes a long time to fix since it does not lead to a compilation error. It occured a bit more often than having a mismatch between a function return type and the type of the variable it assigns to.
Oct 27 2021
On Wednesday, 27 October 2021 at 17:41:40 UTC, Basile B. wrote:I'm a bit surprised by the results of these studies. I'd say that what people prefer actually does not matter because they dont necessarily have in mind the consistency criterion mentioned earlier.My phrasing may have been a bit imprecise. The students were asked to rank the phrases as to how well they thought they matched up to the concept. So, basically, how intuitive they found them. They had C++ experience.(side note: there's actually a proglang, Quorum, that has part of the design bassed on surveys !)Yes, I found some papers on that one too! It appears to have been developed for blind programmers (?!), but has been adopted more widely in teaching. I also found a paper that created and played melodies when debugging programs so that you could hear how the program executed. I assume this means that you could hear when a loop was exited, a branch was taken etc. Surprising things to be found when looking around! Unfortunately there has been very few controlled usability studies of programming language designs... I found a presentation that claimed there has only been 22 studies (over 50 years?).What's important is that the compiler should prevent reasoning errors, just like when AssignExp is rejected if used as condition.I think there are many aspects to focus on. I'll keep it short here. Some dimensions I think are relevant: * learnability: how intuitive and natural is the syntax? * retention: how easy is it to remember what you have learned (consistency, mnemonics etc)? * skimmable: how good impression of what goes on do you get by skim-reading? * legibility: how quickly do you get a correct understanding of what goes on when reading? * error prevention: is the syntax resistant to typos that go undetected? Clearly "and"/"or" is more resistant to typos than "&&"/"||", and also more skimmable with high learnability/retention (especially for "or"). But, if you don't allow implicit conversion to/from bool then the compilation stage should catch most such typos in the type system. So the impact of syntax also depends on language semantics.
Oct 27 2021
On Wednesday, 27 October 2021 at 18:35:24 UTC, Ola Fosheim Grøstad wrote:On Wednesday, 27 October 2021 at 17:41:40 UTC, Basile B. wrote:May also add that the number of years they had used C++ did affect how well they thought the C++ phrases matched the concepts, as we might expect.I'm a bit surprised by the results of these studies. I'd say that what people prefer actually does not matter because they dont necessarily have in mind the consistency criterion mentioned earlier.My phrasing may have been a bit imprecise. The students were asked to rank the phrases as to how well they thought they matched up to the concept. So, basically, how intuitive they found them. They had C++ experience.
Oct 27 2021
On Wednesday, 27 October 2021 at 18:35:24 UTC, Ola Fosheim Grøstad wrote:On Wednesday, 27 October 2021 at 17:41:40 UTC, Basile B. wrote: [...] But, if you don't allow implicit conversion to/from bool then the compilation stage should catch most such typos in the type system. So the impact of syntax also depends on language semantics.Yeah, that's a point of agreement.
Oct 28 2021
On Thursday, 28 October 2021 at 10:34:28 UTC, Basile B. wrote:On Wednesday, 27 October 2021 at 18:35:24 UTC, Ola Fosheim Grøstad wrote:BTW "to bool", as you saiy, is **not an implicit conv**... it's more a special case that **only** happens when a condition is evaluated so `if` condition, `while` condition, CondExp condition, AssertExp, and I think that's all. That detail is important to understand why pascal `and` works perfectly with both numbers and booleans ;)On Wednesday, 27 October 2021 at 17:41:40 UTC, Basile B. wrote: [...] But, if you don't allow implicit conversion to/from bool then the compilation stage should catch most such typos in the type system. So the impact of syntax also depends on language semantics.Yeah, that's a point of agreement.
Oct 28 2021
On Thursday, 28 October 2021 at 10:41:23 UTC, Basile B. wrote:On Thursday, 28 October 2021 at 10:34:28 UTC, Basile B. wrote:it's because it does not do that. If it does, then `and` is directly broken.On Wednesday, 27 October 2021 at 18:35:24 UTC, Ola Fosheim Grøstad wrote:BTW "to bool", as you saiy, is **not an implicit conv**... it's more a special case that **only** happens when a condition is evaluated so `if` condition, `while` condition, CondExp condition, AssertExp, and I think that's all. That detail is important to understand why pascal `and` works perfectly with both numbers and booleans ;)On Wednesday, 27 October 2021 at 17:41:40 UTC, Basile B. wrote: [...] But, if you don't allow implicit conversion to/from bool then the compilation stage should catch most such typos in the type system. So the impact of syntax also depends on language semantics.Yeah, that's a point of agreement.
Oct 28 2021
On Wednesday, 27 October 2021 at 14:07:42 UTC, Ola Fosheim Grøstad wrote:FWIW, from Stefik and Sibert, «An Empirical Investigation into Programming Language syntax», _ACM Transactions on Computing Education_, vol. 13, No. 2, 2013: Both programmers and non-programmers had their preference for *boolean and* ordered as: x and y, x&y, x&&y. With a dip in interest for the && version. Which isn't surprising. For *boolean or* there was more deviance. Non-programmers preferred: x or y, either x or y, x and y (!). Non-programmers seemed to have problem grasping the concept of logical or. Programmers preferred: x or y, either x or y, x||y. For *string concatenation* programmers had a preference for: +, &, _ and a dislike for: -, ?, $As with all statistics the answers are heavily biased by the choices that were not asked for: I would strongly prefer ∨ for or, ∧ for and (and ⊻ for exclusive or btw) and I think ~ for cat is a good choice (and far better than +), but I would prefer ∘.
Oct 28 2021
On Thursday, 28 October 2021 at 07:05:47 UTC, Dom DiSc wrote:I would strongly prefer ∨ for or, ∧ for and (and ⊻ for exclusive or btw) and I think ~ for cat is a good choice (and far better than +), but I would prefer ∘."v" was available, but I don't think they got unicode alternatives.
Oct 28 2021
On Thursday, 28 October 2021 at 07:17:00 UTC, Ola Fosheim Grøstad wrote:On Thursday, 28 October 2021 at 07:05:47 UTC, Dom DiSc wrote:https://tryapl.org/ uni: ∨∧ asc: v^I would strongly prefer ∨ for or, ∧ for and (and ⊻ for exclusive or btw) and I think ~ for cat is a good choice (and far better than +), but I would prefer ∘."v" was available, but I don't think they got unicode alternatives.
Oct 28 2021
On Thursday, 28 October 2021 at 07:45:38 UTC, jfondren wrote:https://tryapl.org/ uni: ∨∧ asc: v^Only that ^ atm is used as xor, not and :-( (uh, writing such a sentence makes very clear, why using words instead of symbolic operators is such a bad idea)
Oct 28 2021
On Thursday, 28 October 2021 at 07:45:38 UTC, jfondren wrote:https://tryapl.org/ uni: ∨∧ asc: v^I think you would have to write to the authors to find out all the alternatives they gave. I don't know if they provided "^" or not.
Oct 28 2021
On Thursday, 28 October 2021 at 08:54:35 UTC, Ola Fosheim Grøstad wrote:On Thursday, 28 October 2021 at 07:45:38 UTC, jfondren wrote:Ok, so I read the article again and they did and they were ranked low for OR: The three lowest ranked for non-programmers: "v", "^", "nor" The three lowest ranked for programmers: "^", "exclusive and", "nor" I don't know how they were ranked for AND.https://tryapl.org/ uni: ∨∧ asc: v^I think you would have to write to the authors to find out all the alternatives they gave. I don't know if they provided "^" or not.
Oct 28 2021
On Thursday, 28 October 2021 at 07:45:38 UTC, jfondren wrote:On Thursday, 28 October 2021 at 07:17:00 UTC, Ola Fosheim Grøstad wrote:In case anyone is unfamiliar with it, Notation As A Tool Of Thought (Iverson) https://www.jsoftware.com/papers/tot.htmOn Thursday, 28 October 2021 at 07:05:47 UTC, Dom DiSc wrote:https://tryapl.org/ uni: ∨∧ asc: v^I would strongly prefer ∨ for or, ∧ for and (and ⊻ for exclusive or btw) and I think ~ for cat is a good choice (and far better than +), but I would prefer ∘."v" was available, but I don't think they got unicode alternatives.
Oct 28 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:* Features you'd like to see in D2 - A BetterC mode but with classes, exceptions, and no GC. 3 - ProtoObject. A nogc nothrow .destroy. 4 - Progressive runtime replaces BetterC. It becomes entirely static and magically works in shared objects. 5 - impure
Oct 11 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:* Worst features implemented in a non-toy languageWell not a feature per se, but the idea that number of keywords or number of features really matters. People argue you should remove things just to remove things. But this often just moves the inherent difficulty of programming from the language to the code. You don't wanna go too far with it, of course, but there is simple metric here.* Worst features (in your opinion) in DThe whole int promotion and casting mess. Two ideas that sound fine in isolation but make things just nearly unusable in real life when combined.* Features you'd like to see in DExplicit implicit construction. Minimally on return values, but also on function arguments would be nice. Note the constructor called implicitly must be explicitly labeled implicit.
Oct 11 2021
On Monday, 11 October 2021 at 20:51:13 UTC, Adam D Ruppe wrote:You don't wanna go too far with it, of course, but there is simple metric here.err there is NO simple metric here.
Oct 11 2021
On Monday, 11 October 2021 at 20:51:13 UTC, Adam D Ruppe wrote:On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:could you give an example on how those features would be like?[...]Well not a feature per se, but the idea that number of keywords or number of features really matters. People argue you should remove things just to remove things. But this often just moves the inherent difficulty of programming from the language to the code. You don't wanna go too far with it, of course, but there is simple metric here.[...]The whole int promotion and casting mess. Two ideas that sound fine in isolation but make things just nearly unusable in real life when combined.[...]Explicit implicit construction. Minimally on return values, but also on function arguments would be nice. Note the constructor called implicitly must be explicitly labeled implicit.
Nov 14 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy language * Worst features (in your opinion) in D * Features you'd like to see in D Ideas? Examples? Thanks!Worst features: - ability to define alias this on class objects - inout
Oct 11 2021
On Monday, 11 October 2021 at 21:22:29 UTC, RazvanN wrote:On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:Yes! This right here is the worst feature as it is a source of headaches when it comes to compiler bugs. We can replace this that introduce new features for the classes such as the much needed properties overhaul that is still WIP. https://github.com/12345swordy/DIPs/blob/properties/DIPs/%40get%20%40set%20.md and introduce default interface implementation. Before you ask, No, using string mixin or templates for implementing interfaces is NOT considered to be a default interface implementation. See here: https://github.com/dotnet/csharplang/blob/main/proposals/csharp-8.0/default-interface-methods.md - AlexI'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy language * Worst features (in your opinion) in D * Features you'd like to see in D Ideas? Examples? Thanks!Worst features: - ability to define alias this on class objects
Oct 11 2021
On Monday, 11 October 2021 at 21:32:52 UTC, 12345swordy wrote:[snip] Before you ask, No, using string mixin or templates for implementing interfaces is NOT considered to be a default interface implementation. See here: https://github.com/dotnet/csharplang/blob/main/proposals/csharp-8.0/default-interface-methods.md - AlexInterfaces can have final methods, you just can't overwrite them.
Oct 11 2021
On Monday, 11 October 2021 at 21:40:08 UTC, jmh530 wrote:On Monday, 11 October 2021 at 21:32:52 UTC, 12345swordy wrote:Did you not read the file that I linked? - Alex[snip] Before you ask, No, using string mixin or templates for implementing interfaces is NOT considered to be a default interface implementation. See here: https://github.com/dotnet/csharplang/blob/main/proposals/csharp-8.0/default-interface-methods.md - AlexInterfaces can have final methods, you just can't overwrite them.
Oct 11 2021
On Monday, 11 October 2021 at 21:54:05 UTC, 12345swordy wrote:[snip]I skimmed it.Interfaces can have final methods, you just can't overwrite them.Did you not read the file that I linked? - Alex
Oct 11 2021
* Worst features implemented in a non-toy language* Embedding js in an html document. * adding objects to an existing language* Worst features (in your opinion) in D* nontrivial namespace collisions when importing std * int promotion * verbose enums * contracts and all the cute ideas expanding a template header to affect the matching * sword of damocles of safe by default or who knows what koolaid being enabled one day* Features you'd like to see in D* base types having fake opoverloads ( 2.opCmp(3) == 1) * universal function call syntax being universal (let me define a function in the same scope that I ufcs it) * a nice overload for _____TrAiTs(compiles,mixin("foo.bar"))
Oct 11 2021
On Monday, 11 October 2021 at 21:41:45 UTC, monkyyy wrote:* nontrivial namespace collisions when importing stdAre these still around? This compiles now: ```d unittest { import std; assert(!std.ascii.isAlpha('5')); } unittest { import std; import std.ascii : isAlpha; assert(isAlpha('X')); assert(std.uni.isAlpha('X')); } ```
Oct 11 2021
On Tuesday, 12 October 2021 at 00:13:45 UTC, jfondren wrote:On Monday, 11 October 2021 at 21:41:45 UTC, monkyyy wrote:The one that annoyed me was stdio and file, write* nontrivial namespace collisions when importing stdAre these still around? This compiles now: ```d unittest { import std; assert(!std.ascii.isAlpha('5')); } unittest { import std; import std.ascii : isAlpha; assert(isAlpha('X')); assert(std.uni.isAlpha('X')); } ```
Oct 12 2021
On Monday, 11 October 2021 at 21:41:45 UTC, monkyyy wrote:Interesting. What is it about safe by default that would worry you?* Worst features implemented in a non-toy language* Embedding js in an html document. * adding objects to an existing language* Worst features (in your opinion) in D* nontrivial namespace collisions when importing std * int promotion * verbose enums * contracts and all the cute ideas expanding a template header to affect the matching * sword of damocles of safe by default or who knows what koolaid being enabled one day
Oct 14 2021
On Thursday, 14 October 2021 at 16:48:12 UTC, Atila Neves wrote:On Monday, 11 October 2021 at 21:41:45 UTC, monkyyy wrote:I've interacted with monkyyy a bunch in the community Discord. He's the kind of programmer who would rather write code with undefined behavior and get away with it than follow any kind of compiler-enforced rules. Most programmers with this attitude eventually get it beaten out of them by painful experience. I wouldn't put too much stock in it.* sword of damocles of safe by default or who knows what koolaid being enabled one dayInteresting. What is it about safe by default that would worry you?
Oct 14 2021
On Thursday, 14 October 2021 at 17:02:49 UTC, Paul Backus wrote:On Thursday, 14 October 2021 at 16:48:12 UTC, Atila Neves wrote:The emphasis there should be on "sword of damocles" (uncertainty wrt. a future negative outcome) and "being enabled one day" (a change in the language). d is currently system by default, and making it safe by default is a breaking change that requires people to run through their code and change it, even if just to add a system: at the top. If you personally greatly value a breaking change then maybe you won't mind this kind of maintenance, but others it's imposed bitrot. dub could be in the position of automatically trying --revert= flags if the latest tag release is older than some breaking change to dmdOn Monday, 11 October 2021 at 21:41:45 UTC, monkyyy wrote:I've interacted with monkyyy a bunch in the community Discord. He's the kind of programmer who would rather write code with undefined behavior and get away with it than follow any kind of compiler-enforced rules. Most programmers with this attitude eventually get it beaten out of them by painful experience. I wouldn't put too much stock in it.* sword of damocles of safe by default or who knows what koolaid being enabled one dayInteresting. What is it about safe by default that would worry you?
Oct 14 2021
On Thursday, 14 October 2021 at 16:48:12 UTC, Atila Neves wrote:On Monday, 11 October 2021 at 21:41:45 UTC, monkyyy wrote:verbosityInteresting. What is it about safe by default that would worry you?* Worst features implemented in a non-toy language* Embedding js in an html document. * adding objects to an existing language* Worst features (in your opinion) in D* nontrivial namespace collisions when importing std * int promotion * verbose enums * contracts and all the cute ideas expanding a template header to affect the matching * sword of damocles of safe by default or who knows what koolaid being enabled one day
Oct 30 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features (in your opinion) in DAttribute soup 1. inconsistent - some with leading ' ' & some without all attributes should start with . This will help to reduce number of key/reserved words 2. need re-declare attributes for aggregated types (struct/class) even if it is already declared on module level 3. All attributes should be non-negative word and introduce negation Ex: gc: nogc become !gc Simple example module x; !gc !throw: void funcionDoNotThrow() {} // Reverse the above module attribute setting void functionThrow() throw {}
Oct 11 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy language * Worst features (in your opinion) in D * Features you'd like to see in D Ideas? Examples? Thanks!__traits should've died years ago. Its continued existence shows some level of paralysis. The decision to build languages as monolithic lumps of specification, then a compiler, also phased in it's design, while simple, I think will be a detriment in the post Moore's law age, as it makes it very irritating to use and understand the full muscle of the optimizer *in the right places* - and fundamentally limits the potential of the/a language in a now post-heterogenous world: you should he able to compile for a GPU as part of the compiler a la a trait (This is an acceptable use of the keyword, reflection is not). I think D's worst feature is really a human tendency to avoid language solutions for things. sumtype is a good library, but it should be core language for example. Typecons.tuple is even less marginal. My dream feature for D is a combination of static analysis, formal verification, and some brand of mutation testing guided by them (When we spoke about it last, Atila, you convinced me but it would take someone more dedicated than I to implement it)
Oct 11 2021
On Monday, 11 October 2021 at 22:01:34 UTC, max haughton wrote:The decision to build languages as monolithic lumps of specification, then a compiler, also phased in it's design, while simple, I think will be a detriment in the post Moore's law age, as it makes it very irritating to use and understand the full muscle of the optimizer *in the right places* - and fundamentally limits the potential of the/a language in a now post-heterogenous world: you should he able to compile for a GPU as part of the compiler a la a trait (This is an acceptable use of the keyword, reflection is not).I think a big problem from an exploratory perspective is that that is essentially impossible in a one-file-at-a-time compilation world and that to explore the space of possibilities far more people than the D community has. This afflicts C, C++, OpenCL, IPSC (1 file at a time, lack of anything other than immediate local context) CUDA, SYCL, (one file at a time, but lets do it twice! one for the host, one for the device) OpenMP (where premature outlining for device offloading has caused massive missed optimisation opportunity)I think D's worst feature is really a human tendency to avoid language solutions for things. sumtype is a good library, but it should be core language for example. Typecons.tuple is even less marginal. __traits should've died years ago. Its continued existence shows some level of paralysis.in a static slice of time, yes. As a feature to easily add language functionality, without taking up more keywords, with minimal "feature space", its indispensable. It does however show that a program needs an API to the compiler during compilation. Is there a better way to do this? core.reflect and core.codegen seem like good steps.
Oct 11 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features (in your opinion) in Dreal, specifically fp80 real. Its slow, its almost always unintentional and phobos tends to use it way more than it should.
Oct 11 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:* Worst features implemented in a non-toy languageEverything to do with header files.* Worst features (in your opinion) in DAutodecoding. Autodecoding. Autodecoding. Mutable by default. Template errors. (esp. `template instance func(T) where T = string cannot be instantiated with T = string`, or something along those lines, really, really, frustrates me) Inconsistent built-in property naming. (As a bonus: historical baggage) A fear of language solutions because of reasons, leading to annoying issues like std.sumtype being a PITA to debug sometimes due to bad error messages it can't really do anything about. `alias this` `abc => { return 123; }` should not be returning a function that returns a function.* Features you'd like to see in DLanguage support for complex types: * sumtype and/or tagged unions. esp. in regards to pattern matching * optional types. * Maybe even a result/value_or_error type. ProtoObject point of usage, not just at definition. Being able to specify new/experimental functionality per-module, Being able to match structs against an `interface` or other such construct. As a language feature since a template version I can foresee eating my CPU. Allocators being better integrated with the language/phobos. Standard, de-facto interface/library/whatever for things like logging, databases, etc. Object initialisers: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/how-to-initialize-objects-by-using-an-object-initializer And most importantly, a plan for D's future and development, because personally I have 0 idea where D is trying to go now, what it's trying to be, who it tries to please, etc. What is our vision? What are our goals and ambitions for the language? I know it's basically completely infeasible but it's a fun thought experiment to think about what a "D3" could be like. Learning from the warts of the current language, removing historical issues, just a complete redesign whilst still being D.
Oct 11 2021
On Tuesday, 12 October 2021 at 03:17:08 UTC, SealabJaster wrote:`abc => { return 123; }` should not be returning a function that returns a function.https://dlang.org/changelog/2.098.0.html#ambiguous-lambdasumtype and/or tagged unions. esp. in regards to pattern matchingI just want to be able to have a returned value be implicitly wrapped if its type is part of the `SumType` returned by the function. ```d // -preview=shortenedMethods is awesome SumType!(int, string) div(int a, int b) => b != 0 ? a : "Divisor is zero"; ```
Oct 11 2021
On 10/12/21 1:29 AM, surlymoor wrote:I just want to be able to have a returned value be implicitly wrapped if its type is part of the `SumType` returned by the function. ```d // -preview=shortenedMethods is awesome SumType!(int, string) div(int a, int b) => b != 0 ? a : "Divisor is zero"; ```Hear, hear
Oct 13 2021
On Tuesday, 12 October 2021 at 03:17:08 UTC, SealabJaster wrote:`abc => { return 123; }` should not be returning a function that returns a function.I agree with this so much, like why couldn't it have been made so you had to be explicit if you wanted to return a function? Like: `abc => &{ return 123; }`
Oct 11 2021
On 10/12/21 2:14 AM, bauss wrote:On Tuesday, 12 October 2021 at 03:17:08 UTC, SealabJaster wrote:Just FYI, the `abc => {}` syntax is just recently deprecated. https://dlang.org/changelog/2.098.0.html#ambiguous-lambda -Steve`abc => { return 123; }` should not be returning a function that returns a function.I agree with this so much, like why couldn't it have been made so you had to be explicit if you wanted to return a function? Like: `abc => &{ return 123; }`
Oct 12 2021
On Tuesday, 12 October 2021 at 11:39:56 UTC, Steven Schveighoffer wrote:On 10/12/21 2:14 AM, bauss wrote:Yeah, but I would rather that it was still allowed and that the semantics just changed. But obviously for good reason that isn't happening since it would break existing code.On Tuesday, 12 October 2021 at 03:17:08 UTC, SealabJaster wrote:Just FYI, the `abc => {}` syntax is just recently deprecated. https://dlang.org/changelog/2.098.0.html#ambiguous-lambda -Steve`abc => { return 123; }` should not be returning a function that returns a function.I agree with this so much, like why couldn't it have been made so you had to be explicit if you wanted to return a function? Like: `abc => &{ return 123; }`
Oct 12 2021
On 10/12/21 8:42 AM, bauss wrote:On Tuesday, 12 October 2021 at 11:39:56 UTC, Steven Schveighoffer wrote:What would you change it to? `(abc) {return 123; }` already works. If you need to return a delegate, then `abc => () { return 123; }` works. We don't need 10 names for different kinds of snow. -SteveOn 10/12/21 2:14 AM, bauss wrote:Yeah, but I would rather that it was still allowed and that the semantics just changed. But obviously for good reason that isn't happening since it would break existing code.On Tuesday, 12 October 2021 at 03:17:08 UTC, SealabJaster wrote:Just FYI, the `abc => {}` syntax is just recently deprecated. https://dlang.org/changelog/2.098.0.html#ambiguous-lambda -Steve`abc => { return 123; }` should not be returning a function that returns a function.I agree with this so much, like why couldn't it have been made so you had to be explicit if you wanted to return a function? Like: `abc => &{ return 123; }`
Oct 12 2021
On Tuesday, 12 October 2021 at 13:26:34 UTC, Steven Schveighoffer wrote:On 10/12/21 8:42 AM, bauss wrote:IMO the actual answer here is to deprecate the `{ /* ... */ }` syntax for function literals entirely. Not only is it confusing in the context of `=>` lambdas, it also creates a grammatical ambiguity between function literals and [block statements][1], which results in bugs like [issue 21619][2]. [1]: https://dlang.org/spec/grammar.html#BlockStatement [2]: https://issues.dlang.org/show_bug.cgi?id=21619Yeah, but I would rather that it was still allowed and that the semantics just changed. But obviously for good reason that isn't happening since it would break existing code.What would you change it to?
Oct 12 2021
On 10/12/21 12:22 PM, Paul Backus wrote:On Tuesday, 12 October 2021 at 13:26:34 UTC, Steven Schveighoffer wrote:It's not a terrible idea. But I think there are hacks all over the place that enjoy the short syntax. One that I know of is to get the parent scope of a location: ```d alias parentScope = __traits(parent, {}); ``` Now, changing this to `__traits(parent, (){})` probably isn't a horrible update to require, but this code breakage is going to seem a little extraneous. -SteveOn 10/12/21 8:42 AM, bauss wrote:IMO the actual answer here is to deprecate the `{ /* ... */ }` syntax for function literals entirely. Not only is it confusing in the context of `=>` lambdas, it also creates a grammatical ambiguity between function literals and [block statements][1], which results in bugs like [issue 21619][2]. [1]: https://dlang.org/spec/grammar.html#BlockStatement [2]: https://issues.dlang.org/show_bug.cgi?id=21619Yeah, but I would rather that it was still allowed and that the semantics just changed. But obviously for good reason that isn't happening since it would break existing code.What would you change it to?
Oct 12 2021
On Tuesday, 12 October 2021 at 17:49:10 UTC, Steven Schveighoffer wrote:It's not a terrible idea. But I think there are hacks all over the place that enjoy the short syntax. One that I know of is to get the parent scope of a location: ```d alias parentScope = __traits(parent, {}); ``` Now, changing this to `__traits(parent, (){})` probably isn't a horrible update to require, but this code breakage is going to seem a little extraneous.This syntax is cute, but it's also extremely opaque, and confusing to beginners [1][2]. `(){}` is not much better, but it at least makes it clear that what you're looking at *isn't* a normal block statement, and you need to check the documentation/ask in the Learn forum/etc. to find out what it is. [1] https://forum.dlang.org/post/rzboijdfewehucrmztyc forum.dlang.org [2] https://forum.dlang.org/post/i40s2i$271n$1 digitalmars.com
Oct 12 2021
On Tuesday, 12 October 2021 at 06:14:40 UTC, bauss wrote:On Tuesday, 12 October 2021 at 03:17:08 UTC, SealabJaster wrote:But you are do it explicitly, use the more verbose syntax: ``` alias a = abc => function{ return 123; }; ``` Also you have warning now`abc => { return 123; }` should not be returning a function that returns a function.I agree with this so much, like why couldn't it have been made so you had to be explicit if you wanted to return a function? Like: `abc => &{ return 123; }`Deprecation: Using `(args) => { ... }` to create a delegate that returns a delegate is error-prone.
Oct 12 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:* Features you'd like to see in D Ideas? Examples?What I want to change: I hope ,can directly use the standard library without 'GC'. I hope ,can also use `<>` as `template parameter` ,as `!()` more literal. I hope ,can use`...` like 'C++'. Hopefully, we can enhance 'betterC' or reduce 'GC', so that we can make good use of the 'standard library' or 'various advanced functions' I also hope that'd has a` simple, direct and easy to use GUI `Library of `hdpi` support.` GUI `is too important. I hope there are also `concept` constraints in in 'd' like in `C++`. I hope that the `d community` can change the `default attribute`. It is better to provide a tool for users to change their code. Be able to list important libraries separately and explain their purpose briefly. I hope we can collect more `good articles in the forum` into Wiki and other places. We should make good use of the `excellent posts` of people in the forum I hope we can pay attention to `Chinese users`, because Chinese people use `d` too little. I have translated many d's articles. I hope to give me some links so that the Chinese can also find `d's article`, so as not to always say that there are too few `Chinese documents`. At present, this is what I can think of , that's all.
Oct 11 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy language- Null terminated strings without length validation - No bounds checking by default - Implicit conversions between enumerations and numeric types - Lack on any sort of namespacing mechanism - Use of explicit pointers for out parameters* Worst features (in your opinion) in D- inconsistent tag soup, e.g. safe vs pure, and the amount that almost feels like coding with Spring annotations - the __ prefixes for some runtime stuff like __traits - chasing the next computing fad while trying to find out the target audience* Features you'd like to see in D- basically all the WIP stuff actually finalized before anything new gets started - safe by default (well I can still dream, until then safe: at the top of each module) when Andrei's book got published.Ideas? Examples? Thanks!
Oct 11 2021
Usage of unsigned integers as positive numbers. cf. dotnet uses signed integers and the sky doesn't fall (it's 32-bit int most of the time even). Granted some C and posix functions use signed integers when they need to return -1 sentinel value. Recently I ported an oldish program to 64 bits, naturally it used narrowing conversions everywhere, but it was mostly signed integers, those aren't very sensitive to narrowing and extension. But the program crashed; when I looked at the cause, it was STL's string::find method returning unsigned integer even though it returns a sentinel value string::npos when the searched string isn't found, and the program there converted the returned value to uint, but then string::npos!=cast(uint)string::npos - unsigned integers are sensitive to extensions.
Oct 12 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy language * Worst features (in your opinion) in D * Features you'd like to see in D Ideas? Examples? Thanks!Not necessarily a feature, but I think the absence of hindley milner type inference is a big one. I think that statically typed languages should adopt it or at the very least be influenced by it unless they have a really good reason not too. Types are completely optional in (vanilla) hindley milner. You can write code that looks like python and still have all the benefits of static typing. It also infers the most general type for the code you write. This makes your code as generic as possible unless you add a type annotation to make it less generic. I also think that it can help in language design in general. Weak typing and subtyping, features that are generally disliked are incompatible with hindley milner. It gives good answers to what the type of a null pointer and an empty array are without resorting to void pointers and void arrays which feel hacky.
Oct 12 2021
On 13/10/2021 3:06 AM, Superstar64 wrote:Not necessarily a feature, but I think the absence of hindley milner type inference is a big one. I think that statically typed languages should adopt it or at the very least be influenced by it unless they have a really good reason not too.Hey hey hey, ML strikes again! ML + C syntax would have been a realllll winner back in the 70's I reckon, or today cos ya know that is the direction we are all going in.
Oct 12 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy language * Worst features (in your opinion) in D * Features you'd like to see in D Ideas? Examples? Thanks!foreach_reverse - worst "feature" mankind has produced
Oct 12 2021
On Tuesday, 12 October 2021 at 18:59:29 UTC, Imperatorn wrote:On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:why is it that bad? lolI'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy language * Worst features (in your opinion) in D * Features you'd like to see in D Ideas? Examples? Thanks!foreach_reverse - worst "feature" mankind has produced
Nov 14 2021
On Sunday, 14 November 2021 at 21:13:59 UTC, Dr Machine Code wrote:On Tuesday, 12 October 2021 at 18:59:29 UTC, Imperatorn wrote:It's just so ugly 😅On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:why is it that bad? lolI'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy language * Worst features (in your opinion) in D * Features you'd like to see in D Ideas? Examples? Thanks!foreach_reverse - worst "feature" mankind has produced
Nov 14 2021
On Sunday, 14 November 2021 at 23:51:00 UTC, Imperatorn wrote:On Sunday, 14 November 2021 at 21:13:59 UTC, Dr Machine Code wrote:The keyword isn't pretty, but it's useful, easy to understand, and actually works correctly. I'm sure you can think of something worse if you really try...On Tuesday, 12 October 2021 at 18:59:29 UTC, Imperatorn wrote:It's just so ugly 😅foreach_reverse - worst "feature" mankind has producedwhy is it that bad? lol
Nov 14 2021
On Monday, 15 November 2021 at 00:49:17 UTC, tsbockman wrote:On Sunday, 14 November 2021 at 23:51:00 UTC, Imperatorn wrote:Well, obviously :) It was more of a joke, but it's still pretty cringe to see itOn Sunday, 14 November 2021 at 21:13:59 UTC, Dr Machine Code wrote:The keyword isn't pretty, but it's useful, easy to understand, and actually works correctly. I'm sure you can think of something worse if you really try...On Tuesday, 12 October 2021 at 18:59:29 UTC, Imperatorn wrote:It's just so ugly 😅foreach_reverse - worst "feature" mankind has producedwhy is it that bad? lol
Nov 15 2021
On 15.11.21 10:29, Imperatorn wrote:On Monday, 15 November 2021 at 00:49:17 UTC, tsbockman wrote:The reason it exists is that reverse iteration over unsigned types is notoriously error prone. I think it's pretty nice to have this built in, knowing that it will be directly transformed into a simple for loop even in debug builds. It also allows easily reversing the order of iteration of any foreach loop, no matter which form. In particular, there is `static foreach_reverse`.On Sunday, 14 November 2021 at 23:51:00 UTC, Imperatorn wrote:Well, obviously :) It was more of a joke, but it's still pretty cringe to see itOn Sunday, 14 November 2021 at 21:13:59 UTC, Dr Machine Code wrote:The keyword isn't pretty, but it's useful, easy to understand, and actually works correctly. I'm sure you can think of something worse if you really try...On Tuesday, 12 October 2021 at 18:59:29 UTC, Imperatorn wrote:It's just so ugly 😅foreach_reverse - worst "feature" mankind has producedwhy is it that bad? lol
Nov 15 2021
On Monday, 15 November 2021 at 12:41:51 UTC, Timon Gehr wrote:On 15.11.21 10:29, Imperatorn wrote:What's wrong about retro? Too retro :DOn Monday, 15 November 2021 at 00:49:17 UTC, tsbockman wrote:The reason it exists is that reverse iteration over unsigned types is notoriously error prone. I think it's pretty nice to have this built in, knowing that it will be directly transformed into a simple for loop even in debug builds. It also allows easily reversing the order of iteration of any foreach loop, no matter which form. In particular, there is `static foreach_reverse`.[...]Well, obviously :) It was more of a joke, but it's still pretty cringe to see it
Nov 15 2021
On Monday, 15 November 2021 at 14:02:42 UTC, Imperatorn wrote:What's wrong about retro? Too retro :Dstd.range.retro is honestly just a bad name. It should have been `reversed`, or maybe `reverser`.
Nov 15 2021
On Monday, 15 November 2021 at 14:09:53 UTC, Paul Backus wrote:On Monday, 15 November 2021 at 14:02:42 UTC, Imperatorn wrote:That reverser thing could have been a builtin property e.g `.reverser`, problem is that the expression that gives a foreach range (https://dlang.org/spec/statement.html#foreach-range-statement) is a bit degenerated for now: `LwrExpression .. UprExpression` is actually not an expression at all thus `(LwrExpression ..UprExpression).reverser` cant work. But Ideally D could get rid of that `foreach_reverse` keyword with a property. ```d foreach (i; (0 .. length).reverser){} foreach (e; elems.reverser){} ``` Off topic side node : the old [DIP 58](https://wiki.dlang.org/DIP58) shows that the idea to have the `..` D operator is not new but apparently the case of simplifying `foreach` was not a goal.What's wrong about retro? Too retro :Dstd.range.retro is honestly just a bad name. It should have been `reversed`, or maybe `reverser`.
Nov 15 2021
On Monday, 15 November 2021 at 14:09:53 UTC, Paul Backus wrote:On Monday, 15 November 2021 at 14:02:42 UTC, Imperatorn wrote:``` alias reversed = retro; ``` Problem solved :)What's wrong about retro? Too retro :Dstd.range.retro is honestly just a bad name. It should have been `reversed`, or maybe `reverser`.
Dec 17 2021
On 15.11.21 15:02, Imperatorn wrote:On Monday, 15 November 2021 at 12:41:51 UTC, Timon Gehr wrote:My post was literally a description of drawbacks of retro. There's nothing wrong with it in particular, but the main drawback is that in general you need to do more than slap retro on the aggregate in order to get the correct semantics. Tuple!(int,int)[] a=...; foreach(i,x;a){} // reverse this!On 15.11.21 10:29, Imperatorn wrote:What's wrong about retro? Too retro :DOn Monday, 15 November 2021 at 00:49:17 UTC, tsbockman wrote:The reason it exists is that reverse iteration over unsigned types is notoriously error prone. I think it's pretty nice to have this built in, knowing that it will be directly transformed into a simple for loop even in debug builds. It also allows easily reversing the order of iteration of any foreach loop, no matter which form. In particular, there is `static foreach_reverse`.[...]Well, obviously :) It was more of a joke, but it's still pretty cringe to see it
Nov 15 2021
On 11/15/21 7:41 AM, Timon Gehr wrote:On 15.11.21 10:29, Imperatorn wrote:Although it's fallen mostly out of style, the reason I hated `foreach_reverse` is because it used to be applicable to delegate iteration, but just iterates forward (I've just checked and it's deprecated, but not disabled). I think I can count on one finger (and you can guess which one) the times I've used `foreach_reverse`. -SteveOn Monday, 15 November 2021 at 00:49:17 UTC, tsbockman wrote:The reason it exists is that reverse iteration over unsigned types is notoriously error prone. I think it's pretty nice to have this built in, knowing that it will be directly transformed into a simple for loop even in debug builds. It also allows easily reversing the order of iteration of any foreach loop, no matter which form. In particular, there is `static foreach_reverse`.On Sunday, 14 November 2021 at 23:51:00 UTC, Imperatorn wrote:Well, obviously :) It was more of a joke, but it's still pretty cringe to see itOn Sunday, 14 November 2021 at 21:13:59 UTC, Dr Machine Code wrote:The keyword isn't pretty, but it's useful, easy to understand, and actually works correctly. I'm sure you can think of something worse if you really try...On Tuesday, 12 October 2021 at 18:59:29 UTC, Imperatorn wrote:It's just so ugly 😅foreach_reverse - worst "feature" mankind has producedwhy is it that bad? lol
Nov 15 2021
On Monday, 15 November 2021 at 14:19:00 UTC, Steven Schveighoffer wrote:I think I can count on one finger (and you can guess which one) the times I've used `foreach_reverse`.Pinkie?
Nov 15 2021
On Monday, 15 November 2021 at 14:19:00 UTC, Steven Schveighoffer wrote:I think I can count on one finger (and you can guess which one) the times I've used `foreach_reverse`.~/arsd$ grep foreach_reverse *.d | wc 34 it p useful actually.
Nov 15 2021
On Monday, 15 November 2021 at 14:19:00 UTC, Steven Schveighoffer wrote:On 11/15/21 7:41 AM, Timon Gehr wrote:Maybe this is older. When I came to D around 2015, I learned that there is `opApply` for forward iteration (`foreach`) and `opApplyReverse` for reverse iteration (`foreach_reverse`). I just tried defining a struct with `opApply`, but no `opApplyReverse`, and then `foreach_reverse` on an instance (on run.dlang.io). Doesn't work.In particular, there is `static foreach_reverse`.Although it's fallen mostly out of style, the reason I hated `foreach_reverse` is because it used to be applicable to delegate iteration, but just iterates forward (I've just checked and it's deprecated, but not disabled).
Dec 18 2021
On 12/18/21 2:54 PM, Quirin Schroll wrote:On Monday, 15 November 2021 at 14:19:00 UTC, Steven Schveighoffer wrote:You can foreach an appropriately typed delegate too. e.g. ``` struct S { int byKey(int delegate(int) dg) { return 0; } } void main() { S s; foreach(i; &s.byKey) {} foreach_reverse(i; &s.byKey) {} // Deprecated, still iterates forwards } ``` https://run.dlang.io/is/G3KUfl As I said, it's fallen out of style. I used this [in my dcollections library](https://github.com/schveiguy/dcollections/blob/82118cfd4faf3f1ad77df078d279f1b964f274e7/co cepts.txt#L81-L100) though. -SteveOn 11/15/21 7:41 AM, Timon Gehr wrote:Maybe this is older. When I came to D around 2015, I learned that there is `opApply` for forward iteration (`foreach`) and `opApplyReverse` for reverse iteration (`foreach_reverse`). I just tried defining a struct with `opApply`, but no `opApplyReverse`, and then `foreach_reverse` on an instance (on run.dlang.io). Doesn't work.In particular, there is `static foreach_reverse`.Although it's fallen mostly out of style, the reason I hated `foreach_reverse` is because it used to be applicable to delegate iteration, but just iterates forward (I've just checked and it's deprecated, but not disabled).
Dec 21 2021
On Mon, Oct 11, 2021 at 03:59:10PM +0000, Atila Neves via Digitalmars-d wrote:I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy languageFrom languages I know:- C: - Implicit decay of array to pointer. - Null-terminated strings (corruption of your string data == buffer overflow exploit waiting to happen). - Pointer syntax: the `*` grammatically attaches to the identifier rather than the type name, which causes all sorts of totally needless syntactic convolutions like the unreadable function pointer syntax. (Yes, I know how it works, I've been writing them for 20+ years and I know them like the back of my hand; but it is nevertheless a Bad Idea(tm).) Not to mention how easily beginners mess it up. - C++: - Template syntax (using `<>` for template parameters/arguments has got to be the worst syntax choice made in the last 30 years, making C++ unlexible until it's first parsed). - Null-terminated strings (one of the worst things to inherit from C). - Free-for-all, wild-wild-west operator overloading that lets you define, e.g., <, <=, >, >= in completely inconsistent, incompatible ways. Not to mention the amount of boilerplate necessary to implement these operators in a consistent way, leading to more opportunities for human error. - Perl: - Sigils: $x, x, %x refer to different things. Worse yet, $x{y} dereferences %x, not $x, and $x[y] dereferences x rather than $x. (Argh...) (I actually *like* the rationale behind sigils, but the way they're implemented is just ... argh...) - JS: - Dynamic typing. Leads to all kinds of bugs and runtime exceptions that eventually compel you to write checks, that ultimately boil down to reinventing static typing in an ad hoc way. As someone once said, dynamic typing is just static typing with only a single type. - `===` vs `==`. - WAT-eliciting behavior of built-in operators: like `[] + []` producing an empty string, `[] + {}` producing `[object Object]` (which is a *string*, not an actual object!) and `{} + []` producing 0.* Worst features (in your opinion) in D- The integer promotion/casting mess. I understand that C compatibility is very important, but things have seriously gone off the rails when you get things like: ubyte x; x = -x; // compile error - Autodecoding. - Half-baked features like `shared`. It kinda-sorta works, its behaviour is by design, casts are intentional, etc.. But it leaves you with the feeling of incompleteness. It promises thread safety (or at least to help towards that goal), but when you use it you feel like you're given parts of some IKEA furniture without nails, screws, or bolts, which you have to provide on your own (and of course, assembly is also DIY, and if it falls apart it's your fault, not ours). - In the same vein, property. It's been how many years now, when are we going to get a comprehensive solution (or, at the very least, when will this sad creature with missing limbs finally be euthanized for mercy's sake)?* Features you'd like to see in D[...] - C++ concepts-like feature of specifying the expected interface of a template parameter. - Yes, sig constraints fit the bill, kinda-sorta. But it leads to poor, unhelpful error messages. Yes, this can be fixed by using static if, pragma(msg), etc., but this requires a lot of extra work on the part of the user which should have been handled by the language. - Yes, there's a dub package that kinda-sorta does this. But again, this is something that should have been done by the language. - More procedural type manipulations. `static foreach` is great; it eliminated a bunch of cases where you'd need to use recursive templates. It'd be nice to have procedural manipulations of types/aliases/etc. as well. Kinda like Stefan's type functions, but more integrated into the language and streamlined with other D features. Basically, get rid of recursive templates except where they're absolutely, unavoidably, necessary. - More complete outworking of features that require deep language support, like `shared` or property or [insert your favorite half-baked D feature here]. Provide a comprehensive package that actually enables you to get stuff done without having to buy your own nails, your own hammer, and assemble things yourself, and that provide some solid guarantees that doesn't just leave you holding the pieces when things break. - Extend `if (auto x = initializer())` to apply to complex conditions as well, e.g.: if (someClause && (auto x = initializer()) && (auto y = initializer2())) { /* use x and y here */ } T -- Turning your clock 15 minutes ahead won't cure lateness---you're just making time go faster!
Oct 12 2021
On Tuesday, 12 October 2021 at 19:41:57 UTC, H. S. Teoh wrote:- C++ concepts-like feature of specifying the expected interface of a template parameter. - Yes, sig constraints fit the bill, kinda-sorta. But it leads to poor, unhelpful error messages. Yes, this can be fixed by using static if, pragma(msg), etc., but this requires a lot of extra work on the part of the user which should have been handled by the language. - Yes, there's a dub package that kinda-sorta does this. But again, this is something that should have been done by the language.You can get about 90% of the way to better constraint errors with existing language features: struct Check { bool passed; string message; T opCast(T : bool)() { return passed; } } enum hasFoo(T) = Check( __traits(hasMember, T, "foo"), "`" ~ T.stringof ~ "` must have a member named `foo`" ); struct Pass { int foo; } struct Fail { int bar; } // Can check with static assert static assert(hasFoo!Pass); static assert(!hasFoo!Fail); // Works in constraints auto getFoo(T)(T input) if (hasFoo!T) { return input.foo; } static assert(__traits(compiles, Pass().getFoo)); static assert(!__traits(compiles, Fail().getFoo)); // Can check error message pragma(msg, hasFoo!Fail.message); The only thing missing is a way to get the compiler to print out your custom message, instead of (or in addition to) the default "must satisfy `hasFoo!T`" message. I plan to write a DIP for this as soon as I am done with nodiscard.
Oct 12 2021
On Tuesday, 12 October 2021 at 20:29:32 UTC, Paul Backus wrote:On Tuesday, 12 October 2021 at 19:41:57 UTC, H. S. Teoh wrote:templates doesn't work with DCD/DSymbol because it doesn't do semantic analysis, so that kind of features is impossible implement for tooling right now.. this is why things like tagged union (sumtype) and multiple return type should be implemented as language features, that way it is easier to parse (on top of other benefits) please push for language feature! your work on sumtype was great, but there is much more to gain from upgrading it as a language feature- C++ concepts-like feature of specifying the expected interface of a template parameter. - Yes, sig constraints fit the bill, kinda-sorta. But it leads to poor, unhelpful error messages. Yes, this can be fixed by using static if, pragma(msg), etc., but this requires a lot of extra work on the part of the user which should have been handled by the language. - Yes, there's a dub package that kinda-sorta does this. But again, this is something that should have been done by the language.You can get about 90% of the way to better constraint errors with existing language features: struct Check { bool passed; string message; T opCast(T : bool)() { return passed; } } enum hasFoo(T) = Check( __traits(hasMember, T, "foo"), "`" ~ T.stringof ~ "` must have a member named `foo`" ); struct Pass { int foo; } struct Fail { int bar; } // Can check with static assert static assert(hasFoo!Pass); static assert(!hasFoo!Fail); // Works in constraints auto getFoo(T)(T input) if (hasFoo!T) { return input.foo; } static assert(__traits(compiles, Pass().getFoo)); static assert(!__traits(compiles, Fail().getFoo)); // Can check error message pragma(msg, hasFoo!Fail.message); The only thing missing is a way to get the compiler to print out your custom message, instead of (or in addition to) the default "must satisfy `hasFoo!T`" message. I plan to write a DIP for this as soon as I am done with nodiscard.
Oct 12 2021
On Wednesday, 13 October 2021 at 01:56:19 UTC, russhy wrote:this is why things like tagged union (sumtype) and multiple return type should be implemented as language features, that way it is easier to parse (on top of other benefits) please push for language feature! your work on sumtype was great, but there is much more to gain from upgrading it as a language featureIf anyone wants to work on a DIP and implementation for built-in sum types, they will have my full support. Unfortunately, I do not have the time or the skills necessary to lead such a project myself.
Oct 12 2021
On Wednesday, 13 October 2021 at 02:39:47 UTC, Paul Backus wrote:On Wednesday, 13 October 2021 at 01:56:19 UTC, russhy wrote:I think such a feature would benefit from having tuple syntax and semantics done first. Timon did have a DIP for tuples.this is why things like tagged union (sumtype) and multiple return type should be implemented as language features, that way it is easier to parse (on top of other benefits) please push for language feature! your work on sumtype was great, but there is much more to gain from upgrading it as a language featureIf anyone wants to work on a DIP and implementation for built-in sum types, they will have my full support. Unfortunately, I do not have the time or the skills necessary to lead such a project myself.
Oct 12 2021
On Wednesday, 13 October 2021 at 02:39:47 UTC, Paul Backus wrote:On Wednesday, 13 October 2021 at 01:56:19 UTC, russhy wrote:it worth doing the extra kilometer to avoid having the situation we have currently, for yet another std package going easy road for what short term benefits? other languages have tagged union built into the language, same for nullable, it's proven to be very useful std should serve for bigger (missing) purposes - Filesystem package: std.fs - Networking package: std.net - Event Loop package: std.event - Graphics package: std.gfx - Datastructure package: std.collections - Memory package: std.mem not for little things that doesn't have any purpose other than inflating the std with tiny packages that everyone already has implemented in their own "utils" module it's to get issues like this: https://forum.dlang.org/thread/gyzbciyzrywphxbbhdpn forum.dlang.org then even more no..this is why things like tagged union (sumtype) and multiple return type should be implemented as language features, that way it is easier to parse (on top of other benefits) please push for language feature! your work on sumtype was great, but there is much more to gain from upgrading it as a language featureIf anyone wants to work on a DIP and implementation for built-in sum types, they will have my full support. Unfortunately, I do not have the time or the skills necessary to lead such a project myself.
Oct 13 2021
On Thursday, 14 October 2021 at 01:33:59 UTC, russhy wrote:On Wednesday, 13 October 2021 at 02:39:47 UTC, Paul Backus wrote:Sometimes the difference is not between "easy" and "hard", but between "possible" and "impossible". If you have never written a DIP, or contributed to DMD, it is easy to underestimate the amount of work required to add a new language feature to D. I have done both, and I can say with confidence that adding built-in sum types will take *at least* 10x the effort it has taken to get std.sumtype to its current state. I would love for D to have built-in sum types, believe me. But adding them is simply too big a project for a single volunteer like me to take on. If you really want this to happen, I think your best bet is to convince Walter and the D Foundation to make it an official priority, and sponsor someone to work on it.If anyone wants to work on a DIP and implementation for built-in sum types, they will have my full support. Unfortunately, I do not have the time or the skills necessary to lead such a project myself.it worth doing the extra kilometer to avoid having the situation we have currently, for yet another std package going easy road for what short term benefits? other languages have tagged union built into the language, same for nullable, it's proven to be very useful
Oct 13 2021
On Thursday, 14 October 2021 at 02:13:00 UTC, Paul Backus wrote:... If you really want this to happen, I think your best bet is to convince Walter and the D Foundation to make it an official priority, and sponsor someone to work on it.Possibly, in a parallel universe. I guess that kind of goes for most of the suggested language additions though as well which isn't very... comforting.
Oct 13 2021
On Tuesday, 12 October 2021 at 19:41:57 UTC, H. S. Teoh wrote:[snip]I've become more sympathetic to this. The main argument against DIP 1023 (resolution of template alias parameters in template functions) boiled down to "why not use signature constraints." Something like Concepts could be an alternative solution to the problems addressed in that DIP (though that may not be the only way to resolve them). Runtime & static polymorphism comes in different types and flavors. D has class, which is similar to how C++ and Java work (ignoring some details). So we can group these together in a run-time polymorphism. D's interface is similar to that, but doesn't do exactly the same thing and is different from Go's interface and Rust's traits system. Concepts as a form of static polymorphism are in a different category as well. But how do we group the categories in a way that makes sense?* Features you'd like to see in D[...] - C++ concepts-like feature of specifying the expected interface of a template parameter. - Yes, sig constraints fit the bill, kinda-sorta. But it leads to poor, unhelpful error messages. Yes, this can be fixed by using static if, pragma(msg), etc., but this requires a lot of extra work on the part of the user which should have been handled by the language. - Yes, there's a dub package that kinda-sorta does this. But again, this is something that should have been done by the language.
Oct 12 2021
On 10/11/21 5:59 PM, Atila Neves wrote:...This is likely to be incomplete or overly abstract, but here's my approximate take:* Worst features implemented in a non-toy language- unsound type system - undefined behavior for categories of errors other than memory corruption - inappropriately nondeterministic semantics - mutable aliasing by default (mutability is fine, aliasing is the issue) - pointer arithmetic without appropriate type system support - imprecise type system (>40 years behind state of the art) - non-orthogonal language definition - null pointers without appropriate type system support - Turing-complete constructors* Worst features (in your opinion) in D- undefined behavior for categories of errors other than memory corruption, e.g. 'assert' - safe `void` initialization - safe extern(C) function prototypes - inout - nondeterministic floating-point semantics - forward reference errors/ambiguities (arising from underspecification of compile-time introspection) - .init - separation of templates and CTFE - null pointers - Turing-complete constructors - Object - interaction of type qualifiers with reference types - underspecification of type/function qualifiers - template syntax is inconsistent between declaration and call site - alias this (it uses lookup rules different from import) - slicing and indexing of sequences is magic, there is no way to slice a library tuple without decaying into an auto-expanding sequence* Features you'd like to see in D- built-in tuples/products with standard syntax - built-in tagged unions/sums, nullable, algebraic data types - pattern matching - real support for linear/affine typing - named parameters with support for perfect forwarding and compile-time introspection - built-in duck-typed record types playing nice with named parameters - type classes / some standard way to add UFCS methods to a type from another module that are then visible in an instantiated template from a third module - uniform syntax for function definition, in particular `int add(int a,int b)=>a+b;` (-preview=shortenedMethods) - `let Statement in Expression` expression - `Expression where Statement` expression - mixin identifiers - __local, static break and continue (https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1010.md) - template literals - static opIndex/opSlice - AST introspection - consistent treatment of operators for built-in types, e.g. 1.opBinary!"+"(2) should work. - operator overloading should combine orthogonally with UFCS - better support for subtyping (expose the concept to user-defined types, e.g., Range!(const(T)) could be a subtype of const(Range!T)) and any other features required to support a good container library - async/await (or similar) - yield (or similar) - range literals - more lightweight coroutines - ProtoObject - special treatment of qualified types, in particular qualified reference types (e.g. `immutable` classes should allow conversion of references from `immutable` to mutable) - non-deterministic semantics, with as little undefined behavior as possible, in particular for type/function qualifiers - compile-time fixed-point support (e.g., with struct S(T){ T* next; }, fix!S gives a singly linked list). - flow-sensitive typing - strong variable updates (probably not happening) - non-lexical variable lifetimes (probably not happening) - parametric polymorphism, in particular for type qualifiers (probably not happening) - some amount of dependent types (dreaming now)
Oct 12 2021
On Tuesday, 12 October 2021 at 21:38:48 UTC, Timon Gehr wrote:- .initIs the issue default initialization or that the property is named `init`?
Oct 12 2021
On 10/12/21 11:50 PM, surlymoor wrote:On Tuesday, 12 October 2021 at 21:38:48 UTC, Timon Gehr wrote:Uninitialized variables are not an option, so default initialization and/or some flow analysis unfortunately seem to be necessary given the limited nature of D's lexical scoping rules. The issue is that every user-defined type is by default assumed to have a default state. It's null pointers with extra steps. I'm not a big fan of the possibility of accidentally hiding a type's `init` using a user-defined field, but this is a lesser issue and at least this way it can be disabled, though I am not absolutely sure that this completely denies access.- .initIs the issue default initialization or that the property is named `init`?
Oct 12 2021
On Tuesday, 12 October 2021 at 21:50:11 UTC, surlymoor wrote:On Tuesday, 12 October 2021 at 21:38:48 UTC, Timon Gehr wrote:The fact that the default value of a type `T` is `T.init` and `init` isn't even a keyword leading to all the problems it has, when it could have been `default(T)` is really embarrassing.- .initIs the issue default initialization or that the property is named `init`?
Nov 15 2021
On 15.11.21 19:04, Q. Schroll wrote:On Tuesday, 12 October 2021 at 21:50:11 UTC, surlymoor wrote:That's not close to all the problems and at least you can ` disable enum init = 0;` now.On Tuesday, 12 October 2021 at 21:38:48 UTC, Timon Gehr wrote:The fact that the default value of a type `T` is `T.init` and `init` isn't even a keyword leading to all the problems it has, when it could have been `default(T)` is really embarrassing.- .initIs the issue default initialization or that the property is named `init`?
Nov 15 2021
On 10/12/21 11:38 PM, Timon Gehr wrote:- local imports that implicitly hide symbols from outer scopes in current module* Worst features (in your opinion) in D
Oct 12 2021
On Tuesday, 12 October 2021 at 21:38:48 UTC, Timon Gehr wrote:On 10/11/21 5:59 PM, Atila Neves wrote:Please mention the language for each point. I think that "inappropriately nondeterministic semantics" can be JS....This is likely to be incomplete or overly abstract, but here's my approximate take:* Worst features implemented in a non-toy language- unsound type system - undefined behavior for categories of errors other than memory corruption - inappropriately nondeterministic semantics - mutable aliasing by default (mutability is fine, aliasing is the issue) - pointer arithmetic without appropriate type system support - imprecise type system (>40 years behind state of the art) - non-orthogonal language definition - null pointers without appropriate type system support - Turing-complete constructors
Oct 12 2021
On 10/12/2021 2:38 PM, Timon Gehr wrote:- non-lexical variable lifetimes (probably not happening)It's already implemented for live.
Oct 15 2021
On 10/16/21 1:12 AM, Walter Bright wrote:On 10/12/2021 2:38 PM, Timon Gehr wrote:Specifically, I would like it to influence scoping. ```d int x=2; int y=move(x); int z=x; // error: undefined identifier x (was moved away) int y=move(y); // ok ```- non-lexical variable lifetimes (probably not happening)It's already implemented for live.
Nov 09 2021
On Wednesday, 10 November 2021 at 07:09:34 UTC, Timon Gehr wrote:On 10/16/21 1:12 AM, Walter Bright wrote:That would be a good start. I would support that.On 10/12/2021 2:38 PM, Timon Gehr wrote:Specifically, I would like it to influence scoping. ```d int x=2; int y=move(x); int z=x; // error: undefined identifier x (was moved away) int y=move(y); // ok ```- non-lexical variable lifetimes (probably not happening)It's already implemented for live.
Nov 10 2021
On Wednesday, 10 November 2021 at 14:15:58 UTC, Stefan Koch wrote:On Wednesday, 10 November 2021 at 07:09:34 UTC, Timon Gehr wrote:Yeah, that would be lovely.Specifically, I would like it to influence scoping. ```d int x=2; int y=move(x); int z=x; // error: undefined identifier x (was moved away) int y=move(y); // ok ```That would be a good start. I would support that.
Nov 10 2021
On Wed, Nov 10, 2021 at 02:17:28PM +0000, Sebastiaan Koppe via Digitalmars-d wrote:On Wednesday, 10 November 2021 at 14:15:58 UTC, Stefan Koch wrote:That would allow a better implementation of ownership tracking. T -- People walk. Computers run.On Wednesday, 10 November 2021 at 07:09:34 UTC, Timon Gehr wrote:Yeah, that would be lovely.Specifically, I would like it to influence scoping. ```d int x=2; int y=move(x); int z=x; // error: undefined identifier x (was moved away) int y=move(y); // ok ```That would be a good start. I would support that.
Nov 10 2021
On Wednesday, 10 November 2021 at 17:05:20 UTC, H. S. Teoh wrote:On Wed, Nov 10, 2021 at 02:17:28PM +0000, Sebastiaan Koppe via Digitalmars-d wrote:Other way around. It requires better compiler ownership tracking.On Wednesday, 10 November 2021 at 14:15:58 UTC, Stefan Koch wrote:That would allow a better implementation of ownership tracking. TOn Wednesday, 10 November 2021 at 07:09:34 UTC, Timon Gehr wrote:Yeah, that would be lovely.Specifically, I would like it to influence scoping. ```d int x=2; int y=move(x); int z=x; // error: undefined identifier x (was moved away) int y=move(y); // ok ```That would be a good start. I would support that.
Nov 10 2021
On Wed, Nov 10, 2021 at 05:55:47PM +0000, Stefan Koch via Digitalmars-d wrote:On Wednesday, 10 November 2021 at 17:05:20 UTC, H. S. Teoh wrote:[...]On Wed, Nov 10, 2021 at 02:17:28PM +0000, Sebastiaan Koppe via Digitalmars-d wrote:On Wednesday, 10 November 2021 at 14:15:58 UTC, Stefan Koch wrote:That would allow a better implementation of ownership tracking.On Wednesday, 10 November 2021 at 07:09:34 UTC, Timon Gehr >wrote:Yeah, that would be lovely.Specifically, I would like it to influence scoping.int x=2; int y=move(x); int z=x; // error: undefined identifier x (was moved away)```d``` That would be a good start. I would support that.int y=move(y); // okOther way around. It requires better compiler ownership tracking.That's what I meant. :D If the compiler has this tracking, then it becomes possible to implement a simple ownership-tracking pointer wrapper type in user code. T -- Stop staring at me like that! It's offens... no, you'll hurt your eyes!
Nov 10 2021
On 11/9/2021 11:09 PM, Timon Gehr wrote:On 10/16/21 1:12 AM, Walter Bright wrote:live currently does that for pointers, but not for non-pointers. What's the use case for it?On 10/12/2021 2:38 PM, Timon Gehr wrote:Specifically, I would like it to influence scoping. ```d int x=2; int y=move(x); int z=x; // error: undefined identifier x (was moved away)- non-lexical variable lifetimes (probably not happening)It's already implemented for live.int y=move(y); // ok ```I see what you mean, but since D disallows: int x; { int x; } which prevents a number of bugs, so I can't see allowing that.
Dec 28 2021
On Wednesday, 29 December 2021 at 05:09:33 UTC, Walter Bright wrote:On 11/9/2021 11:09 PM, Timon Gehr wrote:The typestate [1] design pattern. In languages that support some form of affine types [2] like Rust (*), this design pattern can be used to prevent classes of programmer errors at compile-time, while the best C++ and D can do is use `assert` at run-time to facilitate detecting them. Here's a few articles that showcase this in Rust: * https://cliffle.com/blog/rust-typestate/ * https://rustype.github.io/notes/notes/rust-typestate-series/rust-typestate-part-1 * https://docs.rs/typestate/latest/typestate/ (*) Technically, affine types are about using a variable at most once. In Rust, if a type doesn't implement the Copy / Clone traits [3], variables of that type have move semantics - that is, they can't be used after they have been passed to a function that takes them by value (passing ownership). But they can be still passed multiple times to functions take them by reference (borrowing). [1]: https://en.wikipedia.org/wiki/Typestate_analysis [2]: https://en.wikipedia.org/wiki/Substructural_type_system [3]: https://doc.rust-lang.org/std/marker/trait.Copy.htmlOn 10/16/21 1:12 AM, Walter Bright wrote:live currently does that for pointers, but not for non-pointers. What's the use case for it?On 10/12/2021 2:38 PM, Timon Gehr wrote:Specifically, I would like it to influence scoping. ```d int x=2; int y=move(x); int z=x; // error: undefined identifier x (was moved away)- non-lexical variable lifetimes (probably not happening)It's already implemented for live.
Dec 29 2021
On 12/29/2021 12:10 AM, Petar Kirov [ZombineDev] wrote:The typestate [1] design pattern. In languages that support some form of affine types [2] like Rust (*), this design pattern can be used to prevent classes of programmer errors at compile-time, while the best C++ and D can do is use `assert` at run-time to facilitate detecting them. Here's a few articles that showcase this in Rust: * https://cliffle.com/blog/rust-typestate/ * https://rustype.github.io/notes/notes/rust-typestate-series/rust-typestate-part-1 * https://docs.rs/typestate/latest/typestate/ (*) Technically, affine types are about using a variable at most once. In Rust, if a type doesn't implement the Copy / Clone traits [3], variables of that type have move semantics - that is, they can't be used after they have been passed to a function that takes them by value (passing ownership). But they can be still passed multiple times to functions take them by reference (borrowing). [1]: https://en.wikipedia.org/wiki/Typestate_analysis [2]: https://en.wikipedia.org/wiki/Substructural_type_system [3]: https://doc.rust-lang.org/std/marker/trait.Copy.htmlThanks, I did not know that.
Jan 07 2022
On 29.12.21 06:09, Walter Bright wrote:On 11/9/2021 11:09 PM, Timon Gehr wrote:It removes the variable from the scope? (And anyway, live is a function annotation, which makes little sense.)On 10/16/21 1:12 AM, Walter Bright wrote:live currently does that for pointers, but not for non-pointers.On 10/12/2021 2:38 PM, Timon Gehr wrote:Specifically, I would like it to influence scoping. ```d int x=2; int y=move(x); int z=x; // error: undefined identifier x (was moved away)- non-lexical variable lifetimes (probably not happening)It's already implemented for live.What's the use case for it? ...This is just how moving things works. If you move it, it's no longer where it was. If the variable disappears, we don't have to bother with putting `x` into some safe default state. Some types can't even naturally support a safe default state. The simplest example is indeed a `struct` implementing a unique non-null pointer managing its own memory. (By whatever means you want, it does not even have to have any pointer members to implement such semantics.)I don't see how that's related. It's two variables `y` whose lifetimes do not overlap. It's more like this: {int x; } { int x; } Which D allows.int y=move(y); // ok ```I see what you mean, but since D disallows: int x; { int x; } which prevents a number of bugs, so I can't see allowing that.
Jan 03 2022
On 1/3/2022 8:30 PM, Timon Gehr wrote:On 29.12.21 06:09, Walter Bright wrote:live applies to all the contents of the function. `scope` is ignored for non-pointer variables, whether they are live or not.live currently does that for pointers, but not for non-pointers.It removes the variable from the scope? (And anyway, live is a function annotation, which makes little sense.)You are pedantically correct, but it's one of those things that would be disallowed because it *looks* like a bug. There's no ambiguity to int x; { int x; } either, it just *looks* like a bug, and a good chunk of the time it is not intended by the user and is a bug. I haven't seen a case yet where such code is needed. I don't see a necessity to allow the y redeclaration.What's the use case for it? ...This is just how moving things works. If you move it, it's no longer where it was. If the variable disappears, we don't have to bother with putting `x` into some safe default state. Some types can't even naturally support a safe default state. The simplest example is indeed a `struct` implementing a unique non-null pointer managing its own memory. (By whatever means you want, it does not even have to have any pointer members to implement such semantics.)I don't see how that's related. It's two variables `y` whose lifetimes do not overlap. It's more like this: {int x; } { int x; } Which D allows.int y=move(y); // ok ```I see what you mean, but since D disallows: int x; { int x; } which prevents a number of bugs, so I can't see allowing that.
Jan 07 2022
On 1/8/22 02:01, Walter Bright wrote:On 1/3/2022 8:30 PM, Timon Gehr wrote:And none of the calling context. As I said, makes little sense.On 29.12.21 06:09, Walter Bright wrote:live applies to all the contents of the function. ...live currently does that for pointers, but not for non-pointers.It removes the variable from the scope? (And anyway, live is a function annotation, which makes little sense.)`scope` is ignored for non-pointer variables, whether they are live or not. ...The language can't know what's designed to act like a pointer.Perhaps that's what it looks like to you, but to other people it just looks like the typestate pattern, for example.You are pedantically correct, but it's one of those things that would be disallowed because it *looks* like a bug.What's the use case for it? ...This is just how moving things works. If you move it, it's no longer where it was. If the variable disappears, we don't have to bother with putting `x` into some safe default state. Some types can't even naturally support a safe default state. The simplest example is indeed a `struct` implementing a unique non-null pointer managing its own memory. (By whatever means you want, it does not even have to have any pointer members to implement such semantics.)I don't see how that's related. It's two variables `y` whose lifetimes do not overlap. It's more like this: {int x; } { int x; } Which D allows.int y=move(y); // ok ```I see what you mean, but since D disallows: int x; { int x; } which prevents a number of bugs, so I can't see allowing that.There's no ambiguity to int x; { int x; } either, it just *looks* like a bug, and a good chunk of the time it is not intended by the user and is a bug. I haven't seen a case yet where such code is needed. ...I fully agree that variable hiding is error prone, but that's just not what's going on here.I don't see a necessity to allow the y redeclaration._Redeclaring_ an _existing_ variable is of course disallowed. Declaring a variable of the same name as one that's consumed in its initializer is rather common (e.g. typestate pattern). And it is convenient and not error prone at all.
Jan 09 2022
On 16.10.21 01:12, Walter Bright wrote:On 10/12/2021 2:38 PM, Timon Gehr wrote:(Also, I want it based on the types of the involved values, not based on a non-modular function annotation.)- non-lexical variable lifetimes (probably not happening)It's already implemented for live.
Nov 14 2021
On Tuesday, 12 October 2021 at 21:38:48 UTC, Timon Gehr wrote:On 10/11/21 5:59 PM, Atila Neves wrote:Care to explain?...This is likely to be incomplete or overly abstract, but here's my approximate take:* Worst features implemented in a non-toy language- Turing-complete constructors- safe `void` initializationFor what types? It doesn't compile for pointers, for instance, and I don't see why void initialising an int would be unsafe.- safe extern(C) function prototypesInstead of trusted, you mean?- .initBecause?- separation of templates and CTFEWhat would it look like if they weren't separated?- interaction of type qualifiers with reference typesI'd love to know what you mean by this.
Nov 05 2021
On Friday, 5 November 2021 at 17:02:05 UTC, Atila Neves wrote:Well, I can't answer for him but `void` initialization and `.init` makes it impossible to have any meaningful constraint on a type. And some types may depend on these constraints to maintain safety. ```d import std.stdio; struct LimitedInt(int min, int max) { disable this(); this(int number) { assert(number >= min); assert(number <= max); _number = number; } private int _number; } void main() safe { LimitedInt!(1, 1000) x = void; auto y = LimitedInt!(1, 1000).init; writeln(x); writeln(y); } ``` It's ` safe` in this example but there's no way to enforce these constraints when you have those.- safe `void` initializationFor what types? It doesn't compile for pointers, for instance, and I don't see why void initialising an int would be unsafe.- .initBecause?
Nov 05 2021
On Fri, Nov 05, 2021 at 09:22:12PM +0000, victoroak via Digitalmars-d wrote:On Friday, 5 November 2021 at 17:02:05 UTC, Atila Neves wrote:safe does not mean enforcing type constraints. It means *memory* safety. The above code exhibits no memory unsafety, even though constraints are violated and the output is, ostensibly, wrong because of broken constraints. T -- There are four kinds of lies: lies, damn lies, and statistics.Well, I can't answer for him but `void` initialization and `.init` makes it impossible to have any meaningful constraint on a type. And some types may depend on these constraints to maintain safety. ```d import std.stdio; struct LimitedInt(int min, int max) { disable this(); this(int number) { assert(number >= min); assert(number <= max); _number = number; } private int _number; } void main() safe { LimitedInt!(1, 1000) x = void; auto y = LimitedInt!(1, 1000).init; writeln(x); writeln(y); } ``` It's ` safe` in this example but there's no way to enforce these constraints when you have those.- safe `void` initializationFor what types? It doesn't compile for pointers, for instance, and I don't see why void initialising an int would be unsafe.- .initBecause?
Nov 05 2021
On Friday, 5 November 2021 at 21:46:35 UTC, H. S. Teoh wrote:safe does not mean enforcing type constraints. It means *memory* safety. The above code exhibits no memory unsafety, even though constraints are violated and the output is, ostensibly, wrong because of broken constraints.`.init` was not mentioned as breaking ` safe` just as a bad feature and I was answering why I think it is a bad feature. But the presence of both `.init` and safe `void` initialization makes it way harder to write correct ` trusted` code that depends on some constraints because you can't really enforce them.
Nov 05 2021
On Friday, 5 November 2021 at 21:54:27 UTC, victoroak wrote:On Friday, 5 November 2021 at 21:46:35 UTC, H. S. Teoh wrote:...which is one of the reasons we need system variables: https://github.com/dlang/DIPs/blob/master/DIPs/DIP1035.mdsafe does not mean enforcing type constraints. It means *memory* safety. The above code exhibits no memory unsafety, even though constraints are violated and the output is, ostensibly, wrong because of broken constraints.`.init` was not mentioned as breaking ` safe` just as a bad feature and I was answering why I think it is a bad feature. But the presence of both `.init` and safe `void` initialization makes it way harder to write correct ` trusted` code that depends on some constraints because you can't really enforce them.
Nov 05 2021
On Friday, 5 November 2021 at 21:22:12 UTC, victoroak wrote:On Friday, 5 November 2021 at 17:02:05 UTC, Atila Neves wrote:Interesting. Adding an invariant causes compilation to fail: ``` foo.d(27): Error: variable `foo.main.x` `void` initializers for structs with invariants are not allowed in safe functions ```Well, I can't answer for him but `void` initialization and `.init` makes it impossible to have any meaningful constraint on a type. And some types may depend on these constraints to maintain safety. ```d import std.stdio; struct LimitedInt(int min, int max) { disable this(); this(int number) { assert(number >= min); assert(number <= max); _number = number; } private int _number; } void main() safe { LimitedInt!(1, 1000) x = void; auto y = LimitedInt!(1, 1000).init; writeln(x); writeln(y); } ``` It's ` safe` in this example but there's no way to enforce these constraints when you have those.- safe `void` initializationFor what types? It doesn't compile for pointers, for instance, and I don't see why void initialising an int would be unsafe.- .initBecause?
Nov 08 2021
On 08.11.21 15:04, Atila Neves wrote:On Friday, 5 November 2021 at 21:22:12 UTC, victoroak wrote:Well, that makes some sense, but a struct can have an invariant without actually having it spelled out explicitly in the source code. Furthermore, adding contracts actually makes code less safe in -release mode.On Friday, 5 November 2021 at 17:02:05 UTC, Atila Neves wrote:Interesting. Adding an invariant causes compilation to fail: ``` foo.d(27): Error: variable `foo.main.x` `void` initializers for structs with invariants are not allowed in safe functions ```Well, I can't answer for him but `void` initialization and `.init` makes it impossible to have any meaningful constraint on a type. And some types may depend on these constraints to maintain safety. ```d import std.stdio; struct LimitedInt(int min, int max) { disable this(); this(int number) { assert(number >= min); assert(number <= max); _number = number; } private int _number; } void main() safe { LimitedInt!(1, 1000) x = void; auto y = LimitedInt!(1, 1000).init; writeln(x); writeln(y); } ``` It's ` safe` in this example but there's no way to enforce these constraints when you have those.- safe `void` initializationFor what types? It doesn't compile for pointers, for instance, and I don't see why void initialising an int would be unsafe.- .initBecause?
Nov 09 2021
On Tuesday, 9 November 2021 at 16:37:37 UTC, Timon Gehr wrote:On 08.11.21 15:04, Atila Neves wrote:IMHO -release mode really shouldn't be used, but since contracts are supposed to prevent bugs from occurring, hopefully testing "proved" that "none" exist. In this case specifically, even with -release one gets a compiler error, which is enough of a reason to add one methinks.On Friday, 5 November 2021 at 21:22:12 UTC, victoroak wrote:Well, that makes some sense, but a struct can have an invariant without actually having it spelled out explicitly in the source code. Furthermore, adding contracts actually makes code less safe in -release mode.[...]Interesting. Adding an invariant causes compilation to fail: ``` foo.d(27): Error: variable `foo.main.x` `void` initializers for structs with invariants are not allowed in safe functions ```
Nov 09 2021
On 09.11.21 18:13, Atila Neves wrote:On Tuesday, 9 November 2021 at 16:37:37 UTC, Timon Gehr wrote:"Add an empty invariant to your types for maximum type safety", "we have constructors, but your types have to cope with arbitrary bit patterns anyway" or "this thing is safe but some compiler backends may treat it as UB anyway" are The Last Thing D Needs.On 08.11.21 15:04, Atila Neves wrote:IMHO -release mode really shouldn't be used, but since contracts are supposed to prevent bugs from occurring, hopefully testing "proved" that "none" exist. In this case specifically, even with -release one gets a compiler error, which is enough of a reason to add one methinks.On Friday, 5 November 2021 at 21:22:12 UTC, victoroak wrote:Well, that makes some sense, but a struct can have an invariant without actually having it spelled out explicitly in the source code. Furthermore, adding contracts actually makes code less safe in -release mode.[...]Interesting. Adding an invariant causes compilation to fail: ``` foo.d(27): Error: variable `foo.main.x` `void` initializers for structs with invariants are not allowed in safe functions ```
Nov 10 2021
On Thursday, 11 November 2021 at 02:20:50 UTC, Timon Gehr wrote:"Add an empty invariant to your types for maximum type safety", "we have constructors, but your types have to cope with arbitrary bit patterns anyway" or "this thing is safe but some compiler backends may treat it as UB anyway" are The Last Thing D Needs.This is unfortunately true. This is pervasive in D and by far the biggest practical problem with it.
Dec 17 2021
On 11/5/21 6:02 PM, Atila Neves wrote:On Tuesday, 12 October 2021 at 21:38:48 UTC, Timon Gehr wrote:Sorry, just noticed I never answered this...On 10/11/21 5:59 PM, Atila Neves wrote:......The goal of construction is to create an instance that usually should satisfy a certain invariant. (I don't necessarily mean invariant contracts, often invariants are left implicit.) Therefore, to construct an instance, all that needs to happen is input validation and moving the constructor arguments into the fields of the instance. Right now, constructors first get you some instance _that does not yet satisfy the invariant_ and basically allows you to do anything you want with it. That's quite a drag on type safety. (E.g., good luck adding non-null pointers.) ```d struct S{ immutable int x; this(int x){ foo(); this.x=1; foo(); } void foo(){ writeln(x); } } ``` There just should not be a way to obtain instances that violate (type system) invariants. I think Walter agrees that the constructor design is not optimal, especially regarding exception safety.This is likely to be incomplete or overly abstract, but here's my approximate take:Care to explain? ...* Worst features implemented in a non-toy language- Turing-complete constructorsThe backends may treat accessing it as UB. I'd expect both ldc and gdc to think accessing a void-initialized value is UB. The worst thing is safe void initialization for user-defined types.- safe `void` initializationFor what types? It doesn't compile for pointers, for instance, and I don't see why void initialising an int would be unsafe. ...Yes, at least with trusted you can find it with grep. Slapping safe on something should never be dangerous.- safe extern(C) function prototypesInstead of trusted, you mean? ...It's Hoare's billion dollar mistake, extended to all types. Having a default instance is often antithetical to strong invariants. At least it can be hidden I guess.- .initBecause? ...Stefan's type functions come close. (But I'd like to have dependent types as well.) E.g., manipulating arrays of types in CTFE functions.- separation of templates and CTFEWhat would it look like if they weren't separated? ...The most obvious one is that there is no way to declare a tail-mutable class reference. There's also this: ```d import std.stdio; class C{ static x = [1,2,3]; this(){ x[0]=2; } this()immutable{} } void main(){ auto a=new immutable(C)(); writeln(a.x); // [1,2,3] auto b=new C(); writeln(a.x); // [2,2,3] } ```- interaction of type qualifiers with reference typesI'd love to know what you mean by this.
Nov 10 2021
On Thursday, 11 November 2021 at 00:26:06 UTC, Timon Gehr wrote:On 11/5/21 6:02 PM, Atila Neves wrote:I don't see how ```.init``` is related to null as long as you can disable default construction? That said, I find ```.init``` annoying and want to see it adjusted (zero default across the board for fast array initialization + user provided default constructor).On Tuesday, 12 October 2021 at 21:38:48 UTC, Timon Gehr wrote:It's Hoare's billion dollar mistake, extended to all types. Having a default instance is often antithetical to strong invariants. At least it can be hidden I guess.- .initBecause? ...
Nov 11 2021
On Tuesday, 12 October 2021 at 21:38:48 UTC, Timon Gehr wrote:On 10/11/21 5:59 PM, Atila Neves wrote:could you give example what those would be like?...This is likely to be incomplete or overly abstract, but here's my approximate take:* Worst features implemented in a non-toy language- unsound type system - undefined behavior for categories of errors other than memory corruption - inappropriately nondeterministic semantics - mutable aliasing by default (mutability is fine, aliasing is the issue) - pointer arithmetic without appropriate type system support - imprecise type system (>40 years behind state of the art) - non-orthogonal language definition - null pointers without appropriate type system support - Turing-complete constructors* Worst features (in your opinion) in D- undefined behavior for categories of errors other than memory corruption, e.g. 'assert' - safe `void` initialization - safe extern(C) function prototypes - inout - nondeterministic floating-point semantics - forward reference errors/ambiguities (arising from underspecification of compile-time introspection) - .init - separation of templates and CTFE - null pointers - Turing-complete constructors - Object - interaction of type qualifiers with reference types - underspecification of type/function qualifiers - template syntax is inconsistent between declaration and call site - alias this (it uses lookup rules different from import) - slicing and indexing of sequences is magic, there is no way to slice a library tuple without decaying into an auto-expanding sequence* Features you'd like to see in D- built-in tuples/products with standard syntax - built-in tagged unions/sums, nullable, algebraic data types - pattern matching - real support for linear/affine typing - named parameters with support for perfect forwarding and compile-time introspection - built-in duck-typed record types playing nice with named parameters - type classes / some standard way to add UFCS methods to a type from another module that are then visible in an instantiated template from a third module - uniform syntax for function definition, in particular `int add(int a,int b)=>a+b;` (-preview=shortenedMethods) - `let Statement in Expression` expression - `Expression where Statement` expression- mixin identifiersexample?- __local, static break and continuewhat would __local do?(https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1010.md) - template literalsexample?- static opIndex/opSlice - AST introspection - consistent treatment of operators for built-in types, e.g. 1.opBinary!"+"(2) should work. - operator overloading should combine orthogonally with UFCS - better support for subtyping (expose the concept to user-defined types, e.g., Range!(const(T)) could be a subtype of const(Range!T)) and any other features required to support a good container library - async/await (or similar) - yield (or similar) - range literalswhat's that?- more lightweight coroutines - ProtoObject - special treatment of qualified types, in particular qualified reference types (e.g. `immutable` classes should allow conversion of references from `immutable` to mutable) - non-deterministic semantics, with as little undefined behavior as possible, in particular for type/function qualifiers - compile-time fixed-point support (e.g., with struct S(T){ T* next; }, fix!S gives a singly linked list). - flow-sensitive typingwhat's that?- strong variable updates (probably not happening)what's that?- non-lexical variable lifetimes (probably not happening) - parametric polymorphism, in particular for type qualifiers (probably not happening) - some amount of dependent types (dreaming now)you got very nice features, are you making DIPs for those?
Nov 14 2021
On 14.11.21 22:54, Dr Machine Code wrote:On Tuesday, 12 October 2021 at 21:38:48 UTC, Timon Gehr wrote:auto (a,b) = (1,2); (int a, string b) = fetch!((x)=>(1,text(x))); [(1,2),(3,4)].map!((a,b)=>a+b).each!writeln;On 10/11/21 5:59 PM, Atila Neves wrote:......* Features you'd like to see in D- built-in tuples/products with standard syntaxNot sure about detailed syntax, maybe something like: (int+string) x = inj(0,1); (int+string) y = inj(1,"hi");- built-in tagged unions/sums,nullable,Maybe: int*? x=null; writeln(*x); // error if(x) writeln(*x); // ok C? x = ...; D? = x?.method();algebraic data typesMaybe: enum Result(T){ Ok(T), Error(string) }auto x = match(r){ Ok(0) => 3; Ok(x) => x+1; Error(_): assert(0); } int toInt((int+string) x) match(x){ (0, x): return x; (1, s): return to!int(s); } }- pattern matchingauto x = S(); auto y = move(x); auto z = x; // error: undefined identifier x auto y = move(y); // ok // error: y was not explicitly moved away or destroyed- real support for linear/affine typingvoid foo(int x=0,int y=0,int z=0; foo(x: 100, z: 200); auto apply(alias f,T...)(T args){ return f(args); } apply!foo(x: 100, z: 200);- named parameters with support for perfect forwarding and compile-time introspectionauto r = (x: 100, z: 200); foo(r);- built-in duck-typed record types playing nice with named parametersimport a: S; import b: rangeFun; auto ref front(ref S s){ ... } bool empty(ref S s){ ... } void popFront(){ ... } void main(){ S s; rangeFun(s with(front, empty, popFront)); alias T=S with (front,empty,popFront); T t=s; rangeFun(t); }- type classes / some standard way to add UFCS methods to a type from another module that are then visible in an instantiated template from a third moduleint add(int a,int b)=>a+b;- uniform syntax for function definition, in particular `int add(int a,int b)=>a+b;` (-preview=shortenedMethods)void main(){ auto z = { int x=1; int y=2; } in x+y; assert(z==3); }- `let Statement in Expression` expressionvoid main(){ auto z = x+y where{ int x=1; int y=2; }; assert(z==3); }- `Expression where Statement` expression...could you give example what those would be like? ...See above. Unfortunately I only had time to give some contrived examples.static foreach((name, value);[("x",1),("y",2),("z",3)]){ int mixin(name) = value; } writeln(x," ",y," ",z); // 1 2 3- mixin identifiersexample?static foreach(i;0..100){ __local alias X=Foo!(T[i]); // local to static foreach, does not clash between iterations mixin Bar!X; }- __local, static break and continuewhat would __local do? ...Also see the explanation in the DIP.(https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1010.md)enum sizes = staticMap!((B)!=>B.sizeof,Types);- template literalsexample?auto b = (fun(x) for x in iota(100) if bar(x)); // equivalent to: // auto b = iota(100).filter!(x=>bar(x)).map!(x=>fun(x));- static opIndex/opSlice - AST introspection - consistent treatment of operators for built-in types, e.g. 1.opBinary!"+"(2) should work. - operator overloading should combine orthogonally with UFCS - better support for subtyping (expose the concept to user-defined types, e.g., Range!(const(T)) could be a subtype of const(Range!T)) and any other features required to support a good container library - async/await (or similar) - yield (or similar) - range literalswhat's that?class A{ void foo(){ ... } } class B:A{ void bar(){ ... } } void foo(A a){ if(a is B){ B b=a; // ok a.bar(); // ok } }- more lightweight coroutines - ProtoObject - special treatment of qualified types, in particular qualified reference types (e.g. `immutable` classes should allow conversion of references from `immutable` to mutable) - non-deterministic semantics, with as little undefined behavior as possible, in particular for type/function qualifiers - compile-time fixed-point support (e.g., with struct S(T){ T* next; }, fix!S gives a singly linked list). - flow-sensitive typingwhat's that?int x=2; x="123"; static assert(is(typeof(x)==string)); auto f=File(x,"r"); static assert(is(typeof(f)==File)); f.close(); static assert(is(typeof(f)==ClosedFile));- strong variable updates (probably not happening)what's that?I started this: https://github.com/tgehr/DIPs/blob/tuple-syntax/DIPs/DIP1xxx-tg.md https://github.com/tgehr/dmd/commits/tuple-syntax Unfortunately, I was too busy at the time to finish the implementation, and I am not fully satisfied with the proposal. Probably I'd want to add at least static opIndex and static opSlice to it. Another issue is that it slightly expands `alias this` and I am not sure whether that's a direction Walter is willing to invest in at this point.- non-lexical variable lifetimes (probably not happening) - parametric polymorphism, in particular for type qualifiers (probably not happening) - some amount of dependent types (dreaming now)you got very nice features, are you making DIPs for those?
Nov 14 2021
On Sunday, 14 November 2021 at 23:05:03 UTC, Timon Gehr wrote:On 14.11.21 22:54, Dr Machine Code wrote:...On Tuesday, 12 October 2021 at 21:38:48 UTC, Timon Gehr wrote:On 10/11/21 5:59 PM, Atila Neves wrote:......* Features you'd like to see in D- built-in tuples/products with standard syntaxI started this: https://github.com/tgehr/DIPs/blob/tuple-syntax/DIPs/DIP1xxx-tg.md https://github.com/tgehr/dmd/commits/tuple-syntax Unfortunately, I was too busy at the time to finish the implementation, and I am not fully satisfied with the proposal. Probably I'd want to add at least static opIndex and static opSlice to it. Another issue is that it slightly expands `alias this` and I am not sure whether that's a direction Walter is willing to invest in at this point.Just WOW. What would be needed to get you working on this again?
Nov 15 2021
On 15.11.21 09:01, Arjan wrote:Some reassurance that it won't be shot down for stupid reasons would go a long way. For `static foreach`, the desired semantics were clear to Walter and Andrei from the start and they really wanted that feature in DMD, so that the DIP process went pretty smoothly. I am not feeling any similar excitement for tuples, even though it's the most wanted feature among forum readers according to the state of D 2018 survey... I just don't have the time and energy required for week-long forum debates anymore.I started this: https://github.com/tgehr/DIPs/blob/tuple-syntax/DIPs/DIP1xxx-tg.md https://github.com/tgehr/dmd/commits/tuple-syntax Unfortunately, I was too busy at the time to finish the implementation, and I am not fully satisfied with the proposal. Probably I'd want to add at least static opIndex and static opSlice to it. Another issue is that it slightly expands `alias this` and I am not sure whether that's a direction Walter is willing to invest in at this point.Just WOW. What would be needed to get you working on this again?
Nov 15 2021
On Tuesday, 16 November 2021 at 02:14:22 UTC, Timon Gehr wrote:On 15.11.21 09:01, Arjan wrote:The proposition at that time was stalled because it collided with the comma expression and it was convened that the comma operator would have to be removed before tuple syntax could be introduced. Now that comma operator is deprecated, it would be the right time to reintroduce the tuple syntax.Some reassurance that it won't be shot down for stupid reasons would go a long way. For `static foreach`, the desired semantics were clear to Walter and Andrei from the start and they really wanted that feature in DMD, so that the DIP process went pretty smoothly. I am not feeling any similar excitement for tuples, even though it's the most wanted feature among forum readers according to the state of D 2018 survey... I just don't have the time and energy required for week-long forum debates anymore.I started this: https://github.com/tgehr/DIPs/blob/tuple-syntax/DIPs/DIP1xxx-tg.md https://github.com/tgehr/dmd/commits/tuple-syntax Unfortunately, I was too busy at the time to finish the implementation, and I am not fully satisfied with the proposal. Probably I'd want to add at least static opIndex and static opSlice to it. Another issue is that it slightly expands `alias this` and I am not sure whether that's a direction Walter is willing to invest in at this point.Just WOW. What would be needed to get you working on this again?
Nov 17 2021
On Tuesday, 16 November 2021 at 02:14:22 UTC, Timon Gehr wrote:On 15.11.21 09:01, Arjan wrote:I don't see any good reason to shut it down, never mind stupid reasons.Some reassurance that it won't be shot down for stupid reasons would go a long way. For `static foreach`, the desired semantics were clear to Walter and Andrei from the start and they really wanted that feature in DMD, so that the DIP process went pretty smoothly. I am not feeling any similar excitement for tuples, even though it's the most wanted feature among forum readers according to the state of D 2018 survey... I just don't have the time and energy required for week-long forum debates anymore.[...]Just WOW. What would be needed to get you working on this again?
Nov 23 2021
On 23.11.21 14:41, Atila Neves wrote:On Tuesday, 16 November 2021 at 02:14:22 UTC, Timon Gehr wrote:There are some details such as ABI and sizeof(()). I'll probably get back to this by January. (Some other commitments will have ended by then.)On 15.11.21 09:01, Arjan wrote:I don't see any good reason to shut it down, never mind stupid reasons.Some reassurance that it won't be shot down for stupid reasons would go a long way. For `static foreach`, the desired semantics were clear to Walter and Andrei from the start and they really wanted that feature in DMD, so that the DIP process went pretty smoothly. I am not feeling any similar excitement for tuples, even though it's the most wanted feature among forum readers according to the state of D 2018 survey... I just don't have the time and energy required for week-long forum debates anymore.[...]Just WOW. What would be needed to get you working on this again?
Nov 23 2021
On Wednesday, 24 November 2021 at 05:29:54 UTC, Timon Gehr wrote:On 23.11.21 14:41, Atila Neves wrote:That will be highly appreciated. Is there anything we could do to help you? Can I buy you a coffee/pizza/beer/scotch/.. ?On Tuesday, 16 November 2021 at 02:14:22 UTC, Timon Gehr wrote:There are some details such as ABI and sizeof(()). I'll probably get back to this by January. (Some other commitments will have ended by then.)[...]I don't see any good reason to shut it down, never mind stupid reasons.
Nov 24 2021
On 11/15/2021 6:14 PM, Timon Gehr wrote:Some reassurance that it won't be shot down for stupid reasons would go a long way. For `static foreach`, the desired semantics were clear to Walter and Andrei from the start and they really wanted that feature in DMD, so that the DIP process went pretty smoothly. I am not feeling any similar excitement for tuples, even though it's the most wanted feature among forum readers according to the state of D 2018 survey... I just don't have the time and energy required for week-long forum debates anymore.Actually, I agree with the need for tuples, and am very open to a good design for it.
Dec 28 2021
On Wednesday, 29 December 2021 at 05:14:43 UTC, Walter Bright wrote:On 11/15/2021 6:14 PM, Timon Gehr wrote:Sorry if this sounds very naive, but if we can't use the `struct` ABI for tuples, why don't we use the `class` ABI? Yeah, reference types are undesirable, but it sounds like a very viable placeholder until we think of a better implementation.Some reassurance that it won't be shot down for stupid reasons would go a long way. For `static foreach`, the desired semantics were clear to Walter and Andrei from the start and they really wanted that feature in DMD, so that the DIP process went pretty smoothly. I am not feeling any similar excitement for tuples, even though it's the most wanted feature among forum readers according to the state of D 2018 survey... I just don't have the time and energy required for week-long forum debates anymore.Actually, I agree with the need for tuples, and am very open to a good design for it.
Dec 28 2021
On 12/28/2021 9:14 PM, Walter Bright wrote:Actually, I agree with the need for tuples, and am very open to a good design for it.I'd like to see something that unified arrays, structs, argument lists (for functions).
Dec 28 2021
On Wednesday, 29 December 2021 at 06:48:11 UTC, Walter Bright wrote:On 12/28/2021 9:14 PM, Walter Bright wrote:I think we should unify static arrays and tuples, and call it a day. A tuple or a static array still would not be the same as an argument list, but could be easily converted to one with `.expand`, just like the present-day tuple. As for `struct`s, I think it's better they're not interchangeable with other types by default. One reason is that we still want that overloads like this are possible: ```d void setBackgroundColour(RGB colour); void setBackgroundColour(HSV colour); ``` This way, the author of a type can decide whether the type should be interchangeable: ```d // not interchangeable with other types of similar structure struct Vector(size_t dim) { private float[dim] content; ref opIndex(size_t i){return content[i];} } // This would be interchangeable alias Vector(size_t dim) = float[dim]; // Also interchangeable alias Vector(size_t dim) = Tuple!(Repeat!(dim, float)); ``` Also, If we accept https://github.com/dlang/DIPs/pull/173 (I definitely like it!), I suggest that we also make `void` the same type as `Tuple!()` and `AnyType[0]`.Actually, I agree with the need for tuples, and am very open to a good design for it.I'd like to see something that unified arrays, structs, argument lists (for functions).
Dec 29 2021
On 12/29/21 7:48 AM, Walter Bright wrote:On 12/28/2021 9:14 PM, Walter Bright wrote:I would like to do that, but I think it would break code like this: void foo(int a,int b){} void foo(int[2] x){} After unification, those two function definitions would now be the same. Is this what you have in mind?Actually, I agree with the need for tuples, and am very open to a good design for it.I'd like to see something that unified arrays, structs, argument lists (for functions).
Jan 02 2022
On 1/3/22 8:40 AM, Timon Gehr wrote:On 12/29/21 7:48 AM, Walter Bright wrote:And there is also this: void foo(T...)(T args){} int[2] x; foo(x); // foo!(int[2]) and foo!(int,int) would now need to be the sameOn 12/28/2021 9:14 PM, Walter Bright wrote:I would like to do that, but I think it would break code like this: void foo(int a,int b){} void foo(int[2] x){} After unification, those two function definitions would now be the same. Is this what you have in mind?Actually, I agree with the need for tuples, and am very open to a good design for it.I'd like to see something that unified arrays, structs, argument lists (for functions).
Jan 02 2022
On 1/2/2022 11:42 PM, Timon Gehr wrote:And there is also this: void foo(T...)(T args){} int[2] x; foo(x); // foo!(int[2]) and foo!(int,int) would now need to be the sameWith such implicit conversions, the language would just descend into chaos. So no :-)
Jan 03 2022
On 03.01.22 10:27, Walter Bright wrote:On 1/2/2022 11:42 PM, Timon Gehr wrote:It's not an implicit conversion. I am mostly trying to figure out what constitutes "unification" for you. (In the programming languages I built, `int×int` and `int^2` are literally the same type, there is subtyping, but all actual type conversions are explicit.) Personally, the single thing I care most about in terms of "unification" is that this works: void foo(int a,int b){} (int,int) t; foo(t); // ok, function expects (int,int), and (int,int) was given But *not* this: void foo((int,int) a,int b){} (int,int,int) t; foo(t); // error, function expects ((int,int),int), not (int,int,int) I do not care much about `is((int,int)==int[2])`, but when you say you want to unify tuples and static arrays, that's what I think of.And there is also this: void foo(T...)(T args){} int[2] x; foo(x); // foo!(int[2]) and foo!(int,int) would now need to be the sameWith such implicit conversions, the language would just descend into chaos. So no :-)
Jan 03 2022
On 1/3/2022 6:06 PM, Timon Gehr wrote:On 03.01.22 10:27, Walter Bright wrote:Looks like it to me!On 1/2/2022 11:42 PM, Timon Gehr wrote:It's not an implicit conversion.And there is also this: void foo(T...)(T args){} int[2] x; foo(x); // foo!(int[2]) and foo!(int,int) would now need to be the sameWith such implicit conversions, the language would just descend into chaos. So no :-)I am mostly trying to figure out what constitutes "unification" for you. (In the programming languages I built, `int×int` and `int^2` are literally the same type, there is subtyping, but all actual type conversions are explicit.) Personally, the single thing I care most about in terms of "unification" is that this works: void foo(int a,int b){} (int,int) t; foo(t); // ok, function expects (int,int), and (int,int) was given But *not* this: void foo((int,int) a,int b){} (int,int,int) t; foo(t); // error, function expects ((int,int),int), not (int,int,int) I do not care much about `is((int,int)==int[2])`, but when you say you want to unify tuples and static arrays, that's what I think of.That isn't what I meant. I mean that there are easy ways to convert from one to the other, but not implicit conversions.
Jan 03 2022
On 04.01.22 06:40, Walter Bright wrote:On 1/3/2022 6:06 PM, Timon Gehr wrote:If `foo(int, int)` is defined to be literally the same as `foo(int[2])`, there is no conversion. But anyway, I guess you'd also consider anything that would make this work an "implicit conversion"? double foo(int x,string y); writeln([(1,"2"),(1,"3"),(3,"4")].map!foo); If so, maybe one way to make _some_ progress on this is to have a DIP specifically for destructuring, without adding any new types?On 03.01.22 10:27, Walter Bright wrote:Looks like it to me! ...On 1/2/2022 11:42 PM, Timon Gehr wrote:It's not an implicit conversion.And there is also this: void foo(T...)(T args){} int[2] x; foo(x); // foo!(int[2]) and foo!(int,int) would now need to be the sameWith such implicit conversions, the language would just descend into chaos. So no :-)
Jan 03 2022
On 1/3/2022 10:37 PM, Timon Gehr wrote:If `foo(int, int)` is defined to be literally the same as `foo(int[2])`, there is no conversion. But anyway, I guess you'd also consider anything that would make this work an "implicit conversion"? double foo(int x,string y); writeln([(1,"2"),(1,"3"),(3,"4")].map!foo);Currently, tuples can map right on to argument lists, there is no conversion. This works because a tuple in D isn't really a type at all. It's just a collection of expressions.If so, maybe one way to make _some_ progress on this is to have a DIP specifically for destructuring, without adding any new types?I'm not sure what destructuring, but yes, not adding new types.
Jan 03 2022
On Tuesday, 4 January 2022 at 07:52:00 UTC, Walter Bright wrote:"Destructuring" means binding members of a tuple to separate variables; e.g., struct S { int x; string y; } auto (x, y) = S(123, "hello").tupleof; assert(x == 123 && y == "hello"); C++17 has something similar, which it calls "structured bindings": https://en.cppreference.com/w/cpp/language/structured_bindingIf so, maybe one way to make _some_ progress on this is to have a DIP specifically for destructuring, without adding any new types?I'm not sure what destructuring, but yes, not adding new types.
Jan 04 2022
Thanks, I know what that was, I just didn't know the jargon for it.
Jan 07 2022
On 04.01.22 08:52, Walter Bright wrote:On 1/3/2022 10:37 PM, Timon Gehr wrote:But in the example above, those so-called "tuples" would expand right into the array literal and cause an error due to incompatible types. This can't work if `(1,"2")` etc. auto-expand. Furthermore, to put them into an array, they need to have an address.If `foo(int, int)` is defined to be literally the same as `foo(int[2])`, there is no conversion. But anyway, I guess you'd also consider anything that would make this work an "implicit conversion"? double foo(int x,string y); writeln([(1,"2"),(1,"3"),(3,"4")].map!foo);Currently, tuples can map right on to argument lists, there is no conversion. This works because a tuple in D isn't really a type at all. It's just a collection of expressions. ...Currently working with tuples (including actual tuples that are actual expressions, e.g., Phobos tuples) is inconvenient mostly (but not only) because you can't easily expand them into multiple named variables. ```d auto (col1, col2) = table.query!((ref row)=>tuple(row.column1,row.column2))(key); ``` Proposal 1 here: https://github.com/tgehr/DIPs/blob/tuple-syntax/DIPs/DIP1xxx-tg.md Proof-of-concept implementation here: https://github.com/tgehr/dmd/commit/8ad53b0891d3353dd96711595c06326ac0195d1b https://github.com/tgehr/dmd/commit/a0f59f93ab3727c93585dc658444860926a4b2c6If so, maybe one way to make _some_ progress on this is to have a DIP specifically for destructuring, without adding any new types?I'm not sure what destructuring,but yes, not adding new types.That's what I thought, so the tuple DIP is based on lowering to structs. What's the path forward to making this work? ```d double foo(int x,string y); writeln([(1,"2"),(1,"3"),(3,"4")].map!foo); ``` My suggestion was proposal 2 here: https://github.com/tgehr/DIPs/blob/tuple-syntax/DIPs/DIP1xxx-tg.md Proof-of-concept implementation here: https://github.com/tgehr/dmd/commit/bdb40fa96c471a7ace84596511a27ba3e803214f https://github.com/tgehr/dmd/commit/dad942117d85683e6234ef312c6d59be82f0c3a2 Note that Phobos tuples are implemented using an `alias this` to a built-in "tuple" of members: https://github.com/dlang/phobos/blob/master/std/typecons.d#L636-L655
Jan 04 2022
On 1/4/2022 3:36 PM, Timon Gehr wrote:On 04.01.22 08:52, Walter Bright wrote:I know. It's a problem.On 1/3/2022 10:37 PM, Timon Gehr wrote:But in the example above, those so-called "tuples" would expand right into the array literal and cause an error due to incompatible types. This can't work if `(1,"2")` etc. auto-expand. Furthermore, to put them into an array, they need to have an address.If `foo(int, int)` is defined to be literally the same as `foo(int[2])`, there is no conversion. But anyway, I guess you'd also consider anything that would make this work an "implicit conversion"? double foo(int x,string y); writeln([(1,"2"),(1,"3"),(3,"4")].map!foo);Currently, tuples can map right on to argument lists, there is no conversion. This works because a tuple in D isn't really a type at all. It's just a collection of expressions. ...I don't know. I'll have to look at your proposals.Currently working with tuples (including actual tuples that are actual expressions, e.g., Phobos tuples) is inconvenient mostly (but not only) because you can't easily expand them into multiple named variables. ```d auto (col1, col2) = table.query!((ref row)=>tuple(row.column1,row.column2))(key); ``` Proposal 1 here: https://github.com/tgehr/DIPs/blob/tuple-syntax/DIPs/DIP1xxx-tg.md Proof-of-concept implementation here: https://github.com/tgehr/dmd/commit/8ad53b0891d3353dd96711595c06326ac0195d1b https://github.com/tgehr/dmd/commit/a0f59f93ab3727c93585dc658444860926a4b2c6If so, maybe one way to make _some_ progress on this is to have a DIP specifically for destructuring, without adding any new types?I'm not sure what destructuring,but yes, not adding new types.That's what I thought, so the tuple DIP is based on lowering to structs. What's the path forward to making this work?```d double foo(int x,string y); writeln([(1,"2"),(1,"3"),(3,"4")].map!foo); ``` My suggestion was proposal 2 here: https://github.com/tgehr/DIPs/blob/tuple-syntax/DIPs/DIP1xxx-tg.md Proof-of-concept implementation here: https://github.com/tgehr/dmd/commit/bdb40fa96c471a7ace84596511a27ba3e803214f https://github.com/tgehr/dmd/commit/dad942117d85683e6234ef312c6d59be82f0c3a2 Note that Phobos tuples are implemented using an `alias this` to a built-in "tuple" of members: https://github.com/dlang/phobos/blob/master/std/typecons.d#L636-L655
Jan 07 2022
I'm concerned about what would happen to the following. All these are considered equivalent currently: (a,b,c) (a,(b,c)) ((a,b,c)) ((a,b),(c)) ((a),(b),(c)) [Of course, using the __tuple syntax.] Does your proposal change that? I can't quite be sure.
Jan 07 2022
On 1/8/22 02:39, Walter Bright wrote:I'm concerned about what would happen to the following. All these are considered equivalent currently: (a,b,c) (a,(b,c)) ((a,b,c)) ((a,b),(c)) ((a),(b),(c)) ...x is equivalent to (x). (Always, and a design that changes that is broken.) Therefore, `(a,b,c)`, `((a,b,c))` and `((a),(b),(c))` are the same, a triple with components a, b, and c.[Of course, using the __tuple syntax.] Does your proposal change that? I can't quite be sure.`(a,(b,c))` is not the same as `((a,b),c)` in my proposals, those are always pairs, where the second and first component, respectively, are also pairs. Both are distinct from `(a,b,c)`, which is always a triple. However, I don't propose to _change_ any existing auto-expanding behavior, I want to add tuple syntax and actual tuple behavior for something similar to a Phobos tuple. (I.e., based on a `struct` template.)
Jan 09 2022
On 1/9/22 11:05, Timon Gehr wrote:`(a,(b,c))` is not the same as `((a,b),c)` in my proposals, those are always pairs, where the second and first component, respectively, are also pairs. Both are distinct from `(a,b,c)`, which is always a triple.(Technically, I guess if `a, b or c` is an expression/expanded tuple of the variety that DMD already supports, the number of components of the results can be different.)
Jan 09 2022
On 1/2/2022 11:40 PM, Timon Gehr wrote:On 12/29/21 7:48 AM, Walter Bright wrote:Not exactly, since the ABI won't permit it. For example, struct S { byte b; int c; } byte b; int c; void func(byte, int); I can't call func with S(b,c); because of the function call ABI. Having a struct implicitly convertible to a tuple will also likely cause overloading confusion and will break legacy code. But we could support conversions. For example, a tuple could be converted to an anonymous struct with the syntax `struct(b,c)`. (A tuple can already be used to package up arguments to a function parameter list.) The ABI has no way to return a tuple from a function. But a function returning a tuple can be done by packing it into an anonymous struct and then unpacking it at the call site. This can happen under the hood, the user just sees a tuple. So, no, implicit conversions of Array <=> Struct <=> Tuple will likely cause many problems. But explicit conversions should work.On 12/28/2021 9:14 PM, Walter Bright wrote:I would like to do that, but I think it would break code like this: void foo(int a,int b){} void foo(int[2] x){} After unification, those two function definitions would now be the same. Is this what you have in mind?Actually, I agree with the need for tuples, and am very open to a good design for it.I'd like to see something that unified arrays, structs, argument lists (for functions).
Jan 03 2022
On 03.01.22 10:08, Walter Bright wrote:On 1/2/2022 11:40 PM, Timon Gehr wrote:My DIP draft extends "alias this" to allow this (which should work anyway): alias Seq(T...)=T; struct S{ byte b; int c; alias this=Seq!(b,c); } void func(byte,int); func(S()); Then it proposes to make tuples a struct template with such an alias this. Of course, it would also be possible to make tuples a built-in type, which would be my preferred design for a new language.On 12/29/21 7:48 AM, Walter Bright wrote:Not exactly, since the ABI won't permit it. For example, struct S { byte b; int c; } byte b; int c; void func(byte, int); I can't call func with S(b,c); because of the function call ABI. ...On 12/28/2021 9:14 PM, Walter Bright wrote:I would like to do that, but I think it would break code like this: void foo(int a,int b){} void foo(int[2] x){} After unification, those two function definitions would now be the same. Is this what you have in mind?Actually, I agree with the need for tuples, and am very open to a good design for it.I'd like to see something that unified arrays, structs, argument lists (for functions).Having a struct implicitly convertible to a tuple will also likely cause overloading confusion and will break legacy code.Yes, I don't want that. The benefit of introducing tuples as a struct template is precisely that it is a lot less likely to cause confusion in legacy code. It does have some significant drawbacks, e.g. `foo(int,int)` and `foo((int,int))` would have a different ABI and the second overload can't be called as `foo(1,2);`...But we could support conversions. For example, a tuple could be converted to an anonymous struct with the syntax `struct(b,c)`. (A tuple can already be used to package up arguments to a function parameter list.) The ABI has no way to return a tuple from a function. But a function returning a tuple can be done by packing it into an anonymous struct and then unpacking it at the call site. This can happen under the hood, the user just sees a tuple. ...Returning expanded values from functions is interesting (and my compiler frontend allows it), but I don't think that's really the main issue here.So, no, implicit conversions of Array <=> Struct <=> Tuple will likely cause many problems. But explicit conversions should work.To be very clear, I want this: [(1,2),(3,4)].map!((a,b)=>a+b).each!writeln; An this is generally what people mean when they talk about "tuples".
Jan 03 2022
On 04.01.22 04:09, Timon Gehr wrote:To be very clear, I want this: [(1,2),(3,4)].map!((a,b)=>a+b).each!writeln; An this is generally what people mean when they talk about "tuples".(I understand that there is something in the DMD source code already named "Tuple", but that's not really a tuple, it's a sequence of values that will auto expand into any context. Being able to return that from functions would be nice, but I think it's independent of what people are talking about when they want tuples.)
Jan 03 2022
On 04/01/2022 4:11 PM, Timon Gehr wrote:(I understand that there is something in the DMD source code already named "Tuple", but that's not really a tuple, it's a sequence of values that will auto expand into any context. Being able to return that from functions would be nice, but I think it's independent of what people are talking about when they want tuples.)Actually this is kinda what I want. Remove array, AA definitions in syntax. All you have is a tuple. A tuple accepts both named and unnamed types or values. It can devolve into static arrays, associative arrays, dynamic arrays all implicitly.
Jan 03 2022
On 04.01.22 05:20, rikki cattermole wrote:On 04/01/2022 4:11 PM, Timon Gehr wrote:My point was not that you don't want this, it was that calling it a "tuple" serves only to confuse.(I understand that there is something in the DMD source code already named "Tuple", but that's not really a tuple, it's a sequence of values that will auto expand into any context. Being able to return that from functions would be nice, but I think it's independent of what people are talking about when they want tuples.)Actually this is kinda what I want. Remove array, AA definitions in syntax. All you have is a tuple. A tuple accepts both named and unnamed types or values. It can devolve into static arrays, associative arrays, dynamic arrays all implicitly.
Jan 03 2022
On 04.01.22 06:14, Timon Gehr wrote:On 04.01.22 05:20, rikki cattermole wrote:(Also, having only the expanding variety of this is just not very useful as it prevents nesting.)On 04/01/2022 4:11 PM, Timon Gehr wrote:My point was not that you don't want this, it was that calling it a "tuple" serves only to confuse.(I understand that there is something in the DMD source code already named "Tuple", but that's not really a tuple, it's a sequence of values that will auto expand into any context. Being able to return that from functions would be nice, but I think it's independent of what people are talking about when they want tuples.)Actually this is kinda what I want. Remove array, AA definitions in syntax. All you have is a tuple. A tuple accepts both named and unnamed types or values. It can devolve into static arrays, associative arrays, dynamic arrays all implicitly.
Jan 03 2022
On 1/3/2022 7:11 PM, Timon Gehr wrote:On 04.01.22 04:09, Timon Gehr wrote:Yes, and reconciling this will be the problem.To be very clear, I want this: [(1,2),(3,4)].map!((a,b)=>a+b).each!writeln; An this is generally what people mean when they talk about "tuples".(I understand that there is something in the DMD source code already named "Tuple", but that's not really a tuple, it's a sequence of values that will auto expand into any context. Being able to return that from functions would be nice, but I think it's independent of what people are talking about when they want tuples.)
Jan 08 2022
On 1/9/22 00:03, Walter Bright wrote:On 1/3/2022 7:11 PM, Timon Gehr wrote:I agree. This is what I had in mind: - "tuple": the new thing, has an address - "expanded tuple": the existing thing If you have a tuple `t`, you can get an expanded tuple using `t.expand`, to transform an expanded tuple `e` into a tuple, you use `(e,)`. (This is a single-element tuple, this syntax is the same as in e.g. Python. Due to auto-expanding of `e`, it can have more than one element.) In practice, I think expanding is useful, but I'd mostly prefer to use tuples that don't auto-expand and expand them explicitly with `t.expand` if needed. `t.expand` itself is of course an auto-expanding expression. In `void foo(T...)(T args)`, `args` would probably still be an expanded tuple. The main challenge is this: ```d void foo(T)(T arg){} ``` right now, this will never match the following call: ```d foo(1,2) ``` But with tuples, we could just instantiate it with `T=(int,int)` and then the call should match. This is the main reason why the tuple DIP did not attempt to allow calling a function with a single tuple parameter with multiple arguments, but of course ideally it should work...On 04.01.22 04:09, Timon Gehr wrote:Yes, and reconciling this will be the problem.To be very clear, I want this: [(1,2),(3,4)].map!((a,b)=>a+b).each!writeln; An this is generally what people mean when they talk about "tuples".(I understand that there is something in the DMD source code already named "Tuple", but that's not really a tuple, it's a sequence of values that will auto expand into any context. Being able to return that from functions would be nice, but I think it's independent of what people are talking about when they want tuples.)
Jan 09 2022
On Sunday, 9 January 2022 at 10:35:03 UTC, Timon Gehr wrote: `C++` has `...` To extend the calling parameters, very comfortable. If only `d` had it.
Jan 09 2022
On Sunday, 9 January 2022 at 10:35:03 UTC, Timon Gehr wrote: `C++` has `...` To extend the calling parameters, very comfortable. If only `d` had it.
Jan 09 2022
On Sunday, 9 January 2022 at 12:38:59 UTC, zjh wrote:On Sunday, 9 January 2022 at 10:35:03 UTC, Timon Gehr wrote: `C++` has `...` To extend the calling parameters, very comfortable. If only `d` had it.D does have it
Jan 09 2022
On Sunday, 9 January 2022 at 12:48:37 UTC, max haughton wrote:D does have itfolding expression `...`,like this: ```d template<class...A,class...B> required allsame<A...>&&allsame<B...> void f(map<A,B>&...t){ (print(t.size()),...);//here. } ```
Jan 09 2022
On 1/3/2022 7:09 PM, Timon Gehr wrote:My DIP draft extends "alias this" to allow this (which should work anyway): alias Seq(T...)=T; struct S{ byte b; int c; alias this=Seq!(b,c); } void func(byte,int); func(S());I confess, this makes me uneasy. `alias this` produced a lot of unintended consequences. I'm gunshy of extending it. I'd prefer: func(S().tupleof);It does have some significant drawbacks, e.g. `foo(int,int)` and `foo((int,int))` would have a different ABI and the second overload can't be called as `foo(1,2);`...I tried to actively avoid that :-)To be very clear, I want this: [(1,2),(3,4)].map!((a,b)=>a+b).each!writeln; An this is generally what people mean when they talk about "tuples".I understand. It looks like a worthy goal.
Jan 04 2022
On 05.01.22 07:33, Walter Bright wrote:On 1/3/2022 7:09 PM, Timon Gehr wrote:Well, then let's not extend `alias this`.My DIP draft extends "alias this" to allow this (which should work anyway): alias Seq(T...)=T; struct S{ byte b; int c; alias this=Seq!(b,c); } void func(byte,int); func(S());I confess, this makes me uneasy. `alias this` produced a lot of unintended consequences. I'm gunshy of extending it. I'd prefer: func(S().tupleof); ...How about something like opArgs, dealing specifically with this case? (i.e., a function call `foo(x)` with a single argument is immediately rewritten to `foo(x.opArgs)` if `x` has a member `opArgs`, and this rewrite is applied exactly once.)It does have some significant drawbacks, e.g. `foo(int,int)` and `foo((int,int))` would have a different ABI and the second overload can't be called as `foo(1,2);`...I tried to actively avoid that :-)To be very clear, I want this: [(1,2),(3,4)].map!((a,b)=>a+b).each!writeln; An this is generally what people mean when they talk about "tuples".I understand. It looks like a worthy goal.
Jan 04 2022
On 05.01.22 08:28, Timon Gehr wrote:(This would apply symmetrically at the call site, so that if we define a function `foo(T x)`, where T has an opArgs, it's `foo(typeof(T.opArgs) x)` instead.)How about something like opArgs, dealing specifically with this case? (i.e., a function call `foo(x)` with a single argument is immediately rewritten to `foo(x.opArgs)` if `x` has a member `opArgs`, and this rewrite is applied exactly once.)To be very clear, I want this: [(1,2),(3,4)].map!((a,b)=>a+b).each!writeln; An this is generally what people mean when they talk about "tuples".I understand. It looks like a worthy goal.
Jan 04 2022
On Wednesday, 5 January 2022 at 07:28:41 UTC, Timon Gehr wrote:How about something like opArgs, dealing specifically with this case? (i.e., a function call `foo(x)` with a single argument is immediately rewritten to `foo(x.opArgs)` if `x` has a member `opArgs`, and this rewrite is applied exactly once.)This mechanism seems too powerful to me; for example, one could write code like the following: struct S { string opArgs; } string fun(S s) { return "S overload"; } string fun(string s) { return "string overload"; } void main() { assert(fun(S()) == "S overload"); // fails } If there is to be any mechanism for automatic expansion of tuples, it should probably be narrow enough to avoid enabling surprises like this one.
Jan 05 2022
On 1/5/22 23:42, Paul Backus wrote:On Wednesday, 5 January 2022 at 07:28:41 UTC, Timon Gehr wrote:Why is that a surprise? You could similarly do something like: alias S=AliasSeq!(string);How about something like opArgs, dealing specifically with this case? (i.e., a function call `foo(x)` with a single argument is immediately rewritten to `foo(x.opArgs)` if `x` has a member `opArgs`, and this rewrite is applied exactly once.)This mechanism seems too powerful to me; for example, one could write code like the following: struct S { string opArgs; } string fun(S s) { return "S overload"; } string fun(string s) { return "string overload"; } void main() { assert(fun(S()) == "S overload"); // fails } If there is to be any mechanism for automatic expansion of tuples, it should probably be narrow enough to avoid enabling surprises like this one.
Jan 05 2022
On Wednesday, 5 January 2022 at 23:56:03 UTC, Timon Gehr wrote:On 1/5/22 23:42, Paul Backus wrote:Perhaps this is a better illustration: struct A { B opArgs() { return B(); } } struct B {} string fun(A) { return "A"; } string fun(B) { return "B"; } void main() { assert(fun(A()) == "A"); // fails } It's perfectly logical if you know about opArgs and have the definition of A in front of you, but it's extremely surprising and unintuitive if you don't.On Wednesday, 5 January 2022 at 07:28:41 UTC, Timon Gehr wrote:Why is that a surprise? You could similarly do something like: alias S=AliasSeq!(string);How about something like opArgs, dealing specifically with this case? (i.e., a function call `foo(x)` with a single argument is immediately rewritten to `foo(x.opArgs)` if `x` has a member `opArgs`, and this rewrite is applied exactly once.)This mechanism seems too powerful to me; for example, one could write code like the following: [...]
Jan 05 2022
On 1/6/22 06:58, Paul Backus wrote:No, it's the same thing. I understand what you are saying, I just don't agree it's important or likely to cause surprises in practice.Why is that a surprise? You could similarly do something like: alias S=AliasSeq!(string);Perhaps this is a better illustration: ...struct A { B opArgs() { return B(); } } struct B {} string fun(A) { return "A"; } string fun(B) { return "B"; } void main() { assert(fun(A()) == "A"); // fails } It's perfectly logical if you know about opArgs and have the definition of A in front of you, but it's extremely surprising and unintuitive if you don't.Again, why is that different from the alias case? Furthermore, why would you use this feature willy-nilly in the first place without an intention to implement tuple semantics? "You can use this feature to write bad code" is a weak argument, it applies to every language feature.
Jan 06 2022
On 1/6/22 06:58, Paul Backus wrote:BTW, it should work like this: ```d void foo(string x){} // <- a string, not a tuple void foo(string x,){} // <- unary tuple void foo((string,) t){} // <- unary tuple void foo(string x,int y){} // <- 2-tuple void foo((string,int) t){} // <- 2-tuple ``` So perhaps your example would not even work that way; unary tuples shouldn't decay into the underlying type. The concept will need some fleshing out. Maybe it's indeed too hard to actually retrofit this into the language...Perhaps this is a better illustration: struct A { B opArgs() { return B(); } } struct B {} string fun(A) { return "A"; } string fun(B) { return "B"; } void main() { assert(fun(A()) == "A"); // fails }
Jan 06 2022
On Thursday, 6 January 2022 at 13:18:56 UTC, Timon Gehr wrote:BTW, it should work like this: ```d void foo(string x){} // <- a string, not a tuple void foo(string x,){} // <- unary tuple void foo((string,) t){} // <- unary tuple void foo(string x,int y){} // <- 2-tuple void foo((string,int) t){} // <- 2-tuple ``` So perhaps your example would not even work that way; unary tuples shouldn't decay into the underlying type. The concept will need some fleshing out. Maybe it's indeed too hard to actually retrofit this into the language...Actually I think you were on the right track in [your earlier post][1], with this example: ```d void foo(int a, string b){} // pattern (int a,string b) foo(1,"2"); // match tuple (1,"2") ``` i.e., the argument list itself should be treated like a tuple, and one could also write ```d auto tup = (1, "2"); foo(tup); ``` In fact, this is how tuples already work in D, just with nicer syntax--`(1, "2")` instead of `tuple(1, "2").expand`. What the current language *can't* do, without using wrapper structs like `std.typecons.Tuple`, is nest tuples. In other words, the question we need to answer is perhaps better framed as "when *aren't* tuples expanded?" [1]: https://forum.dlang.org/post/sr5b4a$ogr$1 digitalmars.com
Jan 06 2022
On Thursday, 6 January 2022 at 13:18:56 UTC, Timon Gehr wrote:void foo(string x,){} // <- unary tupleWhile you are correct, it is likely to be a breaking change. Currently (string x,) is allowed and means the same as (string x).
Jan 08 2022
On 1/8/22 11:28, Max Samukha wrote:On Thursday, 6 January 2022 at 13:18:56 UTC, Timon Gehr wrote:True.void foo(string x,){} // <- unary tupleWhile you are correct, it is likely to be a breaking change. Currently (string x,) is allowed and means the same as (string x).
Jan 09 2022
On Wednesday, 5 January 2022 at 22:42:14 UTC, Paul Backus wrote:On Wednesday, 5 January 2022 at 07:28:41 UTC, Timon Gehr wrote:Yeah, and what does "exactly once" mean here? ```d struct S { string opArgs; } string fun(S s) { return "S overload"; } string fun(string s) { return "string overload"; } void main() { S s = S(); assert(fun(s) == "string overload"); // succeeds assert(fun(s) == "S overload"); // this also succeeds?? } ```How about something like opArgs, dealing specifically with this case? (i.e., a function call `foo(x)` with a single argument is immediately rewritten to `foo(x.opArgs)` if `x` has a member `opArgs`, and this rewrite is applied exactly once.)This mechanism seems too powerful to me; for example, one could write code like the following: struct S { string opArgs; } string fun(S s) { return "S overload"; } string fun(string s) { return "string overload"; } void main() { assert(fun(S()) == "S overload"); // fails } If there is to be any mechanism for automatic expansion of tuples, it should probably be narrow enough to avoid enabling surprises like this one.
Jan 05 2022
On Thursday, 6 January 2022 at 02:56:52 UTC, Tejas wrote:On Wednesday, 5 January 2022 at 22:42:14 UTC, Paul Backus wrote:I assume it means "once per argument"; i.e., the rewrite is not applied recursively to its own result. For example: ```d struct A { B opArgs; } struct B { C opArgs; } struct C {} string fun(A) { return "A"; } string fun(B) { return "B"; } string fun(C) { return "C"; } void main() { assert(fun(A()) == "B"); } ``` `A()` is rewritten to `A().opArgs`, but `A().opArgs` is **not** rewritten to `A().opArgs.opArgs`.On Wednesday, 5 January 2022 at 07:28:41 UTC, Timon Gehr wrote:Yeah, and what does "exactly once" mean here?How about something like opArgs, dealing specifically with this case? (i.e., a function call `foo(x)` with a single argument is immediately rewritten to `foo(x.opArgs)` if `x` has a member `opArgs`, and this rewrite is applied exactly once.)[...]
Jan 05 2022
On Wednesday, 5 January 2022 at 22:42:14 UTC, Paul Backus wrote:On Wednesday, 5 January 2022 at 07:28:41 UTC, Timon Gehr wrote:You could just make sure that the root type is always used if an overload is available for it. Just like if you did: ```d struct S { string opArgs; alias opArgs this; } ```How about something like opArgs, dealing specifically with this case? (i.e., a function call `foo(x)` with a single argument is immediately rewritten to `foo(x.opArgs)` if `x` has a member `opArgs`, and this rewrite is applied exactly once.)This mechanism seems too powerful to me; for example, one could write code like the following: struct S { string opArgs; } string fun(S s) { return "S overload"; } string fun(string s) { return "string overload"; } void main() { assert(fun(S()) == "S overload"); // fails } If there is to be any mechanism for automatic expansion of tuples, it should probably be narrow enough to avoid enabling surprises like this one.
Jan 05 2022
On 1/6/22 08:14, bauss wrote:On Wednesday, 5 January 2022 at 22:42:14 UTC, Paul Backus wrote:No, if you want the root type, add a trailing comma to the declaration: string fun(S s,){ return "S overload"; } string fun(string s){ return "string overload"; } (This matches unary tuple syntax (1,).)On Wednesday, 5 January 2022 at 07:28:41 UTC, Timon Gehr wrote:You could just make sure that the root type is always used if an overload is available for it. Just like if you did: ```d struct S { string opArgs; alias opArgs this; } ```How about something like opArgs, dealing specifically with this case? (i.e., a function call `foo(x)` with a single argument is immediately rewritten to `foo(x.opArgs)` if `x` has a member `opArgs`, and this rewrite is applied exactly once.)This mechanism seems too powerful to me; for example, one could write code like the following: struct S { string opArgs; } string fun(S s) { return "S overload"; } string fun(string s) { return "string overload"; } void main() { assert(fun(S()) == "S overload"); // fails } If there is to be any mechanism for automatic expansion of tuples, it should probably be narrow enough to avoid enabling surprises like this one.
Jan 06 2022
On 1/6/22 08:14, bauss wrote:You could just make sure that the root type is always used if an overload is available for it. Just like if you did: ```d struct S { string opArgs; alias opArgs this; } ```(But in general, yes, using `alias this` was my initial proposal and I once thought it's more or less viable, but Walter shot that down already.)
Jan 06 2022
On Thursday, 6 January 2022 at 07:14:49 UTC, bauss wrote:On Wednesday, 5 January 2022 at 22:42:14 UTC, Paul Backus wrote:Sure. You could make overload resolution consider a call that uses opArgs to be a "match with implicit conversion" [1], which would give it lower priority than an "exact match". Which, IMO, perfectly illustrates the problem with opArgs: it's essentially a half-assed version of user-defined implicit conversions. Not powerful enough to do everything you'd want such a feature to do, but still powerful enough to shoot yourself in the foot. [1] https://dlang.org/spec/function.html#function-overloadingThis mechanism seems too powerful to me; for example, one could write code like the following: struct S { string opArgs; } string fun(S s) { return "S overload"; } string fun(string s) { return "string overload"; } void main() { assert(fun(S()) == "S overload"); // fails } If there is to be any mechanism for automatic expansion of tuples, it should probably be narrow enough to avoid enabling surprises like this one.You could just make sure that the root type is always used if an overload is available for it. Just like if you did: ```d struct S { string opArgs; alias opArgs this; } ```
Jan 06 2022
On 1/4/2022 11:28 PM, Timon Gehr wrote:How about something like opArgs, dealing specifically with this case? (i.e., a function call `foo(x)` with a single argument is immediately rewritten to `foo(x.opArgs)` if `x` has a member `opArgs`, and this rewrite is applied exactly once.)Sounds like a promising idea.
Jan 08 2022
On Wednesday, 5 January 2022 at 06:33:39 UTC, Walter Bright wrote:On 1/3/2022 7:09 PM, Timon Gehr wrote:Is this really necessary or even desirable? Tuples do not auto-expand like this in other languages. For example, in Python: def fun(*args): print(len(args)) tup = (1, 2, 3) Even without automatic tuple expansion, Timon's example could be written as follows: alias apply(alias fun) = (args) => fun(args.tupleof); [(1,2), (3,4)].map!(apply!((a, b) => a+b)).each!writeln;To be very clear, I want this: [(1,2),(3,4)].map!((a,b)=>a+b).each!writeln; An this is generally what people mean when they talk about "tuples".I understand. It looks like a worthy goal.
Jan 05 2022
On 1/5/22 23:37, Paul Backus wrote:On Wednesday, 5 January 2022 at 06:33:39 UTC, Walter Bright wrote:This is not about auto-expanding. Conceptually, functions with multiple arguments are functions that take a tuple argument. I am sure you are aware of this.On 1/3/2022 7:09 PM, Timon Gehr wrote:Is this really necessary or even desirable? Tuples do not auto-expandTo be very clear, I want this: [(1,2),(3,4)].map!((a,b)=>a+b).each!writeln; An this is generally what people mean when they talk about "tuples".I understand. It looks like a worthy goal.like this in other languages.Well, in _some_ languages. Those languages get it wrong.For example, in Python: def fun(*args): print(len(args)) tup = (1, 2, 3) ...Yes, and I dislike this about Python. Making multiple arguments a distinct concept from tuples on the surface is just not particularly good design. Why is _that_ desirable? It's a good example of non-orthogonal language design. ```d void foo(int a, string b){} // pattern (int a,string b) foo(1,"2"); // match tuple (1,"2") (int a, string b) = (1,"2"); // same thing void foo((int a, string b), double c){} foo((1,"2"), 3.0); ((int a,string b), double c) = ((1,"2"),3.0); ``` Why would pattern matching tuples work differently in a parameter list and elsewhere?Even without automatic tuple expansion, Timon's example could be written as follows: alias apply(alias fun) = (args) => fun(args.tupleof); [(1,2), (3,4)].map!(apply!((a, b) => a+b)).each!writeln;Clearly, but who wants to do that?
Jan 05 2022
On Wednesday, 29 December 2021 at 05:14:43 UTC, Walter Bright wrote:Actually, I agree with the need for tuples, and am very open to a good design for it.Yes please! some love for tuples is very much needed, recently feep shared his neat lang on the IRC, and look at this beauty: https://github.com/Neat-Lang/neat/blob/master/test/runnable/tuples.nt#L6 No need of an import, no need of special types, it's built-in, using it would be sweet It's similar in GO https://gobyexample.com/multiple-return-values I love that, i wish it could be possible in D
Dec 29 2021
On Sunday, 14 November 2021 at 23:05:03 UTC, Timon Gehr wrote: ...Yes please.nullable,Maybe: int*? x=null; writeln(*x); // error if(x) writeln(*x); // okDoes the `s with...` expression have to keep the same source type? If not we could make a type constructor template `methodize!(S,.)` which wraps the source type but has methods which wrap all public functions in the given module that have a first parameter of the source type.import a: S; import b: rangeFun; auto ref front(ref S s){ ... } bool empty(ref S s){ ... } void popFront(){ ... } void main(){ S s; rangeFun(s with(front, empty, popFront)); alias T=S with (front,empty,popFront); T t=s; rangeFun(t); }- type classes / some standard way to add UFCS methods to a type from another module that are then visible in an instantiated template from a third moduleIsn't this sufficient?: auto z = { int x=1; int y=2; return x+y; }();void main(){ auto z = { int x=1; int y=2; } in x+y; assert(z==3); }- `let Statement in Expression` expressionvoid main(){ auto z = x+y where{ int x=1; int y=2; }; assert(z==3); }- `Expression where Statement` expression...See above. Unfortunately I only had time to give some contrived examples.Yes please.static foreach((name, value);[("x",1),("y",2),("z",3)]){ int mixin(name) = value; } writeln(x," ",y," ",z); // 1 2 3- mixin identifiersexample?I like 'alias template literal' syntax: `alias(B) => B.sizeof` The only problem is currently `alias e = 5;` doesn't compile (at least on run.dlang.org). That is inconsistent as non-literal value expressions work.enum sizes = staticMap!((B)!=>B.sizeof,Types);- template literalsexample?Seems we could add a few UFCS functions to object.d for that.- consistent treatment of operators for built-in types, e.g. 1.opBinary!"+"(2) should work.Maybe a template would make the current code a bit nicer: auto b = iota(100).mapFilter!(x => bar(x) ? fun(x) : none);auto b = (fun(x) for x in iota(100) if bar(x)); // equivalent to: // auto b = iota(100).filter!(x=>bar(x)).map!(x=>fun(x));- range literalswhat's that?Seems bug prone unless it used special syntax to take a value of another type.int x=2; x="123"; static assert(is(typeof(x)==string));- strong variable updates (probably not happening)what's that?auto f=File(x,"r"); static assert(is(typeof(f)==File)); f.close(); static assert(is(typeof(f)==ClosedFile));If we had affine typing, it would be simpler to just design `f.close` to invalidate any use of `f`, like your example calling `move` or `destroy`. (I suppose e.g. `f.closeForNow` would not invalidate `f` if needed).
Nov 15 2021
On 11/14/2021 3:05 PM, Timon Gehr wrote:Another issue is that it slightly expands `alias this` and I am not sure whether that's a direction Walter is willing to invest in at this point.`alias this` suffers from being under-specified. In an attempt to fix that, I discovered it runs smack into multiple inheritance land, something I've tried to avoid. Worse, its implementation does a half-baked job of multiple inheritance, and backwards compatibility interferes with fixing it. To move forward with it, it would have to be abandoned in its current form and completely redesigned.
Dec 28 2021
On Wednesday, 29 December 2021 at 05:13:55 UTC, Walter Bright wrote:To move forward with it, it would have to be abandoned in its current form and completely redesigned.I am in strong favor of being replaced rather than redesigned. The only thing that is preventing alias this from being replaced entirely is implicit conversions, which incidentally is a common use of alias this. D can do implicit conversions differently than C++, as there are other languages out there that have implicit conversions that is (IMO at least) sane and reasonable. The question is Walter: Are you willing to bite the bullet on this or you rather look for some alternative solution here? -Alex
Dec 28 2021
On 12.10.21 23:38, Timon Gehr wrote:Another thing I have sometimes wished for, but forgot to include: - package and module templates* Features you'd like to see in D
Nov 22 2021
On Tuesday, 23 November 2021 at 07:55:45 UTC, Timon Gehr wrote:On 12.10.21 23:38, Timon Gehr wrote:What do you mean by that? Something like this? Or? ```d module main; import a!5; void main() { auto foo = new Foo; foo.field4 = 10; } ``` ```d module a(int fieldCount); import std.string : format; class Foo { static foreach (i; 0 .. fieldCount) { mixin(format("int field%d", i)); } } ```Another thing I have sometimes wished for, but forgot to include: - package and module templates* Features you'd like to see in D
Nov 23 2021
On 11/23/21 10:09 AM, bauss wrote:On Tuesday, 23 November 2021 at 07:55:45 UTC, Timon Gehr wrote:Yes, something like this. Thanks for clarifying! This is a module template, I am not sure what's the best way to parameterize an entire package, maybe the declaration should be in every file like this: module package_(T).a;On 12.10.21 23:38, Timon Gehr wrote:What do you mean by that? Something like this? Or? ```d module main; import a!5; void main() { auto foo = new Foo; foo.field4 = 10; } ``` ```d module a(int fieldCount); import std.string : format; class Foo { static foreach (i; 0 .. fieldCount) { mixin(format("int field%d", i)); } } ```Another thing I have sometimes wished for, but forgot to include: - package and module templates* Features you'd like to see in D
Nov 23 2021
On Tuesday, 23 November 2021 at 09:09:03 UTC, bauss wrote:On Tuesday, 23 November 2021 at 07:55:45 UTC, Timon Gehr wrote:I think that is what he means. template modules are something I have thought about, it's a simple addition but I fear they might not be advisable in the long run. Unfortunately I cannot really put my finger onto why that might be. I have a vague sense that this feature would lead to un-synchronized changes which are meant to be synchronized.On 12.10.21 23:38, Timon Gehr wrote:What do you mean by that? Something like this? Or? ```d module main; import a!5; void main() { auto foo = new Foo; foo.field4 = 10; } ``` ```d module a(int fieldCount); import std.string : format; class Foo { static foreach (i; 0 .. fieldCount) { mixin(format("int field%d", i)); } } ```Another thing I have sometimes wished for, but forgot to include: - package and module templates* Features you'd like to see in D
Nov 23 2021
On Tuesday, 23 November 2021 at 14:09:56 UTC, Stefan Koch wrote:template modules are something I have thought about, it's a simple addition but I fear they might not be advisable in the long run.IIRC, Bjarne Stroustrup was advised to use the less problematic scheme of having parametric modules for C++, but he went with the more problematic templates instead. :-)
Nov 23 2021
On Tuesday, 23 November 2021 at 07:55:45 UTC, Timon Gehr wrote:On 12.10.21 23:38, Timon Gehr wrote:You mean showing the `static this()` to accept parameters? That'd be amazing 😄Another thing I have sometimes wished for, but forgot to include: - package and module templates* Features you'd like to see in D
Nov 23 2021
On Tuesday, 23 November 2021 at 10:15:52 UTC, Tejas wrote:On Tuesday, 23 November 2021 at 07:55:45 UTC, Timon Gehr wrote:Not showing, I meant 'allowing'On 12.10.21 23:38, Timon Gehr wrote:You mean showing the `static this()` to accept parameters? That'd be amazing 😄Another thing I have sometimes wished for, but forgot to include: - package and module templates* Features you'd like to see in D
Nov 23 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy languageGo's implicit duck-typing of structs to interfaces. Things don't accidentally match a non-trivial interface, and hardly anyone wants to make an interface for a struct that some third party manages (just wrapping the struct would more idiomatic for Go). For the sake of saving a one-line inheritance specifier, this magic makes it so much harder to figure out which structs are intended to match an interface in a large codebase written by multiple people. Supporting error detection without helping with error handling. Python is good because exceptions inherit from standard types that can be handled consistently (e.g., KeyError). Most other languages (including D) aren't much help here. Go misses the point by acting like "if err != nil { return err }" is actually handling errors. I agree with others that C's type declaration syntax is a non-feature. It's pointlessly "clever" and not even consistent. I've blogged about this problem here: https://theartofmachinery.com/2020/08/18/d_declarations_for_c_programmers.html I'm sure you can think of more C++ problems than me, but let me pick three that epitomise why I don't like C++ any more: SFINAE. It's powerful, but makes template metaprogramming slow at compile time, terrible to debug and hard to read. D shows that explicit constraints are better all around. Member function pointers. They're hard to use correctly and "feel" low level, but are actually very high level. D's delegates are easier to use and reason about, yet are lower level (NB: closures are higher level, but that's a different story). Sensible operator overloading for a simple number-like type takes a lot of boring boilerplate, which encourages developers to do "interesting" things with operator overloading instead. D makes the sensible things easy, so there's less of a culture of "interesting" metaprogramming hacks.* Worst features (in your opinion) in D* The multiple (confusing) ways to write anonymous lambdas. * opDispatch's (lack of) error handling semantics. * Autodecoding. * Overuse of attributes. (It fills the type system with things that could be better done with separate notation for static checking tooling.) * Overloaded semantics of . that makes namespacing hard in practice. * The hacky non-virtual destructor implementation.* Features you'd like to see in DOverall, I don't think D needs many more features. But because you asked: * Better value analysis to make integer promotion issues less annoying. * Better error handling for opDispatch. * Native tuple support (with destructuring, etc.).Ideas? Examples? Thanks!
Oct 12 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:* Worst features implemented in a non-toy languageI can't believe no one has mentioned this yet: PHP register globals. That is, the feature that creates variables in your scripts from request parameters.* Worst features (in your opinion) in DDifficult to say, but all the half implemented features.* Features you'd like to see in D* Non nullable pointers and reference types by default * Built-in or syntax sugar for optional types * Native tuples with destruction and named values: ```d (int, string) tup = (1, "foo"); auto (a, b) = tup; (int, int) point = (x: 2, y: 4); auto x = point.x + a; ``` * Some form of zero overhead exceptions. Example: ```d struct PermissionDenied {} struct FileNotFound {} int open(string filename) throw(PermissionDenied, FileNotFound); string readFile(string filename) throw(auto) { auto fd = open(filename); // ... } void main() { try auto content = readFile("foo.txt"); catch (PermissionDenied e) {} catch (FileNotFound e) {} } ``` The above is lowered to: ```d struct PermissionDenied {} struct FileNotFound {} Result!(int, PermissionDenied, FileNotFound) open(string filename); Result!(string, PermissionDenied, FileNotFound) readFile(string filename) { R0 __tmp0 = open(filename); int fd = void; switch (__tmp0.tag) { case R0.Tag.success: fd = __tmp0.value; // ... break; case R0.Tag.error0: return typeof(return)(__tmp0.error0); case R0.Tag.error1: return typeof(return)(__tmp0.error1); } } void main() { R0 __tmp0 = readFile("foo.txt"); string content = void; switch (__tmp0.tag) { case R0.Tag.success: content = __tmp0.value; break; case R0.Tag.error0: PermissionDenied e = __tmp0.error0; break; case R0.Tag.error1: FileNotFound e = __tmp0.error1; break; } } ``` -- /Jacob Carlborg
Oct 13 2021
On Wednesday, 13 October 2021 at 19:55:29 UTC, Jacob Carlborg wrote:On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:"Native tuples with destruction", are you sure you don't want deconstruction instead 😉[...]I can't believe no one has mentioned this yet: PHP register globals. That is, the feature that creates variables in your scripts from request parameters. [...]
Oct 13 2021
On Wednesday, 13 October 2021 at 20:10:06 UTC, Imperatorn wrote:"Native tuples with destruction", are you sure you don't want deconstruction instead 😉Yes, that's what I meant. -- /Jacob Carlborg
Oct 13 2021
On Wednesday, 13 October 2021 at 19:55:29 UTC, Jacob Carlborg wrote:(int, int) point = (x: 2, y: 4); auto x = point.x + a; ```This would be better if the identifier was tied to the type. Like below: ```d (int x, int y) point = (2, 4); auto x = point.x + a; ``` Because with your example the following fails: ```d (int, int) getPoint1() { return (x: 2, y: 4); } (int, int) getPoint2(bool shouldGetPoint1) { if (shouldGetPoint1) return getPoint1(); return (left: 2, top: 4); // Possible error since the named values will be different?? } auto point1 = getPoint1(); auto point2 = getPoint2(true); auto point3 = getPoint2(false); writeln("%d %d", point1.x, point1.y); writeln("%d %d", point2.left, point2.top); // Error writeln("%d %d", point3.left, point3.top); ``` However it wouldn't fail if it worked like below: ```d (int x, int y) getPoint1() { return (2, 4); } (int left, int top) getPoint2(bool shouldGetPoint1) { if (shouldGetPoint1) return getPoint1(); return (2, 4); // Ok } auto point1 = getPoint1(); auto point2 = getPoint2(true); auto point3 = getPoint2(false); writeln("%d %d", point1.x, point1.y); writeln("%d %d", point2.left, point2.top); // Ok writeln("%d %d", point3.left, point3.top); ```
Oct 14 2021
On Thursday, 14 October 2021 at 10:55:14 UTC, bauss wrote:On Wednesday, 13 October 2021 at 19:55:29 UTC, Jacob Carlborg wrote:Ofc. these are supposed to be writefln and not writeln.(int, int) point = (x: 2, y: 4); auto x = point.x + a; ```This would be better if the identifier was tied to the type. Like below: ```d (int x, int y) point = (2, 4); auto x = point.x + a; ``` Because with your example the following fails: ```d (int, int) getPoint1() { return (x: 2, y: 4); } (int, int) getPoint2(bool shouldGetPoint1) { if (shouldGetPoint1) return getPoint1(); return (left: 2, top: 4); // Possible error since the named values will be different?? } auto point1 = getPoint1(); auto point2 = getPoint2(true); auto point3 = getPoint2(false); writeln("%d %d", point1.x, point1.y); writeln("%d %d", point2.left, point2.top); // Error writeln("%d %d", point3.left, point3.top); ``` However it wouldn't fail if it worked like below: ```d (int x, int y) getPoint1() { return (2, 4); } (int left, int top) getPoint2(bool shouldGetPoint1) { if (shouldGetPoint1) return getPoint1(); return (2, 4); // Ok } auto point1 = getPoint1(); auto point2 = getPoint2(true); auto point3 = getPoint2(false); writeln("%d %d", point1.x, point1.y); writeln("%d %d", point2.left, point2.top); // Ok writeln("%d %d", point3.left, point3.top); ```
Oct 14 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy languageIt's a hard one. Variables implicitly declared as global in JS certainly is up there.* Worst features (in your opinion) in DPretty much anything working around the incompleteness of type qualifiers. nogc, shared being a nightmare, the impossibility of having a proper container library, all stem from the same place.* Features you'd like to see in Downed as a type qualifier. Because it would fix most of the problems for which many features have been introduced. I think we could reduce the language size overall by adding this one.
Oct 13 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy language * Worst features (in your opinion) in D * Features you'd like to see in D Ideas? Examples? Thanks!Worst features in a non-toy language. This is going to be controversial, but templates. They start innocent enough, just a way for functions to work with generic arguments. But then you build templates upon templates, and suddenly IDEs get lost, auto-refactoring stops becoming a possibility because most code doesn't exist yet, and you have to read documentation to understand what the return types and input types are of method T doStuff(T, U)(T val, U min, U max); I wouldn't say worst, but I feel like D has many features which just don't get much use. For example contracts. Sure, they sound nice in principle, and I am sure there are some users of that feature. There's nothing wrong with that, but every feature adds more complexity and bugs to fix. Features I'd like to see in D? Named arguments and struct/associative array initializers working outside of initialization, e.g. as function arguments. Some syntactic sugar I like from other languages: Named constructors as a replacement for factory static methods: ```d class Angle { this.fromDegrees(float deg) { ... } this.fromRadians(float rad) { ... } } Angle a = new Angle.fromDegrees(90.0f); ``` Initializer fields: ```d class Person { string firstName, lastName; int age; this(this.firstName, this.lastName, this.age); } Person p = new Person("Michael", "Schumacher", 52); ```
Oct 14 2021
On Thursday, 14 October 2021 at 11:06:00 UTC, JN wrote:Named constructors as a replacement for factory static methods: ```d class Angle { this.fromDegrees(float deg) { ... } this.fromRadians(float rad) { ... } } Angle a = new Angle.fromDegrees(90.0f); ```You can somewhat hack your way to it, by generating static functions at compile-time. Of course they're not real constructors, so immutable cannot be used and you can't utilize it like `new Angle.fromDegrees(90.0f)` and will have to do it like `Angle.fromDegrees(90.0f)` instead. Example: ```d class Angle { private: this(){} Ctor void _fromDegrees(float deg) { writeln("from degrees"); } Ctor void _fromRadians(float rad) { writeln("from radians"); } mixin NamedConstructors!Angle; } void main() { auto a = Angle.fromDegrees(90.0f); auto b = Angle.fromRadians(90.0f); } ``` Implementation of the hacky stuff: ```d struct Ctor {} template ParametersFullyQualified(alias fun) { Tuple!(string,string)[] produceIndexed(T)(T[] a, T[] b) { Tuple!(string,string)[] produced = []; if (a.length == b.length) { foreach (i; 0 .. a.length) { produced ~= tuple(a[i], b[i]); } } return produced; } enum ParametersTypeArray = Parameters!(fun).stringof[1..$-1].split(", "); enum ParameterNamesArray = [ParameterIdentifierTuple!(fun)]; enum ParametersFullyQualified = produceIndexed(ParametersTypeArray, ParameterNamesArray).map!(t => t[0] ~ " " ~ t[1]).join(", "); } mixin template NamedConstructors(T) { public: static: static foreach (member; __traits(derivedMembers, T)) { static if (mixin("hasUDA!(" ~ T.stringof ~ "." ~ member ~ ", Ctor)")) { mixin(T.stringof ~ " " ~ member[1 .. $] ~ "(" ~ ParametersFullyQualified!(mixin(T.stringof ~ "." ~ member)) ~ ") { auto o = new " ~ T.stringof ~ "(); o." ~ member ~ "(" ~ [ParameterIdentifierTuple!(mixin(T.stringof ~ "." ~ member))].join(", ") ~ "); return o; }"); } } } ```
Oct 14 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:* Worst features implemented in a non-toy languageThis is not a feature but a language design question. One of the worst thins you can ever do to language is to mix language paradigms. This totally messes up the language as well as your brain. One of example is C++ template programming which is based on ML. Lately in newer C++ they have tried to taint that mistake up by adding static if and and other things. However, this hasn't completely removed the difficulties with C++ templates and they have added so many things that you might end up even more confused. You would think that C++ was the last making that mistake but no, Rust did it again. Rust decided to include macro_rules which uses a declarative syntax. Just as in C++ this totally messes up the readability and your way of thinking. Later on Rust realized the mistake and added function macros as well. Do not make computer languages schizophrenic by mixing programming paradigms.
Oct 14 2021
On Thursday, 14 October 2021 at 18:55:53 UTC, IGotD- wrote:On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:they added `if constexpr` not `static if`, which is another thing to add to the list of worst features implemented. The critical difference is that `if constexpr` always adds a scope whereas `static if` doesn't. Adding a scope if you need it costs you {}. This prevents `if constexpr` from being able to conditionally declare declarations (variables, members, members functions etc.)* Worst features implemented in a non-toy languageThis is not a feature but a language design question. One of the worst thins you can ever do to language is to mix language paradigms. This totally messes up the language as well as your brain. One of example is C++ template programming which is based on ML. Lately in newer C++ they have tried to taint that mistake up by adding static if
Oct 14 2021
On Friday, 15 October 2021 at 03:38:56 UTC, Nicholas Wilson wrote:they added `if constexpr` not `static if`, which is another thing to add to the list of worst features implemented. The critical difference is that `if constexpr` always adds a scope whereas `static if` doesn't. Adding a scope if you need it costs you {}. This prevents `if constexpr` from being able to conditionally declare declarations (variables, members, members functions etc.)Actually that avoids many tricky problems in the compiler implementation. When an inline metaprogram can add declarations that requires the compiler to have support for deferred and partial symbol resolution. At least if you want it work consistently. Static if, works in most cases that I've seen it used... But then again a case that didn't work wouldn't end up in production code so it's hard to tell. When you start playing around with it a bit you'll find it can have very bizarre behavior.
Oct 15 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy language * Worst features (in your opinion) in D * Features you'd like to see in D Ideas? Examples? Thanks!About Wrong D features: In my opinion, **D is afraid of embracing decisions with all it's consequences**... it maintains itself in a position where nothing is "the best for niche X" **i.e.:** UFCS has not been really embraced with all it's consequences D doesn't allow this ```d "hello".(s){ s.writeln; } ``` Of course, you can introduce a template like ```auto doWith(alias f,T)(T v)=>f(v)``` or use the "pipe!" template: ```d "hello".doWith!((s){ s.writeln; }) ``` But then yo find you can't do this ```d void x(string s){ s.writeln; } "hello".x; ``` **i.e.:** The "Nullable" allien!!! D has a complete functional library based on ranges But then, you find an alien named "Nullable" that is not the equivalent to Optional/Some/None and has not the range capabilities (map, fold, ...). How difficult will be to embrace the Optional/Some/None pattern in phobos? D needs to assume it's responsibility standardizing this kind of decisions giving a solid base to other "high level" libraries like database ones (i.e.: managing nullable fields in a "functional" way using the Optional pattern). **i.e.:** GC/Not GC. I really don't want to enter here, but I'm unhappy with this kind of discussions and I find myself driven to use other languages where they have made that decision clearly: Nim has GC (you can select the GC strategy), Rust has not GC. **i.e.:** **Official "high level" libraries for common uses** (i.e.: Database libraries) 1 week ago I "returned" to D after some months... I need to perform a simple database task (with postgres) and I found that dpq2 was the most "recommended" one (Dlang site itself). It has vibe-d dependency (nice!!! may be it's based on fibers!!!) The library didn't compile (it references an old vive-d version with deprecated code)... I created an issue on github with the problem and maintainer didn't recognize the problem (initially). Finally I modified manually the library and tried to run the example proposed in "examples" folder but DMD couldn't compile because some strange missing things on system libraries with my Ubuntu... I have not mentioned that for checking it, I first created an small webserver using **the example you can find in D home page**... surprise!!! it didn't compile neither because references the same vive-d deprecated version (after updating the version, all worked enought). It was enough for me. May be next year :-) (and it will be my N-D try).
Oct 15 2021
On Friday, 15 October 2021 at 09:47:48 UTC, Antonio wrote:Rust has not GC.Rust has GC, i.e. reference counting. This is also often required with multiple ownership which you often end up with in data structures. I would rather say GC is mandatory in Rust, unless you want to take the unsafe approach. It's a matter what you regard as GC. Is only tracing GC regarded as true GC?
Oct 15 2021
On Friday, 15 October 2021 at 09:53:18 UTC, IGotD- wrote:On Friday, 15 October 2021 at 09:47:48 UTC, Antonio wrote:Hi IGotD- really fast response :-) Nim has reference counting too (combined with "cycle" detection "true" GC)... I really love not to use the "ownership" pattern (it's like strait jacket)... some "functional" tries with Rust results in "hard to read" code... As time goes by, I find it harder to be imperative. When I say that GC/Not GC is a problem is because there is an eternal discussion in forums and D maintains itself "neutral" when, in fact, it is a GC language... There is Walter experimental tries to introduce "ownership" equivalent (at least last time I review), there is people requesting a non GC based Phobos library... I consider myself an "external observer". May be D must introduce the Nim filosofy about GC( select your best option: Pure GC, Counter + GC, Counter only) and developer must be responsible about avoiding problems under the selected scenary, and Phobos must be compatible with the most restrictive one (Counter only) My point is about D must be clear and advance, it's impossible to keep everyone happy.Rust has not GC.Rust has GC, i.e. reference counting. This is also often required with multiple ownership which you often end up with in data structures. I would rather say GC is mandatory in Rust, unless you want to take the unsafe approach. It's a matter what you regard as GC. Is only tracing GC regarded as true GC?
Oct 15 2021
On Friday, 15 October 2021 at 09:47:48 UTC, Antonio wrote:On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:I'm not sure what you mean by your gc/nogc comment. Could you clarify? D allows for all approaches afaik[...]About Wrong D features: In my opinion, **D is afraid of embracing decisions with all it's consequences**... it maintains itself in a position where nothing is "the best for niche X" [...]
Oct 15 2021
On Friday, 15 October 2021 at 10:26:51 UTC, Imperatorn wrote:On Friday, 15 October 2021 at 09:47:48 UTC, Antonio wrote:I think that's his problem. D doesn't have a specific philosophy about memory management.On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:I'm not sure what you mean by your gc/nogc comment. Could you clarify? D allows for all approaches afaik[...]About Wrong D features: In my opinion, **D is afraid of embracing decisions with all it's consequences**... it maintains itself in a position where nothing is "the best for niche X" [...]
Oct 15 2021
On Friday, 15 October 2021 at 10:58:14 UTC, bauss wrote:I think that's his problem. D doesn't have a specific philosophy about memory management.This is fine. But here is the deal: that means D cannot have a philosophy on safety. Or have closure allocated on the GC by default. Or a gazilion other things. It's the same problem, just in another dimension: a decision is made, ut then consequences are not accepted.
Oct 15 2021
On Friday, 15 October 2021 at 11:57:28 UTC, deadalnix wrote:On Friday, 15 October 2021 at 10:58:14 UTC, bauss wrote:using allocators aware APIs solves all of this, look at zig! it is a problem already solved, use allocators and don't assume one is using GC or other means -- on the nullable thingy, i agree 100%, we now got 2 way for ``null`` - ``null`` keyword - ``isNull`` method nice! in the std! it's standard now!..I think that's his problem. D doesn't have a specific philosophy about memory management.This is fine. But here is the deal: that means D cannot have a philosophy on safety. Or have closure allocated on the GC by default. Or a gazilion other things. It's the same problem, just in another dimension: a decision is made, ut then consequences are not accepted.
Oct 15 2021
On Friday, 15 October 2021 at 13:21:25 UTC, russhy wrote:on the nullable thingy, i agree 100%, we now got 2 way for ``null`` - ``null`` keyword - ``isNull`` method nice! in the std! it's standard now!..This is just bad naming--`isNull` should be called `empty`. It has nothing to do with `null`.
Oct 15 2021
On Friday, 15 October 2021 at 13:30:46 UTC, Paul Backus wrote:On Friday, 15 October 2021 at 13:21:25 UTC, russhy wrote:Now let's break code again and rename it!on the nullable thingy, i agree 100%, we now got 2 way for ``null`` - ``null`` keyword - ``isNull`` method nice! in the std! it's standard now!..This is just bad naming--`isNull` should be called `empty`. It has nothing to do with `null`.
Oct 15 2021
On Friday, 15 October 2021 at 13:21:25 UTC, russhy wrote:On Friday, 15 October 2021 at 11:57:28 UTC, deadalnix wrote:Many D construct assume a GC. Which kinda is the point. Either you don't assume a GC and go the zig road, or you assume a GC. But D is trying to have its cake and eat it too, and the result is schizophrenic in nature. At some point you need to chose a path. And if you don't want to chose a path at level N to leave that to the user, then you need to pick a path at level N-1 or bellow.On Friday, 15 October 2021 at 10:58:14 UTC, bauss wrote:using allocators aware APIs solves all of this, look at zig! it is a problem already solved, use allocators and don't assume one is using GC or other meansI think that's his problem. D doesn't have a specific philosophy about memory management.This is fine. But here is the deal: that means D cannot have a philosophy on safety. Or have closure allocated on the GC by default. Or a gazilion other things. It's the same problem, just in another dimension: a decision is made, ut then consequences are not accepted.
Oct 15 2021
On Friday, 15 October 2021 at 13:45:11 UTC, deadalnix wrote:Many D construct assume a GC. Which kinda is the point. Either you don't assume a GC and go the zig road, or you assume a GC. But D is trying to have its cake and eat it too, and the result is schizophrenic in nature.This problem could still be solved by making the GC just another allocator (and make it the default global allocator). D's current GC only runs when an allocation is made anyway, so doing this shouldn't break the behavior of existing code (except leaking memory if the constructs that assume GC is used, of course). Maybe from this point on those constructs can be made to use reference counting instead and make sure they're allocator-independent.
Oct 15 2021
On Friday, 15 October 2021 at 14:24:16 UTC, SomeGuy wrote:On Friday, 15 October 2021 at 13:45:11 UTC, deadalnix wrote:Bring back new and make it configurable 😎Many D construct assume a GC. Which kinda is the point. Either you don't assume a GC and go the zig road, or you assume a GC. But D is trying to have its cake and eat it too, and the result is schizophrenic in nature.This problem could still be solved by making the GC just another allocator (and make it the default global allocator). D's current GC only runs when an allocation is made anyway, so doing this shouldn't break the behavior of existing code (except leaking memory if the constructs that assume GC is used, of course). Maybe from this point on those constructs can be made to use reference counting instead and make sure they're allocator-independent.
Oct 15 2021
On Friday, 15 October 2021 at 15:17:11 UTC, Imperatorn wrote:On Friday, 15 October 2021 at 14:24:16 UTC, SomeGuy wrote:Maybe I can make LWDR do this.On Friday, 15 October 2021 at 13:45:11 UTC, deadalnix wrote:Bring back new and make it configurable 😎[...]This problem could still be solved by making the GC just another allocator (and make it the default global allocator). D's current GC only runs when an allocation is made anyway, so doing this shouldn't break the behavior of existing code (except leaking memory if the constructs that assume GC is used, of course). Maybe from this point on those constructs can be made to use reference counting instead and make sure they're allocator-independent.
Oct 15 2021
On Friday, 15 October 2021 at 14:24:16 UTC, SomeGuy wrote:This problem could still be solved by making the GC just another allocator (and make it the default global allocator). D's current GC only runs when an allocation is made anyway, so doing this shouldn't break the behavior of existing code (except leaking memory if the constructs that assume GC is used, of course). Maybe from this point on those constructs can be made to use reference counting instead and make sure they're allocator-independent.The biggest obstacle is that D has no fat pointers. It has only pointers which is enough when you have tracing GC but not enough if your pointers requires extra metadata. This is one of the biggest mistakes in D which limits the possibility to change GC type. Other languages like Nim have a reference types which is a fat pointer type. Nim has gone through more GC types in a shorter time than D. Fat pointers come at a cost though which might be extra dereferences as your data is an inner pointer member. In practice this is already possible in D as a library solution. Problem is that you cannot easily change Druntime/Phobos to also use your custom GC.
Oct 15 2021
On Friday, 15 October 2021 at 15:42:13 UTC, IGotD- wrote:On Friday, 15 October 2021 at 14:24:16 UTC, SomeGuy wrote:Er, that's not how Nim's "fat pointers" work and the term is either misleading or wrong, sizeof(ref) == sizeof(void*) in Nim land.[...]The biggest obstacle is that D has no fat pointers. It has only pointers which is enough when you have tracing GC but not enough if your pointers requires extra metadata. This is one of the biggest mistakes in D which limits the possibility to change GC type. Other languages like Nim have a reference types which is a fat pointer type. Nim has gone through more GC types in a shorter time than D. Fat pointers come at a cost though which might be extra dereferences as your data is an inner pointer member. In practice this is already possible in D as a library solution. Problem is that you cannot easily change Druntime/Phobos to also use your custom GC.
Oct 15 2021
On Friday, 15 October 2021 at 16:05:13 UTC, Araq wrote:Er, that's not how Nim's "fat pointers" work and the term is either misleading or wrong, sizeof(ref) == sizeof(void*) in Nim land.So how do they work then, when you have set the GC to default ORC?
Oct 15 2021
On Friday, 15 October 2021 at 16:10:04 UTC, IGotD- wrote:On Friday, 15 October 2021 at 16:05:13 UTC, Araq wrote:The RC and metadata are stored at negative offsets.Er, that's not how Nim's "fat pointers" work and the term is either misleading or wrong, sizeof(ref) == sizeof(void*) in Nim land.So how do they work then, when you have set the GC to default ORC?
Oct 15 2021
On Friday, 15 October 2021 at 17:17:33 UTC, Araq wrote:The RC and metadata are stored at negative offsets.I was thinking. One way for D which has common GC/raw pointers is to always allocate metadata at negative offsets. Then we D compiler can have hooks that runs when a pointer is copied, moved or goes out of scope. At negative offsets can have a flag field that tells us if the memory is GC allocated or not. If it is not GC it just jumps over the hook code. Drawbacks with this solution is the the raw C malloc/free cannot be used and a wrapped D version must be used that allocates additional space for the metadata. Also non GC memory will have a penalty with the hooks, as it needs to check the type all the time. For the current GC these hooks would be empty though. Is this penalty we can live with?
Oct 15 2021
On Saturday, 16 October 2021 at 00:16:07 UTC, IGotD- wrote:Is this penalty we can live with?Probably but it's a hack, the proper solution is to fix the type system. And since this the topic already: Not distinguishing between traced and untraced pointers (or between owned and unowned pointers for that matter) is indeed one of the "worst" language features.
Oct 15 2021
On Friday, 15 October 2021 at 15:42:13 UTC, IGotD- wrote:The biggest obstacle is that D has no fat pointers. It has only pointers which is enough when you have tracing GC but not enough if your pointers requires extra metadata. This is one of the biggest mistakes in D which limits the possibility to change GC type. Other languages like Nim have a reference types which is a fat pointer type. Nim has gone through more GC types in a shorter time than D. Fat pointers come at a cost though which might be extra dereferences as your data is an inner pointer member. In practice this is already possible in D as a library solution. Problem is that you cannot easily change Druntime/Phobos to also use your custom GC.Yeah, what I was proposing is not actually for adding custom GC types, it is for gradually phasing out the GC (for libraries) and maybe replace it with some `reference counted` type like Rust has. When people complain about GC in D it's mostly because the library ecosystem is by default ` YesGC`. TBH I like having a GC and using it when I don't care about memory usage or speed. This mostly when I use D as a Python replacement and it does its job well. The problem is when I want to use D as a C++ replacement. When I try to do that, I can't D libraries that are not ` nogc`. I want library developers to design their interfaces after considering allowing the usage of different allocators. Because if that happens then I could pass the GC as the allocator parameter and not care about memory management, or maybe I want to pass my own arena allocator when I'm thinking about cache locality or whatever. Otherwise we're risking two different library ecosystems coexisting (one ` nogc` and one ` yesgc`) and that means we'll never have a good library ecosystem. Just let the application developers pass whatever allocator parameter into the libraries (and actually make the stdlib work this way to set an example). If the current situation persists, D is just "C" or "Go" with more features and much fewer libraries. I'm okay with D not having the ecosystem of C (or Rust, or Go) and building everything from ground-up, most people wouldn't be. Don't tell me we have great interop with C and C++, I'm using D because I want to minimize my exposure to C & C++. I hope the situation changes, because if it doesn't Zig will eat D's lunch even though it is actually a worse language (with probably a better ecosystem). Or maybe Jai will if the situation doesn't change before Jai is released (and everybody knows it won't be released for years, still). That'd be especially saddening since Jai is actually just D with different syntax, no GC and more powerful CTFE. That's literally it.
Oct 15 2021
On Friday, 15 October 2021 at 16:21:32 UTC, SomeGuy wrote:When people complain about GC in D it's mostly because the library ecosystem is by default ` YesGC`. TBH I like having a GC and using it when I don't care about memory usage or speed. This mostly when I use D as a Python replacement and it does its job well.You kind have to, the alternative being that the library aren't YesGC as you say, and then whatever reference they manipulate is now invisible to the GC. That may cause library users to see their object being collected when they are still alive and a whole slue of similar problem. If you want the language to support a GC, you *HAVE TO* have the library allocate anything using the GC. From there you have several options: 1/ Not use a GC at all and do manual memory management à la C++. 2/ Use a GC for everything à la Java. 3/ Not use a GC an use an ownership system instead à la Rust. 4/ Allow for manual memory management via GC free, but in which case the compiler can't prove anything, so things like safe or nogc cannot work by design. 5/ Use a GC *AND* an ownership system that allow the compiler to prove invariant about freeing (and even do a lot of it automatically) so things like safe can work (and nogc needs to forbid GC leaks rather than GC allocations). D correspond to none of the above, even though it tries to be kind of 4 kind of 5. Then end result in practice is that almost everything uses the GC, and that safe and nogc are almost useless.
Oct 15 2021
On Friday, 15 October 2021 at 16:44:57 UTC, deadalnix wrote:Then end result in practice is that almost everything uses the GC, and that safe and nogc are almost useless.Is there anything we can do to start addressing this, and the other woes people have brought up? The answer is likely no, so I foresee these same things popping up over and over and over again with no resolution since we seem to have dug ourselves into a corner.
Oct 15 2021
On Friday, 15 October 2021 at 21:55:55 UTC, SealabJaster wrote:On Friday, 15 October 2021 at 16:44:57 UTC, deadalnix wrote:Well at some point we need to make choices about the invariant we want and stick with them. Considering D's values, I'd say the solution that make sense is to allocate using the GC, have an ownership system on top of it that can free most things safely. You'll note that is is possible to build a GC that is as fast as malloc free (for instance, I was able to build a GC on top of jemalloc, and the only thing I had to add is one hashmap store when allocating chunk of size bigger than 4MB. this happens almost never and when it does, memory allocation is usually not the problem as simply filling these 4MB with literally anything is far more work than the work the allocator does (to be 100% fair, this doesn't work with all mallocs, a tcmalloc style structure wouldn't cut it for instance, but jemalloc is notorious to be one of the fastest and bestest so we are not making a big concession). So using a GC instead of malloc/free is very much viable. In fact, because we know if something is shared or not, I bet we can do something that is even faster than traditional mallocs. So we allocate on the GC, always and use ownership on top of it. Ownership should allow you to express common allocation/disposition patterns, and when you can't, either you leak to the GC, or you free explicitly, which is unsafe. That require repurposing nogc as preventing leaking from the ownership system to the GC rather than allocating on the GC - which in itself is no problem if the allocations are freed properly. There are a ton of added benefit that come attached to this if done properly, like solving a ton of problems with shared. Even tricky situations such as nogc exception become trivial in that model. Consider: ```d void foo() { // Allocate the exception using the GC. The exception is // an owned(Exception), and the corresponding overload from // the runtime is called. // Ownership of the exception is transferred to the runtime. // The ownership system didn't lose track of the exception, so // foo can be nogc . throw new Exception(); } void bar() { try { foo(); } catch(Exception e) { // The ownership of the Exception is transferred back to the // user's code. The Exception doesn't leave the catch block, // so it can be freed automatically without the user having to // do anything. // In practice, that require the runtime to provide the // exception handler with knowledge of the exception being // owned or not and a runtime check, so that, if it is owned // it is freed. // bar can also be nogc , because either the exception is owned // in which case it is freed and no leak occurred, or the exception // is not owned, in which case the leak happened somewhere else. // In that case, this somewhere else cannot be nogc . } } ``` You'll note that the ownership system does not need to be as rich as Rust's, because there is always the option to fallback on the GC or on unsafe constructs.Then end result in practice is that almost everything uses the GC, and that safe and nogc are almost useless.Is there anything we can do to start addressing this, and the other woes people have brought up? The answer is likely no, so I foresee these same things popping up over and over and over again with no resolution since we seem to have dug ourselves into a corner.
Oct 15 2021
On Friday, 15 October 2021 at 23:58:34 UTC, deadalnix wrote:On Friday, 15 October 2021 at 21:55:55 UTC, SealabJaster wrote:What is your plan to make GC incremental? what about latency sensitive applications? Can you scale the GC? servers with heaps above 1TB? Both Java and Go can scale their GC and ensure sub 1ms collection without stopping the world I hear you want to stick to the GC no matter what, did you know to target 60 FPS in games, one only has a budget of 16ms per frame Languages with GC can afford one because their GC is competitive and they put lot of R&D in constantly improving and tuning them I'm not saying GC is bad, i'm saying if you want someone to take you seriously, you have to provide serious tools so you can assist them whenever they need to scale their buisnesses Look at ASP.NET team at microsoft, they all working towards improving the C#language so it is much less reliant on the GC Span, value task, ref, stack alloc and bunch of other stuff they D's history is C/C++, why stray away from that history?On Friday, 15 October 2021 at 16:44:57 UTC, deadalnix wrote:Well at some point we need to make choices about the invariant we want and stick with them. Considering D's values, I'd say the solution that make sense is to allocate using the GC, have an ownership system on top of it that can free most things safely. You'll note that is is possible to build a GC that is as fast as malloc free (for instance, I was able to build a GC on top of jemalloc, and the only thing I had to add is one hashmap store when allocating chunk of size bigger than 4MB. this happens almost never and when it does, memory allocation is usually not the problem as simply filling these 4MB with literally anything is far more work than the work the allocator does (to be 100% fair, this doesn't work with all mallocs, a tcmalloc style structure wouldn't cut it for instance, but jemalloc is notorious to be one of the fastest and bestest so we are not making a big concession). So using a GC instead of malloc/free is very much viable. In fact, because we know if something is shared or not, I bet we can do something that is even faster than traditional mallocs. So we allocate on the GC, always and use ownership on top of it. Ownership should allow you to express common allocation/disposition patterns, and when you can't, either you leak to the GC, or you free explicitly, which is unsafe. That require repurposing nogc as preventing leaking from the ownership system to the GC rather than allocating on the GC - which in itself is no problem if the allocations are freed properly. There are a ton of added benefit that come attached to this if done properly, like solving a ton of problems with shared. Even tricky situations such as nogc exception become trivial in that model. Consider: ```d void foo() { // Allocate the exception using the GC. The exception is // an owned(Exception), and the corresponding overload from // the runtime is called. // Ownership of the exception is transferred to the runtime. // The ownership system didn't lose track of the exception, so // foo can be nogc . throw new Exception(); } void bar() { try { foo(); } catch(Exception e) { // The ownership of the Exception is transferred back to the // user's code. The Exception doesn't leave the catch block, // so it can be freed automatically without the user having to // do anything. // In practice, that require the runtime to provide the // exception handler with knowledge of the exception being // owned or not and a runtime check, so that, if it is owned // it is freed. // bar can also be nogc , because either the exception is owned // in which case it is freed and no leak occurred, or the exception // is not owned, in which case the leak happened somewhere else. // In that case, this somewhere else cannot be nogc . } } ``` You'll note that the ownership system does not need to be as rich as Rust's, because there is always the option to fallback on the GC or on unsafe constructs.Then end result in practice is that almost everything uses the GC, and that safe and nogc are almost useless.Is there anything we can do to start addressing this, and the other woes people have brought up? The answer is likely no, so I foresee these same things popping up over and over and over again with no resolution since we seem to have dug ourselves into a corner.
Oct 15 2021
On Saturday, 16 October 2021 at 04:03:29 UTC, russhy wrote:What is your plan to make GC incremental? what about latency sensitive applications?I asserted to write an elaborated answered and then decided to scrap it. Your answer misses the point to a degree that qualifying it of an answer is a stretch to begin with. Long story short: none of the shit is needed if one can free explicitely, and collection cycle only are required when you leak, so really not a problem for anyone who don't leak. You'll get the same performance profile as malloc/free. End of story.D's history is C/C++, why stray away from that history?Because we already have C and C++.
Oct 16 2021
On Saturday, 16 October 2021 at 04:03:29 UTC, russhy wrote:On Friday, 15 October 2021 at 23:58:34 UTC, deadalnix wrote:Hence the solution is to improve the GC 😎[...]What is your plan to make GC incremental? what about latency sensitive applications? [...]
Oct 16 2021
On Saturday, 16 October 2021 at 10:32:59 UTC, Imperatorn wrote:On Saturday, 16 October 2021 at 04:03:29 UTC, russhy wrote:No. Well it doesn't hurt to improve the GC, but no, it isn't the solution.On Friday, 15 October 2021 at 23:58:34 UTC, deadalnix wrote:Hence the solution is to improve the GC 😎[...]What is your plan to make GC incremental? what about latency sensitive applications? [...]
Oct 16 2021
On Saturday, 16 October 2021 at 12:51:26 UTC, deadalnix wrote:On Saturday, 16 October 2021 at 10:32:59 UTC, Imperatorn wrote:I inserted the emoji there but it didn't work 😑On Saturday, 16 October 2021 at 04:03:29 UTC, russhy wrote:No. Well it doesn't hurt to improve the GC, but no, it isn't the solution.On Friday, 15 October 2021 at 23:58:34 UTC, deadalnix wrote:Hence the solution is to improve the GC 😎[...]What is your plan to make GC incremental? what about latency sensitive applications? [...]
Oct 16 2021
On Saturday, 16 October 2021 at 17:18:34 UTC, Imperatorn wrote:On Saturday, 16 October 2021 at 12:51:26 UTC, deadalnix wrote:Works fine here. I just think that it wasn't clear whatever you meant by it.On Saturday, 16 October 2021 at 10:32:59 UTC, Imperatorn wrote:I inserted the emoji there but it didn't work 😑On Saturday, 16 October 2021 at 04:03:29 UTC, russhy wrote:No. Well it doesn't hurt to improve the GC, but no, it isn't the solution.On Friday, 15 October 2021 at 23:58:34 UTC, deadalnix wrote:Hence the solution is to improve the GC 😎[...]What is your plan to make GC incremental? what about latency sensitive applications? [...]
Oct 17 2021
On Friday, 15 October 2021 at 23:58:34 UTC, deadalnix wrote:So using a GC instead of malloc/free is very much viable. In fact, because we know if something is shared or not, I bet we can do something that is even faster than traditional mallocs.Well, yes, malloc is only the default, when people want speed in system level programming they create their own allocators. In order to get to a competitive advantage, D has to decide what its primary use case is. Maybe it would be better for D to position itself as a higher level language with some lower level features. I think also GC and malloc can be combined and improved on. You could probably get better performance and less fragmentation if the allocation contained a hint of when it statistically would be released. You could also get better performance by providing information about typical allocation patterns and sizes. But without a clear vision of what the key use cases for the language is, getting a direction on all of this is going to be difficult. (Much easier to make tough decision if you have a clear picture of what the main use scenario is.)
Oct 18 2021
On Monday, 18 October 2021 at 11:08:08 UTC, Ola Fosheim Grøstad wrote:Well, yes, malloc is only the default, when people want speed in system level programming they create their own allocators.It doesn't matter. These allocator need memory from the system and almost always use malloc do get it. Which as far as the GC is concerned, it the only thing that is needed. It doesn't matter if you malloc each object or if you malloc a large slab and then manage it manually.
Oct 18 2021
On Monday, 18 October 2021 at 11:33:02 UTC, deadalnix wrote:It doesn't matter. These allocator need memory from the system and almost always use malloc do get it.Yes, but often times they don't release it until program exit.
Oct 18 2021
On Monday, 18 October 2021 at 11:38:46 UTC, Ola Fosheim Grøstad wrote:On Monday, 18 October 2021 at 11:33:02 UTC, deadalnix wrote:That still doesn't change anything to the point made.It doesn't matter. These allocator need memory from the system and almost always use malloc do get it.Yes, but often times they don't release it until program exit.
Oct 18 2021
On Monday, 18 October 2021 at 11:33:02 UTC, deadalnix wrote:On Monday, 18 October 2021 at 11:08:08 UTC, Ola Fosheim Grøstad wrote:and then you freeze all threads and must scan all allocated pointers whenever your "gc'd malloc"'s buffer needs to growWell, yes, malloc is only the default, when people want speed in system level programming they create their own allocators.It doesn't matter. These allocator need memory from the system and almost always use malloc do get it. Which as far as the GC is concerned, it the only thing that is needed. It doesn't matter if you malloc each object or if you malloc a large slab and then manage it manually.In order to get to a competitive advantage, D has to decide what its primary use case is. >Maybe it would be better for D to position itself as a higher level language with some >lower level features.I think also GC and malloc can be combined and improved on. You could probably get better >performance and less fragmentation if the allocation contained a hint of when it >statistically would be released. You could also get better performance by providinginformation about typical allocation patterns and sizes.But without a clear vision of what the key use cases for the language is, getting a >direction on all of this is going to be difficult. (Much easier to make tough decision if >you have a clear picture of what the main use scenario is.)you can't compete with highlevel languages and their sub 1ms incremental GC that's very depressing to focus on whether or not we should use the GC that is not the question we should ask, the question is: what problem do we want to solve AGAIN ASP.net team is working hard on reducing the impact of the GC in their library!!!! even thought they have a competitive GC, they are making sure they don't do useless GC allocations and are using Span/stackalloc/ValueTysk everywhere!! Learn from them, don't be like their old-them and saying, we should use and embrace GC everywhere That is not how you make fast and competing software...... The smart and pragmatic approach is to give tools for people to write efficient software Allocators is one of them And it doesn't change the way people code, if they want to use a GC, they are free to do it so But go tell an graphics engine programmer to use a GC, he'll laugh at you Vulkan is meant to be used with an allocator https://gpuopen.com/vulkan-memory-allocator/ That is the pragmatic way of designing portable and efficient libraries Have we lost our mind focusing on the GC? i think yes
Oct 18 2021
On Monday, 18 October 2021 at 14:39:35 UTC, russhy wrote:and then you freeze all threads and must scan all allocated pointers whenever your "gc'd malloc"'s buffer needs to growAn unsolvable problem, clearly, as it is inconceivable that the user could set a heap size. Don't believe anyone that would tell you this could boils down to a simple call to a function, such as GC.setHeapSize(XXXX), they are clearly manipulating you.you can't compete with highlevel languages and their sub 1ms incremental GCLet me tell you a secret. most modern languages use an hybrid approach as the one I described, and even old one have been repurposed to use that when possible (for instance python).AGAIN ASP.net team is working hard on reducing the impact of the GC in their library!!!! even thought they have a competitive GC, they are making sure they don't do useless GC allocations and are using Span/stackalloc/ValueTysk everywhere!!Ho, damn, a hybrid approach that allocates on the stack or the GC and frees instead of leaking. Who could have though of that?The smart and pragmatic approach is to give tools for people to write efficient software Allocators is one of themHow the strawman screaming in between you hear doing?Have we lost our mind focusing on the GC? i think yesWith all due respect, you clearly are not able to address the points made in the discussions you are participating in. It's harsh, but it's true. You shouldn't be making statements about others losing their mind.
Oct 18 2021
On Monday, 18 October 2021 at 15:22:30 UTC, deadalnix wrote:On Monday, 18 October 2021 at 14:39:35 UTC, russhy wrote:You miss the point.. What problem are you trying to solve? I'm trying to solve the problem that we don't encourage people to write their latency sensitive programs in D and instead fallback to C++ (game engines for example), because std isn't built in the idea that they can provide their own allocation schemes Be pragmatic, please Can we at least agree that the work on https://dlang.org/phobos/std_experimental_allocator.html must be resumed and moved out of experimental?and then you freeze all threads and must scan all allocated pointers whenever your "gc'd malloc"'s buffer needs to growAn unsolvable problem, clearly, as it is inconceivable that the user could set a heap size. Don't believe anyone that would tell you this could boils down to a simple call to a function, such as GC.setHeapSize(XXXX), they are clearly manipulating you.you can't compete with highlevel languages and their sub 1ms incremental GCLet me tell you a secret. most modern languages use an hybrid approach as the one I described, and even old one have been repurposed to use that when possible (for instance python).AGAIN ASP.net team is working hard on reducing the impact of the GC in their library!!!! even thought they have a competitive GC, they are making sure they don't do useless GC allocations and are using Span/stackalloc/ValueTysk everywhere!!Ho, damn, a hybrid approach that allocates on the stack or the GC and frees instead of leaking. Who could have though of that?The smart and pragmatic approach is to give tools for people to write efficient software Allocators is one of themHow the strawman screaming in between you hear doing?Have we lost our mind focusing on the GC? i think yesWith all due respect, you clearly are not able to address the points made in the discussions you are participating in. It's harsh, but it's true. You shouldn't be making statements about others losing their mind.
Oct 18 2021
On Monday, 18 October 2021 at 18:12:49 UTC, russhy wrote:Can we at least agree that the work on https://dlang.org/phobos/std_experimental_allocator.html must be resumed and moved out of experimental?std.experimental is where modules go to die. Nothing ever leaves it.
Oct 19 2021
On Tuesday, 19 October 2021 at 07:02:01 UTC, bauss wrote:On Monday, 18 October 2021 at 18:12:49 UTC, russhy wrote:We really should move `allocator` into normal `std` namespace though. It will somewhat help us get to parity with `Zig`, which does this at a language level, I believe.Can we at least agree that the work on https://dlang.org/phobos/std_experimental_allocator.html must be resumed and moved out of experimental?std.experimental is where modules go to die. Nothing ever leaves it.
Oct 19 2021
On Monday, 18 October 2021 at 14:39:35 UTC, russhy wrote:you can't compete with highlevel languages and their sub 1ms incremental GC ASP.net team is working hard on reducing the impact of the GC in their library!When GC flies out of the window, it shouldn't matter whether it's sub 1ms incremental or what.
Oct 20 2021
On Wednesday, 20 October 2021 at 08:09:18 UTC, Kagamin wrote:On Monday, 18 October 2021 at 14:39:35 UTC, russhy wrote:Are we getting rid of the GC? :D I never read about any of that here, can you please share the source of this amazing info :)you can't compete with highlevel languages and their sub 1ms incremental GC ASP.net team is working hard on reducing the impact of the GC in their library!When GC flies out of the window, it shouldn't matter whether it's sub 1ms incremental or what.
Oct 20 2021
On Wednesday, 20 October 2021 at 10:50:26 UTC, Tejas wrote:Are we getting rid of the GC? :DIn the ASP.net team sense.I never read about any of that here, can you please share the source of this amazing info :)https://dlang.org/phobos/std_container_array.html
Oct 20 2021
On Friday, 15 October 2021 at 21:55:55 UTC, SealabJaster wrote:On Friday, 15 October 2021 at 16:44:57 UTC, deadalnix wrote:In the end, i think it doesn't really matter to be honest, as long as we make sure that additions to the STD doesn't make assumption about the memory allocation strategy, we'll be fine The library authors will be free to use what ever is best for their libraries/program STD will be here to assist them, rather than enforce them into something One thing to mention is that entertainment is, more and more, and faster than ever, being consumed online, in dematerialized ways, that includes games and anything VR/AR/XR There will be a massive need of software being built, games being created for various kind devices and for multiple experiences WASM will be important, game engines/framework built for it will be needed And those kind of libraries will avoid GC'd langauges to maximize perf Web stuff is a problem already solved, trying to chase it is a dead end Our best bet i believe, is believe is to target those devs, for their engine needs, they need something that helps them be in control over the memory allocations they wish, but let them consume our libraries, they'll depend on D forever, they'll appreciate D, and maybe they'll also use D for their gameplay code instead of having to glue one Making the STD empower that is i believe important I think the best short term move that will help in the very long term is to finally finish ``STD.EXPERIMENTAL.ALLOCATORS`` and put it in ``STD.MEM`` It's a little bit bloated, it'll need a little lifting What its author has to say?Then end result in practice is that almost everything uses the GC, and that safe and nogc are almost useless.Is there anything we can do to start addressing this, and the other woes people have brought up? The answer is likely no, so I foresee these same things popping up over and over and over again with no resolution since we seem to have dug ourselves into a corner.
Oct 15 2021
On Saturday, 16 October 2021 at 05:37:40 UTC, russhy wrote:In the end, i think it doesn't really matter to be honest, as long as we make sure that additions to the STD doesn't make assumption about the memory allocation strategy, we'll be fineThat really doesn't work in practice, as it prevent libraries from allocating at all.
Oct 16 2021
On Friday, 15 October 2021 at 14:24:16 UTC, SomeGuy wrote:On Friday, 15 October 2021 at 13:45:11 UTC, deadalnix wrote:Yes i agree with you, that would make everyone happy and would be transparent without breaking any existing codeMany D construct assume a GC. Which kinda is the point. Either you don't assume a GC and go the zig road, or you assume a GC. But D is trying to have its cake and eat it too, and the result is schizophrenic in nature.This problem could still be solved by making the GC just another allocator (and make it the default global allocator). D's current GC only runs when an allocation is made anyway, so doing this shouldn't break the behavior of existing code (except leaking memory if the constructs that assume GC is used, of course). Maybe from this point on those constructs can be made to use reference counting instead and make sure they're allocator-independent.
Oct 15 2021
On Friday, 15 October 2021 at 13:21:25 UTC, russhy wrote:On Friday, 15 October 2021 at 11:57:28 UTC, deadalnix wrote:Except safety, using Zig is no better than Modula-2, as it doesn't prevent use-after-free bugs.On Friday, 15 October 2021 at 10:58:14 UTC, bauss wrote:using allocators aware APIs solves all of this, look at zig! it is a problem already solved, use allocators and don't assume one is using GC or other means -- on the nullable thingy, i agree 100%, we now got 2 way for ``null`` - ``null`` keyword - ``isNull`` method nice! in the std! it's standard now!..[...]This is fine. But here is the deal: that means D cannot have a philosophy on safety. Or have closure allocated on the GC by default. Or a gazilion other things. It's the same problem, just in another dimension: a decision is made, ut then consequences are not accepted.
Oct 15 2021
On Friday, 15 October 2021 at 10:58:14 UTC, bauss wrote:On Friday, 15 October 2021 at 10:26:51 UTC, Imperatorn wrote:Oh, I see 😎On Friday, 15 October 2021 at 09:47:48 UTC, Antonio wrote:I think that's his problem. D doesn't have a specific philosophy about memory management.On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:I'm not sure what you mean by your gc/nogc comment. Could you clarify? D allows for all approaches afaik[...]About Wrong D features: In my opinion, **D is afraid of embracing decisions with all it's consequences**... it maintains itself in a position where nothing is "the best for niche X" [...]
Oct 15 2021
On Friday, 15 October 2021 at 17:14:10 UTC, Andrei Alexandrescu wrote:I have one! noreturnContext: Andrei is expressing his frustration with noreturn in discord due to the poor implementation and testing of it. -Alex
Oct 15 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:* Worst features implemented in a non-toy languageDifficult to say, features may not be bad in isolation, but turn bad when combined with other features. Features can turn bad when they can be abused for more terse source code in ways the language designers did not intend, or when scripting languages are used for larger programs. But by-name parameter passing is pretty bad. Having expressions passed into a function executed multiple times backfires real fast in imperative languages. Such bugs can be difficult to identify.* Worst features (in your opinion) in DLack of consistency (unnecessary complexity?) in the meta-programming feature set / type system, but cannot be fixed as it would become a different language.* Features you'd like to see in DSimplify the language. Flow typing. A type system that makes it possible for the compiler to reason about ownership. Implementation: clean separation between front-end and back-end.
Oct 15 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy language- records implementation - object promotion - array covariance - half baked generics - operator overloading verbosity - mutability by default - New nullable semantics* Worst features (in your opinion) in D- Module private instead of class private - Integer promotion - Phobos names (cryptic, completely different from other languages) - Autodecoding - Foreach_reverse (useless) - Two mechanism for foreach (opApply & popFront) - Traits as a library - Real (D standardised primitive types, but here it comes with a machine dependent one) - ff as init value for chars - Dub as package manager - Unqualified parameter passing (if a parameter is ref, you must pass it prefixed with ref)* Features you'd like to see in D- Unittest naming - Benchmarks included in language similar to unittests - Templated class/interface inheritance - Shared (truly implemented) - Cent (truly implemented) - Range concept as language built in - Safe by default - Nullable/Optional as language featureIdeas? Examples? Thanks!
Oct 15 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:* Worst features (in your opinion) in DFinally got one for D. - Phobos always being compiled in release, regardless of whether you compile your application in release mode or not. Which leads to issues like this: https://forum.dlang.org/thread/skjrdf$2buv$1 digitalmars.com And also opens up for buffer overflow for anyone using Phobos. It's by far one of the most serious issue D has had in years.
Oct 19 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy languageOld but still nice: https://eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design/* Worst features (in your opinion) in D- Every not-fully-implemented/half backed feature added prematurely.* Features you'd like to see in DFirst thing I notice when I switch from android development: real string interpolation
Oct 20 2021
On Wednesday, 20 October 2021 at 08:17:48 UTC, Andrea Fontana wrote:On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:This has been worked on several times. The community has trouble agreeing on how it should look / work it seems.I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy languageOld but still nice: https://eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design/* Worst features (in your opinion) in D- Every not-fully-implemented/half backed feature added prematurely.* Features you'd like to see in DFirst thing I notice when I switch from android development: real string interpolation
Oct 20 2021
On Wednesday, 20 October 2021 at 08:17:48 UTC, Andrea Fontana wrote:First thing I notice when I switch from android development: real string interpolationIf there's one feature that shows the severe split between "BUT GC", "BUT NOGC", "BUT EASE OF USE", "BUT POWAH", "BUT PRINTF(For some ungodly reason)", "BUT BUT BUT". That one is it.
Oct 20 2021
On Wednesday, 20 October 2021 at 08:54:17 UTC, SealabJaster wrote:If there's one feature that shows the severe split between "BUT GC", "BUT NOGC", "BUT EASE OF USE", "BUT POWAH", "BUT PRINTF(For some ungodly reason)", "BUT BUT BUT". That one is it.Why are many using D using printf to begin with and not the D equivalent like writeln?
Oct 20 2021
On Wednesday, 20 October 2021 at 09:32:15 UTC, IGotD- wrote:Why are many using D using printf to begin with and not the D equivalent like writeln?In the case of the string interpolation DIP, from what I remember it was mostly Walter was very adamant on string interpolation being printf compatible. In the general case, I assume people using `printf` are mostly GC-phobic, or are just in general writing nogc code. Here's the DIP, including the links to the discussion threads: https://github.com/dlang/DIPs/blob/master/DIPs/rejected/DIP1027.md I can't be bothered myself to skim through things to pick out examples, but feel free to do so yourself.
Oct 20 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy language * Worst features (in your opinion) in D * Features you'd like to see in D Ideas? Examples? Thanks!completely pointless in web development because it will deserialize invalid values. If you have ``` public enum Animal { Cat = 1, Dog = 2, Bird = 3 } ``` 1. You can still load a database row where the Animal value is, say, 200, and it will not give you any errors 2. You can still receive a web request for an object with property Animal Pet {get;set;} where the Animal value is 1000 and it will deserialize from JSON and create the object with a non-null Pet property like it did it correctly. When you go to use it, it will not be Cat Dog or Bird. It's so dumb. There is no advantage of using an enum over a type except when setting a value manually, which you will not be doing often in comparison to user supplied values. much a complete failure.
Oct 30 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:* Worst features implemented in a non-toy languagePython: Assign operator meaning different things in different context `x = 3` Can mean "create a new variable x with value 3" or "assign the value 3 to variable x". This can hit you both ways, I had bugs because I misspelled a variable and created a new variable instead of assigning a new value to an existing one, and I inadvertently changed the value of an existing variable instead of creating a new one. Because of this, I am also very skeptical of Rust's "variable shadowing" feature. Python passing by reference unless it doesn't: `i=1; j=i; j+=2 ` -> i = 1, j=3 `li=[1]; lj=li; lj += [2]` -> li = [1,2], lj = [1,2]* Worst features (in your opinion) in D- char[] pretends to be an array but is actually more like a linked list - lots of attributes and keywords* Features you'd like to see in D- Cleaning up the attributes - Making the language simpler, not more complicated Concerning the "or" vs "||" discussion, as a non-native English speaker, I learned programming as a teenager with barely any English knowledge, and was attracted to the C/C++ syntax as it depends less on English compared to Pascal's syntax. An English-agnostic programming language would be nice to help non-native English speakers to get into programming more easily, but how would you replace keywords like "if", "while" or "for"?
Nov 01 2021
On Monday, 1 November 2021 at 09:45:10 UTC, glis-glis wrote:An English-agnostic programming language would be nice to help non-native English speakers to get into programming more easily, but how would you replace keywords like "if", "while" or "for"?You could replace "if" with "?", "??" or "¿" and use "⟳" for loops. However, I've found that this makes code harder to read as you no longer get a visual separation of "numeric expressions" and the main structure of the program. This presumes that you use a regular text editor. If you create a graphical editor, you probably could use only symbols or pictures with good effect, but it is a lot of work to develop such editors.
Nov 01 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy languageWorst line of reasoning for not having a feature is Go that refuses to add exceptions because they don't think people will do cleanup correctly, instead you are faced with 150% more error-handling code (or code that ignore errors). Error handling in Rust also looks pretty atrocious, but I haven't written anything more than toy programs in Rust.
Nov 06 2021
On Saturday, 6 November 2021 at 11:45:18 UTC, Ola Fosheim Grøstad wrote:On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:Go has exceptions, although they don't call them as such (panic/recover). Rust error handling is not easy by default, however there are some helper libraries to make it easier to do rail oriented programming, and they are in the process of adding vocabulary types for improved error handling, based on the experience of those libraries.I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy languageWorst line of reasoning for not having a feature is Go that refuses to add exceptions because they don't think people will do cleanup correctly, instead you are faced with 150% more error-handling code (or code that ignore errors). Error handling in Rust also looks pretty atrocious, but I haven't written anything more than toy programs in Rust.
Nov 06 2021
On Saturday, 6 November 2021 at 19:13:11 UTC, Paulo Pinto wrote:Go has exceptions, although they don't call them as such (panic/recover).They discourage using it for regular errors, and Go programmers seem to swallow the very noice error-checking regime. Panic recover is also quite clunky and runtime dependent. Yes, I personally use it as clunky hack to emulate exceptions, but it is much less maintainable.programming, and they are in the process of adding vocabulary types for improved error handling, based on the experience of those libraries.Are they extending the language?
Nov 06 2021
On Saturday, 6 November 2021 at 19:36:19 UTC, Ola Fosheim Grøstad wrote:On Saturday, 6 November 2021 at 19:13:11 UTC, Paulo Pinto wrote:I meant "very noisy"…Go has exceptions, although they don't call them as such (panic/recover).They discourage using it for regular errors, and Go programmers seem to swallow the very noice error-checking regime. Panic
Nov 06 2021
On Saturday, 6 November 2021 at 19:36:19 UTC, Ola Fosheim Grøstad wrote:On Saturday, 6 November 2021 at 19:13:11 UTC, Paulo Pinto wrote:Have a look here, https://blog.rust-lang.org/inside-rust/2021/07/01/What-the-error-handling-project-group-is-working-towards.htmlGo has exceptions, although they don't call them as such (panic/recover).They discourage using it for regular errors, and Go programmers seem to swallow the very noice error-checking regime. Panic recover is also quite clunky and runtime dependent. Yes, I personally use it as clunky hack to emulate exceptions, but it is much less maintainable.programming, and they are in the process of adding vocabulary types for improved error handling, based on the experience of those libraries.Are they extending the language?
Nov 06 2021
On Saturday, 6 November 2021 at 19:13:11 UTC, Paulo Pinto wrote:On Saturday, 6 November 2021 at 11:45:18 UTC, Ola Fosheim Grøstad wrote:I thought Rust error handling wasn't easy by default until they added the ? operator, at which point it became like exceptions but better. To me that was always the issue with error handling without exceptions - how to easily just propagate it up (nearly always what one wants to do). I think they nailed it.On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:Go has exceptions, although they don't call them as such (panic/recover). Rust error handling is not easy by default, however there are some helper libraries to make it easier to do rail oriented programming, and they are in the process of adding vocabulary types for improved error handling, based on the experience of those libraries.I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy languageWorst line of reasoning for not having a feature is Go that refuses to add exceptions because they don't think people will do cleanup correctly, instead you are faced with 150% more error-handling code (or code that ignore errors). Error handling in Rust also looks pretty atrocious, but I haven't written anything more than toy programs in Rust.
Nov 08 2021
On Monday, 8 November 2021 at 14:08:32 UTC, Atila Neves wrote:I thought Rust error handling wasn't easy by default until they added the ? operator, at which point it became like exceptions but better.Looks like syntactical sugar to me, but I am no Rust expert. It means you now loose context, and how do you log?To me that was always the issue with error handling without exceptions - how to easily just propagate it up (nearly always what one wants to do). I think they nailed it.For simple situations maybe, but it looks like a hack, as far as I can tell from the docs.
Nov 08 2021
On Monday, 8 November 2021 at 14:23:15 UTC, Ola Fosheim Grøstad wrote:On Monday, 8 November 2021 at 14:08:32 UTC, Atila Neves wrote:It propagates the error to the caller, so you don't lose context, as the error still needs to be handled somewhere, you just don't explicitly have to return the error from your function etc. If you need to log the error at the specific location etc. then you just don't use the ? operator. If the same mechanic existed in D then it would be something like: ```d Result!(int,Error) bar(); Result!(int,Error) foo(int x) { auto i = bar()?; return result(i * x); } void main() { auto r = foo(10); if (r.error) { // Error ... } else { writeln(r.value); } } ``` Which would translate to: ```d Result!(int,Error) bar(); Result!(int,Error) foo(int x) { auto r = bar(); if (r.error) return r; auto i = r.value; return result(i * x); } void main() { auto r = foo(10); if (r.error) { // Error ... } else { writeln(r.value); } } ``` Of course the if statements would be using pattern matching for Ok and Error, which it does in Rust. But felt lazy.I thought Rust error handling wasn't easy by default until they added the ? operator, at which point it became like exceptions but better.Looks like syntactical sugar to me, but I am no Rust expert. It means you now loose context, and how do you log?
Nov 09 2021
On Tuesday, 9 November 2021 at 10:58:34 UTC, bauss wrote:On Monday, 8 November 2021 at 14:23:15 UTC, Ola Fosheim Grøstad wrote:As a library author you don't know what the application is interested in. Anyway, they are working on retaining context, so the Rust developers apparently see this as being an issue. If you can only use "?" in one location without loosing context that basically establishes it as being the quick hack it looks like (by reading the docs).On Monday, 8 November 2021 at 14:08:32 UTC, Atila Neves wrote:It propagates the error to the caller, so you don't lose context, as the error still needs to be handled somewhere, you just don't explicitly have to return the error from your function etc. If you need to log the error at the specific location etc. then you just don't use the ? operator.I thought Rust error handling wasn't easy by default until they added the ? operator, at which point it became like exceptions but better.Looks like syntactical sugar to me, but I am no Rust expert. It means you now loose context, and how do you log?
Nov 09 2021
On Tuesday, 9 November 2021 at 11:09:07 UTC, Ola Fosheim Grøstad wrote:On Tuesday, 9 November 2021 at 10:58:34 UTC, bauss wrote:Yeah, it's definitely a quick hack. It was added to just remove the verbosity that you had otherwise.On Monday, 8 November 2021 at 14:23:15 UTC, Ola Fosheim Grøstad wrote:As a library author you don't know what the application is interested in. Anyway, they are working on retaining context, so the Rust developers apparently see this as being an issue. If you can only use "?" in one location without loosing context that basically establishes it as being the quick hack it looks like (by reading the docs).On Monday, 8 November 2021 at 14:08:32 UTC, Atila Neves wrote:It propagates the error to the caller, so you don't lose context, as the error still needs to be handled somewhere, you just don't explicitly have to return the error from your function etc. If you need to log the error at the specific location etc. then you just don't use the ? operator.I thought Rust error handling wasn't easy by default until they added the ? operator, at which point it became like exceptions but better.Looks like syntactical sugar to me, but I am no Rust expert. It means you now loose context, and how do you log?
Nov 09 2021
On Monday, 8 November 2021 at 14:23:15 UTC, Ola Fosheim Grøstad wrote:On Monday, 8 November 2021 at 14:08:32 UTC, Atila Neves wrote:Correct, but then again, anything other than machine code is syntatical sugar. So is `throw new Exception("oh noes");`I thought Rust error handling wasn't easy by default until they added the ? operator, at which point it became like exceptions but better.Looks like syntactical sugar to me, but I am no Rust expert.It means you now loose contextI don't see how.and how do you log?The same way in pretty much any and all programs written that handles exceptions - some outer loop, possibly in the main function.I disagree. To me, it has all the convenience of exceptions with none of the drawbacks.To me that was always the issue with error handling without exceptions - how to easily just propagate it up (nearly always what one wants to do). I think they nailed it.For simple situations maybe, but it looks like a hack, as far as I can tell from the docs.
Nov 09 2021
On Tuesday, 9 November 2021 at 11:37:49 UTC, Atila Neves wrote:Correct, but then again, anything other than machine code is syntatical sugar. So is `throw new Exception("oh noes");`No, syntactical sugar has nothing to do with the machine. It is sugar if it can be fully/easily replaced by other language constructs with no semantic/typing changes. You technically can totally restructure a program with exceptions to one without, it is a rather comprehensive transformation. You usually treat exceptions as a separate construct when reasoning about the type system.In D you can throw a wide variety of exceptions and propagate them without even knowing that they were thrown. D even retains the exception chain… (perhaps too much context for most use cases). Clearly you loose context by "?" in comparison? Python also allows you to trace the stack… that is a lot of context…It means you now loose contextI don't see how.
Nov 09 2021
On Tuesday, 9 November 2021 at 13:26:20 UTC, Ola Fosheim Grøstad wrote:On Tuesday, 9 November 2021 at 11:37:49 UTC, Atila Neves wrote:If there are no exceptions and one is returning regular values, then the call stack is... the call stack. Given that "?" returns the original failure with whatever extra data it had, I really don't see what the difference is.In D you can throw a wide variety of exceptions and propagate them without even knowing that they were thrown. D even retains the exception chain… (perhaps too much context for most use cases). Clearly you loose context by "?" in comparison? Python also allows you to trace the stack… that is a lot of context…It means you now loose contextI don't see how.
Nov 09 2021
On 09.11.21 16:39, Atila Neves wrote:On Tuesday, 9 November 2021 at 13:26:20 UTC, Ola Fosheim Grøstad wrote:Having a stack trace with line numbers is a big deal in case the exception was unexpected.On Tuesday, 9 November 2021 at 11:37:49 UTC, Atila Neves wrote:If there are no exceptions and one is returning regular values, then the call stack is... the call stack. Given that "?" returns the original failure with whatever extra data it had, I really don't see what the difference is.In D you can throw a wide variety of exceptions and propagate them without even knowing that they were thrown. D even retains the exception chain… (perhaps too much context for most use cases). Clearly you loose context by "?" in comparison? Python also allows you to trace the stack… that is a lot of context…It means you now loose contextI don't see how.
Nov 09 2021
On Tuesday, 9 November 2021 at 16:44:50 UTC, Timon Gehr wrote:On 09.11.21 16:39, Atila Neves wrote:Good point. I hadn't thought of that.On Tuesday, 9 November 2021 at 13:26:20 UTC, Ola Fosheim Grøstad wrote:Having a stack trace with line numbers is a big deal in case the exception was unexpected.[...]If there are no exceptions and one is returning regular values, then the call stack is... the call stack. Given that "?" returns the original failure with whatever extra data it had, I really don't see what the difference is.
Nov 09 2021
On Tuesday, 9 November 2021 at 17:16:52 UTC, Atila Neves wrote:Not a big deal IMO. Stack traces are not the main feature of exceptions anyway. Now granted that the error is a bit harder to track down without the stack trace but we don't put stack traces to `null`s or `NaN`s either. We insert logging statements separately if we want to prepare for tracking an unexpected bug.Having a stack trace with line numbers is a big deal in case the exception was unexpected.Good point. I hadn't thought of that.
Nov 09 2021
On Tuesday, 9 November 2021 at 11:37:49 UTC, Atila Neves wrote:On Monday, 8 November 2021 at 14:23:15 UTC, Ola Fosheim Grøstad wrote:Actually, Rust also has exceptions but like Go, it's ashamed to admit it: https://doc.rust-lang.org/std/panic/fn.catch_unwind.html It's supposed to be used only for unrecoverable runtime errors (panics in Rust parlance).On Monday, 8 November 2021 at 14:08:32 UTC, Atila Neves wrote:Correct, but then again, anything other than machine code is syntatical sugar. So is `throw new Exception("oh noes");`I thought Rust error handling wasn't easy by default until they added the ? operator, at which point it became like exceptions but better.Looks like syntactical sugar to me, but I am no Rust expert.It means you now loose contextI don't see how.and how do you log?The same way in pretty much any and all programs written that handles exceptions - some outer loop, possibly in the main function.I disagree. To me, it has all the convenience of exceptions with none of the drawbacks.To me that was always the issue with error handling without exceptions - how to easily just propagate it up (nearly always what one wants to do). I think they nailed it.For simple situations maybe, but it looks like a hack, as far as I can tell from the docs.
Nov 23 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy language * Worst features (in your opinion) in D * Features you'd like to see in D Ideas? Examples? Thanks!I'd say being able to do the same thing, multiple ways. IMO. It's the worst feature, and yet, it's also the best feature.
Nov 09 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy language * Worst features (in your opinion) in D * Features you'd like to see in D Ideas? Examples? Thanks!I don't think I've answered yet, even tho I have responded to a couple others. I don't really have many things to add that others haven't said but I just have this one thing to say:* Worst features (in your opinion) in DThe way D solves problems is by adding new features (such as attributes etc.) - but what ends up happening is that each problem solved by adding a new feature, introduces a new set of problems; often the old problem isn't even fixed properly either because the new feature is either a) not implemented entirely b) not working as intended - and then we somehow ends up with a new feature to fix the new feature. It's an endless loop that D has put itself into. I'm not sure if it can be fixed, nor am I even sure that I could think of a way to fix it. Which brings me to:* Features you'd like to see in DI'd like to see everything currently in D finished, instead of introducing new features. Sometimes less is more.
Nov 15 2021
On Mon, Nov 15, 2021 at 02:23:03PM +0000, bauss via Digitalmars-d wrote: [...]+1. We've a lot of unfinished/incomplete things: shared, std.experimental.allocator, etc.. It's more fun to implement new things, but *somebody* has to do the grunt work of polishing what's already there. T -- Once bitten, twice cry...* Features you'd like to see in DI'd like to see everything currently in D finished, instead of introducing new features. Sometimes less is more.
Nov 15 2021
* Worst features implemented in a non-toy language? * Worst features (in your opinion) in D * Features you'd like to see in D Undisputed first place: Reference types (ptrs, function ptrs, arrays, classes, etc.) are nullable by default in Java and many others, including D. D could have had `int*` and `int*?`, `int function()` and `int function?()`, `int[]` and `int[]?`, `Object` and `Object?`. `std.typecons.Nullable` is basically a type constructor, and faking one via templates only works half-way (for example, `const(int)?` and `const(int?)` are the same type). Distinguishing nullable types is very useful documentation-wise. If you do this, enable nullable for every type, even if `int?` is implemented by a plain bool-int pair. For me, second place for bad D feature: function types. Not function *pointer* types but mere function types. They aren't even documented, so it's technically a bug that they exist. --- A few other nuisances that are just unnecessary to work around and have absolutely no justification existing: 1. Cannot initialize an empty AA by `[ ]`. Especially a nuisances when wanting to pass an empty AA as an argument to a function. 2. The `new` keyword is needed to allocate class objects. Makes meta-programming annoying, and one cannot have a literal pointer like `new int(1)` for, say, `Object`. 3. One cannot express every type (not counting encapsulation, i.e. Voldemort types) directly: Notably, one cannot express a function pointer returning by reference in a function argument list.
Nov 15 2021
* Worst features implemented in a non-toy language* C: zero-terminated strings * Python 3: Metaclasses (they violate the philosophy of Python that code should be explicit, obvious and not "clever") * C++: where to start... * Java: the int/Integer (and similar) duality, made even worse by automatic boxing/unboxing * Still Java: Generic types erasure* Worst features (in your opinion) in DI never really used D for anything beyond simple toy programs, but from reading about it it doesn't seem to have any truly egregious features as such apart from autodecoding. The main problem that I see is that everything is kind of half-baked, unfinished, features get added in a pursuit of the Great-Opportunity-of-the-week but they don't work coherently together.
Nov 23 2021
On Wednesday, 24 November 2021 at 06:28:35 UTC, arco wrote: The funniest part is that it's often not the deep users of D who say D is bad.
Nov 23 2021
On Wednesday, 24 November 2021 at 06:48:12 UTC, zjh wrote:On Wednesday, 24 November 2021 at 06:28:35 UTC, arco wrote: The funniest part is that it's often not the deep users of D who say D is bad.Well... Bubble, echo chamber, baby duck syndrome and all that. When people are not heavy users of D, there may often have a reason. Many language communities actively listen to what the critics say and often try to acknowledge or even address the issues. If Dlang just wants to dismiss criticism as being irrelevant because it comes from someone who doesn't really use D, then all that will achieve is that 10 years from now there will still be threads "Why is D not popular?" ;)
Nov 23 2021
On Wednesday, 24 November 2021 at 06:48:12 UTC, zjh wrote:The funniest part is that it's often not the deep users of D who say D is bad.Brags about other languages, and is critical of D. Bad money drives out `good` money.
Nov 23 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:* Worst features implemented in a non-toy language * Worst features (in your opinion) in DI am a bit late to this party :) but after reading all 29 pages of it I would say most of it is said except this one thing: I hate language constructs that go in opposite order from my thoughts making me type something then having to navigate back to add another thing. Best example for this is casting in any language. I always have to write cast operator before the thing I am casting yet in my head I never think "then I need to cast to int the variable X that I want to add". I think more like "Then I need to add variable X but I have to cast it to int".
Dec 17 2021
On Friday, 17 December 2021 at 13:14:50 UTC, Igor wrote:On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:You must love the `to` template in `std.conv` then :P* Worst features implemented in a non-toy language * Worst features (in your opinion) in DI am a bit late to this party :) but after reading all 29 pages of it I would say most of it is said except this one thing: I hate language constructs that go in opposite order from my thoughts making me type something then having to navigate back to add another thing. Best example for this is casting in any language. I always have to write cast operator before the thing I am casting yet in my head I never think "then I need to cast to int the variable X that I want to add". I think more like "Then I need to add variable X but I have to cast it to int".
Dec 17 2021
On Friday, 17 December 2021 at 13:33:00 UTC, Tejas wrote:On Friday, 17 December 2021 at 13:14:50 UTC, Igor wrote:That's indeed a good way to have cast as postfix expressions except that `to` is more than cast, as it also checks for overflow and can throw.On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:You must love the `to` template in `std.conv` then :P[...]I am a bit late to this party :) but after reading all 29 pages of it I would say most of it is said except this one thing: I hate language constructs that go in opposite order from my thoughts making me type something then having to navigate back to add another thing. Best example for this is casting in any language. I always have to write cast operator before the thing I am casting yet in my head I never think "then I need to cast to int the variable X that I want to add". I think more like "Then I need to add variable X but I have to cast it to int".
Dec 17 2021
On Friday, 17 December 2021 at 17:50:25 UTC, user1234 wrote:On Friday, 17 December 2021 at 13:33:00 UTC, Tejas wrote:Those are not good things?On Friday, 17 December 2021 at 13:14:50 UTC, Igor wrote:That's indeed a good way to have cast as postfix expressions except that `to` is more than cast, as it also checks for overflow and can throw.[...]You must love the `to` template in `std.conv` then :P
Dec 17 2021
On Friday, 17 December 2021 at 13:14:50 UTC, Igor wrote:On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:In sql you can write ```cast(field as type)```. semantics are not 100% equivalent to the usual cast operator ().* Worst features implemented in a non-toy language * Worst features (in your opinion) in DI am a bit late to this party :) but after reading all 29 pages of it I would say most of it is said except this one thing: I hate language constructs that go in opposite order from my thoughts making me type something then having to navigate back to add another thing. Best example for this is casting in any language. I always have to write cast operator before the thing I am casting yet in my head I never think "then I need to cast to int the variable X that I want to add". I think more like "Then I need to add variable X but I have to cast it to int".
Dec 17 2021
On Friday, 17 December 2021 at 13:14:50 UTC, Igor wrote:I hate language constructs that go in opposite order from my thoughts making me type something then having to navigate back to add another thing. Best example for this is casting in any language. I always have to write cast operator before the thing I am casting yet in my head I never think "then I need to cast to int the variable X that I want to add". I think more like "Then I need to add variable X but I have to cast it to int".I feel the same about writing. But you have to consider how code as TargetType` there. In D, you can do the same: ```D auto ref TargetType as(TargetType, SourceType)(auto ref SourceType object) { return cast(TargetType) object; } auto result = fun(x.as!int).as!string; ``` I'll agree that an operator would look nicer, but – as is more often than not the case with D – if a library solution is found that isn't horrible, the probability that the language will be extended is around 0.
Dec 18 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:* Worst features implemented in a non-toy languageI did some programming at a tech company in 2011, and was introduced to ASP. The default in the webpage-based language was variables were passed around using reference. This of course turns the whole programming understanding on it's head because you assume you pass copies of native types or copy structs to the stack and you can't affect the original variables (unless you intend to or they are classes passed around). So to get around to expected normal behavior you have to put ByVal everywhere on all arguments.
Dec 28 2021
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:I'm brainstorming about what I'll talk about at DConf, and during a conversation with Walter I thought it might be cool to talk about: * Worst features implemented in a non-toy language * Worst features (in your opinion) in D * Features you'd like to see in D Ideas? Examples? Thanks!For me there are two main ones: * A lot of people have said this one but I'll +1 it. Tuples fully built into the language with destructuring and all the common features. A year or two ago I thought this was definitely going to happen. * Relaxing policy on symbolic and infix/prefix/postfix/binary/unary notation, perhaps having protections against using obvious things like "." but relatively free elsewhere. From a science/math point of view this would be great, and it can greatly improve code readability in such applications.
Dec 29 2021
On Wednesday, 29 December 2021 at 20:07:20 UTC, data pulverizer wrote:For me there are two main ones: * A lot of people have said this one but I'll +1 it. Tuples fully built into the language with destructuring and all the common features. A year or two ago I thought this was definitely going to happen. * Relaxing policy on symbolic and infix/prefix/postfix/binary/unary notation, perhaps having protections against using obvious things like "." but relatively free elsewhere. From a science/math point of view this would be great, and it can greatly improve code readability in such applications.One more thing, native string interpolation similar to f-strings style in Python or Julia style strings for example ``` auto my_variable = 42; auto output = "The meaning of life is ${my_variable}" ``` I think this also seemed like it was in the works a year or two ago.
Jan 08 2022
On Monday, 11 October 2021 at 15:59:10 UTC, Atila Neves wrote:* Worst features implemented in a non-toy language- C Preprocessor - C Macros - Error handling through return codes - Languages with undecidable grammar* Worst features (in your opinion) in D- I need more time for this to find ones, but mostly it is the half backedness of features* Features you'd like to see in D- structs implementing interfaces - autoboxing structs to interfaces - faster, easier and more powerful CTFE, I think this will come with newCTFE - runtime templates/runtime reflection (not as default, but as an option) I'm unsure about type classes/protocols/concepts/traits, they are, theoretically, clearly superior to OOP, but as we already have classes & interfaces in D, they would be too overlapping, I think.
Apr 23 2022
On 24/04/2022 3:01 AM, sighoya wrote:I'm unsure about type classes/protocols/concepts/traits, they are, theoretically, clearly superior to OOP, but as we already have classes & interfaces in D, they would be too overlapping, I think.Signatures are OOP. Its just that the relationship is inverse of class/interface.
Apr 23 2022