[Issue 17512] [REG 2.073] [DIP1000] Error on bad interplay of "auto ref" and "return" attribute deduction.
https://issues.dlang.org/show_bug.cgi?id=17512 --- Comment #4 from Carsten Blüggel <chi...@posteo.net> --- Another error example from phobos (-dip1000, DMD64 D Compiler v2.078.2): https://github.com/dlang/phobos/blob/master/std/range/package.d std/range/package.d(1738) [referring to roundRobin.Result. @property auto ref front()]: Error: function type pure nothrow @nogc @property return @safe int() has return but does not return any indirections --
[Issue 17512] [REG 2.073] [DIP1000] Error on bad interplay of "auto ref" and "return" attribute deduction.
https://issues.dlang.org/show_bug.cgi?id=17512 Carsten Blüggelchanged: What|Removed |Added Blocks||18444 Referenced Issues: https://issues.dlang.org/show_bug.cgi?id=18444 [Issue 18444] [DIP25][DIP1000] Tracking issue for: "The implementation doesn't match DIPs 25/1000" --
[Issue 18401] New: Auto-generate rdmd man page + HTML documentation
https://issues.dlang.org/show_bug.cgi?id=18401 Issue ID: 18401 Summary: Auto-generate rdmd man page + HTML documentation Product: D Version: D2 Hardware: All OS: All Status: NEW Severity: enhancement Priority: P1 Component: tools Assignee: nob...@puremagic.com Reporter: greensunn...@gmail.com These pages have a tendency to get outdated: https://github.com/dlang/tools/blob/master/man/man1/rdmd.1 https://dlang.org/rdmd.html We should generate them like we do for dmd. They are even outdated atm - search for `--shebang` on the man page. --
[Issue 18329] std.algorithm.startsWith & endsWith can sometimes statically determine auto-decoding unnecessary
https://issues.dlang.org/show_bug.cgi?id=18329 Nathan S. <n8sh.second...@hotmail.com> changed: What|Removed |Added Summary|std.algorithm.startsWith & |std.algorithm.startsWith & |endsWith can sometimes |endsWith can sometimes |avoid auto-decoding |statically determine | |auto-decoding unnecessary --
[Issue 18329] New: std.algorithm.startsWith & endsWith can sometimes avoid auto-decoding
https://issues.dlang.org/show_bug.cgi?id=18329 Issue ID: 18329 Summary: std.algorithm.startsWith & endsWith can sometimes avoid auto-decoding Product: D Version: D2 Hardware: All OS: All Status: NEW Severity: enhancement Priority: P1 Component: phobos Assignee: nob...@puremagic.com Reporter: n8sh.second...@hotmail.com std.algorithm.startsWith & endsWith with a narrow string and a single-char/wchar/dchar search term can sometimes avoid auto-decoding. --
[Issue 17512] [REG 2.073] [DIP1000] Error on bad interplay of "auto ref" and "return" attribute deduction.
https://issues.dlang.org/show_bug.cgi?id=17512 Carsten Blüggelchanged: What|Removed |Added CC||chi...@posteo.net --
[Issue 18000] [scope] auto-generated opAssign not scope aware
https://issues.dlang.org/show_bug.cgi?id=18000 Carsten Blüggelchanged: What|Removed |Added CC||chi...@posteo.net --
[Issue 18262] stdx.allocator.building_blocks.bitmapped_block has spurious failures on the auto-tester
https://issues.dlang.org/show_bug.cgi?id=18262 Basile B.changed: What|Removed |Added Status|NEW |RESOLVED CC||b2.t...@gmx.com Resolution|--- |DUPLICATE --- Comment #1 from Basile B. --- *** This issue has been marked as a duplicate of issue 18140 *** --
[Issue 18262] New: stdx.allocator.building_blocks.bitmapped_block has spurious failures on the auto-tester
https://issues.dlang.org/show_bug.cgi?id=18262 Issue ID: 18262 Summary: stdx.allocator.building_blocks.bitmapped_block has spurious failures on the auto-tester Product: D Version: D2 Hardware: x86_64 OS: Mac OS X Status: NEW Severity: normal Priority: P1 Component: phobos Assignee: nob...@puremagic.com Reporter: greensunn...@gmail.com core.exception.AssertError@std/experimental/allocator/building_blocks/bitmapped_block.d(177): Data must be aligned properly 4 test_runner 0x00010ab6496b onAssertErrorMsg + 107 5 test_runner 0x00010ab64bc8 _d_assert_msg + 68 6 test_runner 0x00010a68049b pure ref std.experimental.allocator.building_blocks.bitmapped_block.BitmappedBlock!(128uL, 16u, std.experimental.allocator.building_blocks.null_allocator.NullAllocator).BitmappedBlock std.experimental.allocator.building_blocks.bitmapped_block.BitmappedBlock!(128uL, 16u, std.experimental.allocator.building_blocks.null_allocator.NullAllocator).BitmappedBlock.__ctor(ubyte[]) + 111 7 test_runner 0x00010a682dd2 pure std.experimental.allocator.building_blocks.bitmapped_block.BitmappedBlock!(128uL, 16u, std.experimental.allocator.building_blocks.null_allocator.NullAllocator).BitmappedBlock std.experimental.allocator.building_blocks.bitmapped_block.BitmappedBlock!(128uL, 16u, std.experimental.allocator.building_blocks.null_allocator.NullAllocator).BitmappedBlock.__unittest_std_experimental_allocator_building_blocks_bitmapped_block_57_16().__lambda2() + 102 8 test_runner 0x00010a68258b void std.experimental.allocator.common.testAllocator!(std.experimental.allocator.building_blocks.bitmapped_block.BitmappedBlock!(128uL, 16u, std.experimental.allocator.building_blocks.null_allocator.NullAllocator).BitmappedBlock.__unittest_std_experimental_allocator_building_blocks_bitmapped_block_57_16().__lambda2()).testAllocator() + 39 9 test_runner 0x00010a680316 void std.experimental.allocator.building_blocks.bitmapped_block.BitmappedBlock!(128uL, 16u, std.experimental.allocator.building_blocks.null_allocator.NullAllocator).BitmappedBlock.__unittest_std_experimental_allocator_building_blocks_bitmapped_block_57_16() + 74 10 test_runner 0x00010a67ed65 void std.experimental.allocator.building_blocks.affix_allocator.__modtest() + 53 11 test_runner 0x000109610683 void test_runner.doTest(object.ModuleInfo*, ref core.runtime.UnitTestResult) + 99 12 test_runner 0x00010961058b core.runtime.UnitTestResult test_runner.testModules() + 395 13 test_runner 0x0001096103d7 core.runtime.UnitTestResult test_runner.tester() + 31 14 test_runner 0x00010ab656a3 runModuleUnitTests + 151 15 test_runner 0x00010ab7a3b5 void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).runAll() + 37 16 test_runner 0x00010ab7a333 void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(scope void delegate()) + 51 17 test_runner 0x00010ab7a296 _d_run_main + 814 18 test_runner 0x000109610285 main + 33 19 test_runner 0x000109610243 start + 51 20 ??? 0x0001 0x0 + 1 make[1]: *** [unittest/std/experimental/allocator/building_blocks/affix_allocator.run] Error 1 make[1]: *** Waiting for unfinished jobs 0.031s PASS debug64 std.experimental.allocator.building_blocks.allocator_list --
[Issue 18151] New: wrong auto ref lvalue inference for implicitly converted alias this parameters
https://issues.dlang.org/show_bug.cgi?id=18151 Issue ID: 18151 Summary: wrong auto ref lvalue inference for implicitly converted alias this parameters Product: D Version: D2 Hardware: All OS: All Status: NEW Severity: major Priority: P3 Component: dmd Assignee: nob...@puremagic.com Reporter: c...@dawg.eu cat > bug.d << CODE void test()(auto ref Inner inner) { pragma(msg, __traits(isRef, inner) ? "ref" : "value"); } struct Inner { } struct Outer { Inner inner; Inner get() { return inner; } alias get this; } void bug() { Outer outer; test(outer); } CODE dmd -c bug.d ref bug.d(20): Error: outer.get() is not an lvalue Happens apparently because auto ref is resolved before implicit alias this conversion kicks in. --
Re: Please do not use 'auto' return types without thoroughly describing the interface
On Wednesday, 27 December 2017 at 16:36:59 UTC, H. S. Teoh wrote: On Tue, Dec 26, 2017 at 11:28:56AM +, Mark via Digitalmars-d wrote: On Monday, 25 December 2017 at 22:48:39 UTC, H. S. Teoh wrote: > [...] Maybe we can document the interface of the return type using signature constraints? For instance, for the function: auto map(Range)(Range r) if (isInputRange!(Unqual!Range)); we'd add the following to its constraints: isInputRange!(ReturnType!(map!R)) However, this does not compile at the moment. I'm not sure why. I'm not sure why either, but signature constraints are intended to be used for constraining the range of incoming template arguments that the template will accept. It's not intended to establish a contract on what the template is going to produce when instantiated with those arguments, though this could well be an enhancement request. Perhaps this should be filed in bugzilla so that it won't get forgotten. T I guess we could introduce "static in" and "static out" contracts analogous to the existing "in" and "out" contracts, except these would be run at compile-time. But this doesn't seem strictly necessary - the compiler can figure out on its own which constraints depend only on the function's (compile-time) parameters and which constraints also depend on its return type.
Re: Please do not use 'auto' return types without thoroughly describing the interface
On Tue, Dec 26, 2017 at 01:50:06AM +, Neia Neutuladh via Digitalmars-d wrote: > On Monday, 25 December 2017 at 22:48:39 UTC, H. S. Teoh wrote: > > The exact type does not and should not need to be known by user > > code. > > It's a public type reported by some of the documentation but not other > parts. Its capabilities are given vaguely in the docs for the > functions that return it. > > This is a documentation problem, but concrete return types will put a > hard limit on how bad the documentation situation can be. Then the documentation needs to be fixed. Resorting to concrete return types seems to me to be a pessimistic approach, when we should rather be improving the code / docs. > > It's an implementation detail. > > The fact that there is a named type involved is not shocking. If there > is not a named type, we can use something like: > > public alias Regex(Char) = typeof(regex([Char.init])); > > I can add it in my own code too. Pretty much no chance of breakage. > > The fact that two functions return values of the same type is perhaps > an implementation detail, but there's no way to ensure you don't break > user code that way besides using a unique type for each (hello, > std.typecons.Typedef). If more than one function is returning the same type, then that's reasonable grounds to ask for a named return type. OTOH, there's the case where the API may reasonably return distinct types, but just so happens that the present implementation reuses the same type, in which case user code should not rely on the return types being compatible with each other. Your example below of matchFirst vs. matchAll could, arguably, be an example of this category, since conceivably, matchFirst could return a type that encapsulates a single match, whereas matchAll could return a range of such matches. Then potentially a future version of the library could use different return types, even if the current implementation does reuse the same type. Assuming that the return types are compatible is an iffy proposition at best. Keeping the return types opaque helps to discourage this sort of misplaced assumption in user code. > Like I might read the docs and, quite reasonably, write: > > auto capture = needFirst ? matchFirst(str, regex) : matchAll(str, > regex).skip(3).front; > auto process = asShell ? spawnShell("echo hi") : > spawnProcess(["/bin/echo", "hi"]); I think you're missing some context there, I'm not sure what the second line of code has to do with `capture` in the first line. Care to clarify? > And that's suddenly going to stop compiling some day. Maybe. Except > that would be bonkers because nobody's going to write two different > `Captures` structs to be used in nearly identical circumstances. It > would be pointless work to have two different types with the same > interface for processes. Not necessarily, if matchFirst returns a single Match type, say, and matchAll returns a range of Match elements. Then you could very well have different, incompatible return types here. > The fact that it's somehow absolutely essential to maintain this > option in all current cases, but not so essential as to motivate > anyone to deprecate public types for anything or use Typedef > everywhere, is kind of worrying. I wouldn't say it's *absolutely essential*, just that imposing the least amount of constraints on the code (including possible future changes) is a desirable thing to have. T -- If you're not part of the solution, you're part of the precipitate.
Re: Please do not use 'auto' return types without thoroughly describing the interface
On Wednesday, 27 December 2017 at 16:36:59 UTC, H. S. Teoh wrote: The best we can do currently, which unfortunately won't show up in the docs, is to use a static assert to force compilation failure when the return type doesn't match expectations, e.g.: [...] static assert(isInputRange!Result); I'm more concerned about types that are specific to a purpose with an interface that is not standard and widely used across a lot of D code. Which is why I'm talking about std.regex.Captures and not std.algorithm.iteration.MapResult: MapResult is just a range implementation, and ranges are a core concept in D today. And this is about documentation, so a static assert inside the implementation doesn't really help.
Re: Please do not use 'auto' return types without thoroughly describing the interface
On Tue, Dec 26, 2017 at 11:28:56AM +, Mark via Digitalmars-d wrote: > On Monday, 25 December 2017 at 22:48:39 UTC, H. S. Teoh wrote: > > While I agree that all template parameters ought to be documented > > and all auto return types thoroughly described, I disagree with > > explicit naming of auto return types. The whole point of auto return > > types is to return an *opaque* type that user code should not depend > > on, apart from what the documentation says you can do with the type. > > It's a matter of encapsulation, i.e., "you can do X, Y, Z with the > > return value of this function, everything else is none of your > > business". Or, in other words, if your code can't possibly work > > without knowing the explicit type of the return value, then you're > > doing something wrong (using the function wrongly). > > > > T > > Maybe we can document the interface of the return type using signature > constraints? For instance, for the function: > > auto map(Range)(Range r) if (isInputRange!(Unqual!Range)); > > we'd add the following to its constraints: > > isInputRange!(ReturnType!(map!R)) > > However, this does not compile at the moment. I'm not sure why. I'm not sure why either, but signature constraints are intended to be used for constraining the range of incoming template arguments that the template will accept. It's not intended to establish a contract on what the template is going to produce when instantiated with those arguments, though this could well be an enhancement request. Perhaps this should be filed in bugzilla so that it won't get forgotten. The best we can do currently, which unfortunately won't show up in the docs, is to use a static assert to force compilation failure when the return type doesn't match expectations, e.g.: auto myFunc(Args...)(Args args) { struct Result { ... } static assert(isInputRange!Result); return Result(args); } Or similarly: auto myFunc(Args...)(Args args) { return ...; assert(is(typeof(return) == ExpectedType)); } T -- The easy way is the wrong way, and the hard way is the stupid way. Pick one.
Re: Please do not use 'auto' return types without thoroughly describing the interface
On Monday, 25 December 2017 at 22:48:39 UTC, H. S. Teoh wrote: On Mon, Dec 25, 2017 at 04:26:52PM +, Piotr Klos via Digitalmars-d wrote: On Monday, 25 December 2017 at 03:23:33 UTC, Neia Neutuladh wrote: > If you have a function with a return type listed as `auto`, > please thoroughly describe what interface the return value > provides. > I would just like to say that I strongly agree. Lack of documentation of template parameters and other unspecified types in interfaces, like auto return types is one of the primary reasons for people to turn away from template libraries and regard templates as obscure. While I agree that all template parameters ought to be documented and all auto return types thoroughly described, I disagree with explicit naming of auto return types. The whole point of auto return types is to return an *opaque* type that user code should not depend on, apart from what the documentation says you can do with the type. It's a matter of encapsulation, i.e., "you can do X, Y, Z with the return value of this function, everything else is none of your business". Or, in other words, if your code can't possibly work without (...) While I agree with the sentiment that encapsulation is good and all, I think the emphasis is on the wrong thing here. It seems that you are happy to take forever thinking about the right thing to do, even at the price of eternal unusability. The desing goals of standard library should be the exact opposite, i.e. make things 100% usable even at the cost of making less features, and then maybe later make more features if a need appears. If something is not usable yet, it shouldn't be in the stdlib! So in my humble opinion the process for getting something into a stdlib should be create + document + assess usability -> repeat -> publish or reject, not create -> publish -> document, especially for template libs! Otherwise you risk that the lib won't be very usable after all despite the best intentions (if users are even patient enouh to wait for the proper docs). For example look at all the template parameters in boost c++ libraries, most of which are never used.
Re: Please do not use 'auto' return types without thoroughly describing the interface
On Monday, 25 December 2017 at 22:48:39 UTC, H. S. Teoh wrote: While I agree that all template parameters ought to be documented and all auto return types thoroughly described, I disagree with explicit naming of auto return types. The whole point of auto return types is to return an *opaque* type that user code should not depend on, apart from what the documentation says you can do with the type. It's a matter of encapsulation, i.e., "you can do X, Y, Z with the return value of this function, everything else is none of your business". Or, in other words, if your code can't possibly work without knowing the explicit type of the return value, then you're doing something wrong (using the function wrongly). T Maybe we can document the interface of the return type using signature constraints? For instance, for the function: auto map(Range)(Range r) if (isInputRange!(Unqual!Range)); we'd add the following to its constraints: isInputRange!(ReturnType!(map!R)) However, this does not compile at the moment. I'm not sure why.
Re: Please do not use 'auto' return types without thoroughly describing the interface
On Monday, 25 December 2017 at 22:48:39 UTC, H. S. Teoh wrote: The exact type does not and should not need to be known by user code. It's a public type reported by some of the documentation but not other parts. Its capabilities are given vaguely in the docs for the functions that return it. This is a documentation problem, but concrete return types will put a hard limit on how bad the documentation situation can be. It's an implementation detail. The fact that there is a named type involved is not shocking. If there is not a named type, we can use something like: public alias Regex(Char) = typeof(regex([Char.init])); I can add it in my own code too. Pretty much no chance of breakage. The fact that two functions return values of the same type is perhaps an implementation detail, but there's no way to ensure you don't break user code that way besides using a unique type for each (hello, std.typecons.Typedef). Like I might read the docs and, quite reasonably, write: auto capture = needFirst ? matchFirst(str, regex) : matchAll(str, regex).skip(3).front; auto process = asShell ? spawnShell("echo hi") : spawnProcess(["/bin/echo", "hi"]); And that's suddenly going to stop compiling some day. Maybe. Except that would be bonkers because nobody's going to write two different `Captures` structs to be used in nearly identical circumstances. It would be pointless work to have two different types with the same interface for processes. The fact that it's somehow absolutely essential to maintain this option in all current cases, but not so essential as to motivate anyone to deprecate public types for anything or use Typedef everywhere, is kind of worrying.
[Issue 18124] Over-use of `auto` return type in std.regex
https://issues.dlang.org/show_bug.cgi?id=18124 --- Comment #3 from Seb--- > I wasn't aware that a decision to use the type system was bikeshedding. Okay let me go one step back here: I do see your point of explicitly stating the return type, s.t. it's one click away from the user. However, this comes up regularly and as you have seen in your recent NG thread [1] this is a topic with divided minds. Regarding bikeshedding: > spending the majority of its time on discussions about relatively minor but > easy-to-grasp issues, such as what materials to use for the staff bike shed, > while neglecting the proposed design of the plant itself, which is far more > important and a far more difficult and complex task. Maybe it's a better of interpretetion. [1] http://forum.dlang.org/post/plgxyxhvmfwnimuyk...@forum.dlang.org [2] https://en.wikipedia.org/wiki/Law_of_triviality > Just a tip: emoticons can make an otherwise professional comment seem smarmy > or condescending. If you do not intend to seem smarmy or condescending, you > may wish to avoid them. This wasn't my intention. Thanks for the advice! (FYI: I'm doing most of open source work on my phone, so typos arise from time to time and emoticons are in close reach.) --
Re: Please do not use 'auto' return types without thoroughly describing the interface
On Mon, Dec 25, 2017 at 04:26:52PM +, Piotr Klos via Digitalmars-d wrote: > On Monday, 25 December 2017 at 03:23:33 UTC, Neia Neutuladh wrote: > > If you have a function with a return type listed as `auto`, please > > thoroughly describe what interface the return value provides. > > > > I would just like to say that I strongly agree. Lack of documentation > of template parameters and other unspecified types in interfaces, like > auto return types is one of the primary reasons for people to turn > away from template libraries and regard templates as obscure. While I agree that all template parameters ought to be documented and all auto return types thoroughly described, I disagree with explicit naming of auto return types. The whole point of auto return types is to return an *opaque* type that user code should not depend on, apart from what the documentation says you can do with the type. It's a matter of encapsulation, i.e., "you can do X, Y, Z with the return value of this function, everything else is none of your business". Or, in other words, if your code can't possibly work without knowing the explicit type of the return value, then you're doing something wrong (using the function wrongly). Ideally, you shouldn't even be able to create an instance of the type yourself, hence the name Voldemort type (the type that can't be named) though there is a valid use case for storing instances of such types in aggregates like structs and classes. For the latter use case, typeof(...) is your friend. The idea behind this kind of coding style is to make your code as generic as possible, i.e., it will work knowing only the bare minimum about the data it's given, so it can handle a wider variety of data than when types are hard-coded. Naming explicit library types creates an unnecessary dependency between user code and library implementation details, and reduces encapsulation. [...] > > But look at std.regex.RegexMatch.front: > > > > "Functionality for processing subsequent matches of global regexes > > via range interface" > > > > It has an example that mentions a `hit` property. Other parts of the > > RegexMatch interface mention `pre` and `post` properties. What are > > they? It is a mystery! > > > > Turns out that the return type is a Captures struct, and that could > > be made explicit with little effort. (Such as > > https://github.com/dlang/phobos/pull/5963.) [...] I strongly disagree with this kind of change. The exact type does not and should not need to be known by user code. It's an implementation detail. The whole idea is that user code shouldn't need to know what the type is in order to be able to work with it. This is part of the encapsulation of the library type. Making the type name visible to user code means that future Phobos releases can no longer rename the type or otherwise substitute it with something else without breaking user code. This breaks encapsulation. Making the type non-explicit in user code means Phobos can transparently change the concrete type and user code will still work as before after recompilation. Even if you need to store the result in a struct member, you can use typeof(...) to implicitly get the type needed to declare the member. In this case, the typeof(...) will automatically adjust itself to whatever the return type is when a future release of Phobos changes the underlying implementation, so it keeps user code independent of Phobos implementation details and preserves encapsulation. Now granted, if the documentation is unclear about what exactly you can do with the type, then the docs are at fault and need to be improved. If what exactly can be done with .pre and .post isn't made clear, then the docs need to be fixed. But the declaration of such types ought to remain internal to Phobos and opaque to user code. T -- This is a tpyo.
[Issue 18124] Over-use of `auto` return type in std.regex
https://issues.dlang.org/show_bug.cgi?id=18124 --- Comment #2 from Neia Neutuladh--- I wasn't aware that a decision to use the type system was bikeshedding. Just a tip: emoticons can make an otherwise professional comment seem smarmy or condescending. If you do not intend to seem smarmy or condescending, you may wish to avoid them. --
[Issue 18124] Over-use of `auto` return type in std.regex
https://issues.dlang.org/show_bug.cgi?id=18124 Seb <greensunn...@gmail.com> changed: What|Removed |Added Status|NEW |RESOLVED CC||greensunn...@gmail.com Resolution|--- |WONTFIX --- Comment #1 from Seb <greensunn...@gmail.com> --- Advantage of `auto`: - we can change the API - less visual clutter (that's subjective though) See the discussion at https://github.com/dlang/phobos/pull/5963 We have to be careful here, this a bikesheeding topic and a lot time can be wasted with discussing the pros and cons. A good improvement, however, could be to improve Ddoc or documentation, s.t. it helps the reader more what `auto` could be mean and whats capabilities one can expect from it. Please feel free to open a respective issue with concrete for dlang.org ;-) --
Re: Please do not use 'auto' return types without thoroughly describing the interface
On Monday, 25 December 2017 at 03:23:33 UTC, Neia Neutuladh wrote: If you have a function with a return type listed as `auto`, please thoroughly describe what interface the return value provides. I would just like to say that I strongly agree. Lack of documentation of template parameters and other unspecified types in interfaces, like auto return types is one of the primary reasons for people to turn away from template libraries and regard templates as obscure. "Returns a forward range of Elem", where Elem is a template parameter, is fine, for instance. But look at std.regex.RegexMatch.front: "Functionality for processing subsequent matches of global regexes via range interface" It has an example that mentions a `hit` property. Other parts of the RegexMatch interface mention `pre` and `post` properties. What are they? It is a mystery! Turns out that the return type is a Captures struct, and that could be made explicit with little effort. (Such as https://github.com/dlang/phobos/pull/5963.) This *is* redundant. Looking at the source code lets you find the return type in less than thirty seconds. Or you can put into your code: `pragma(msg, ReturnType!(func).stringof);` However, I imagine we'd lose a lot of people in the "see missing documentation" → "look at source code" step. This is not redundant. The documentation doesn't give enough information to use the interface, so its simply incomplete.
Re: Please do not use 'auto' return types without thoroughly describing the interface
I would like to fix this using signatures[0]. Signatures have a number of benefits here, including removing of TypeInfo (which prevents code-bloat). There is a few other examples based upon allocators here[1]. But this isn't a short term goal even if it does get approved ;) [0] https://github.com/rikkimax/DIPs/blob/master/DIPs/DIP1xxx-RC.md [1] https://github.com/rikkimax/stdc-signatures/blob/master/stdc/memory/allocators.d
Please do not use 'auto' return types without thoroughly describing the interface
If you have a function with a return type listed as `auto`, please thoroughly describe what interface the return value provides. "Returns a forward range of Elem", where Elem is a template parameter, is fine, for instance. But look at std.regex.RegexMatch.front: "Functionality for processing subsequent matches of global regexes via range interface" It has an example that mentions a `hit` property. Other parts of the RegexMatch interface mention `pre` and `post` properties. What are they? It is a mystery! Turns out that the return type is a Captures struct, and that could be made explicit with little effort. (Such as https://github.com/dlang/phobos/pull/5963.) This *is* redundant. Looking at the source code lets you find the return type in less than thirty seconds. Or you can put into your code: `pragma(msg, ReturnType!(func).stringof);` However, I imagine we'd lose a lot of people in the "see missing documentation" → "look at source code" step.
[Issue 18124] New: Over-use of `auto` return type in std.regex
https://issues.dlang.org/show_bug.cgi?id=18124 Issue ID: 18124 Summary: Over-use of `auto` return type in std.regex Product: D Version: D2 Hardware: x86_64 OS: Linux Status: NEW Severity: enhancement Priority: P1 Component: phobos Assignee: nob...@puremagic.com Reporter: dhase...@gmail.com auto return types are terrible for documentation. You need to include the full documentation of the return type in the function description, or you need to separately link to the return type. It's a lot nicer and more efficient to simply fill in a concrete return type (when not using voldemort types). std.regex uses `auto` as a return type rather a lot. Sometimes it has okay documentation for what the return type is. Sometimes it doesn't. PR incoming. --
[Issue 17935] [scope] auto-generated destructor not scope aware
https://issues.dlang.org/show_bug.cgi?id=17935 --- Comment #3 from github-bugzi...@puremagic.com --- Commits pushed to stable at https://github.com/dlang/dmd https://github.com/dlang/dmd/commit/c9ff5810a2f449f19a39172461d511c895dcb519 fix Issue 17935 - [scope] auto-generated destructor not scope aware https://github.com/dlang/dmd/commit/0bb4ad1668fa7ea6539c2bf2c7035309afabbdd4 Merge pull request #7283 from WalterBright/fix17935 --
mysql-native v1.1.4: Introduced auto-purge to fix a few problems
An all-D MySQL/MariaDB client library: https://github.com/mysql-d/mysql-native In v1.1.4: Introduced auto-purge to fix a few problems. - Fixed: #117: ResultRange cannot be copied. (@Abscissa) - Fixed: #119: Is a defensive Connection.purgeResult call necessary before executing another statement? (As of this release, the answer changed from "sometimes" to "no") (@Abscissa) - Fixed: #139: Server packet out of order when Prepared is destroyed too early. (@Abscissa) - Change: MySQLDataPendingException (aka, MYXDataPending) is no longer necessary, and no longer thrown. When issuing a command that communicates with the server while a ResultRange still has data pending, instead of throwing, mysql-native now automatically purges the range and safely marks it as invalid and no longer usable. This was changed in order to fix #117, #119, and #139. This change should neither break user code nor require any changes. (@Abscissa) - Change: Manually releasing a prepared statement is no longer guaranteed to notify the server immediately. In order to facilitate the above fixes, and avoid any nasty surprise with struct dtors triggering results purges implicitly, any release of prepared statements from the server is now queued until mysql-native can be certain no data is already pending. This change should neither break user code nor require any changes. (@Abscissa) - Change: Prepared statements are no longer released automatically, due to the fix for #117. However, prepared statements and their lifetimes are tied to individual connections, and thus will die along with their connection, so manual release is not strictly necessary either. Accordingly, this change should neither break user code nor require any changes. (@Abscissa) - Fixed: #143: Keep travis-ci build times under control by limiting the number of compiler versions tested on OSX. (@SingingBush) Tentative plans for the next release (probably v1.2.0) include, among other things, removing the old deprecated APIs from pre-1.0, deprecating a few no-longer-needed things and some misc doc improvements. Aside from those housekeeping details, my other next big priority is to finally tackle the awkwardness of combining prepared statements with connection pools. MySQL itself ties prepared statements to the individual connection that created them, and that's caused difficulties for connection pool users. So I'm thinking a connection-independent abstraction is warranted for prepared statements. Mysql-native is made for its users, so if an issue is particularly pressing for you that you feel has been neglected, vote for your biggest bug-a-boo by pinging it: https://github.com/mysql-d/mysql-native/issues (Or better yet, contribute!)
[Issue 18000] New: [scope] auto-generated opAssign not scope aware
https://issues.dlang.org/show_bug.cgi?id=18000 Issue ID: 18000 Summary: [scope] auto-generated opAssign not scope aware Product: D Version: D2 Hardware: All OS: All Status: NEW Severity: normal Priority: P3 Component: dmd Assignee: nob...@puremagic.com Reporter: c...@dawg.eu cat > bug.d << CODE module bug; struct File { @safe @nogc: ~this() scope { } void* f; } void test() @safe @nogc { scope File f; f = File(); } CODE dmd -c -dip1000 bug bug.d(16): Error: scope variable f assigned to non-scope parameter this calling bug.File.opAssign We should infer scope for any auto-generated functions like opAssign. --
[Issue 17992] New: auto return type and null for classes
https://issues.dlang.org/show_bug.cgi?id=17992 Issue ID: 17992 Summary: auto return type and null for classes Product: D Version: D2 Hardware: All OS: All Status: NEW Severity: normal Priority: P1 Component: dmd Assignee: nob...@puremagic.com Reporter: temta...@gmail.com class C { int v; C parent; C[] childs; auto foo(int a) { a -= v; if(parent && a < 0) { return null; } foreach(c; childs) { if(auto r = c.foo(a)) { pragma(msg, typeof(r)); return r; } } if(parent) { return this; } return null; } } void main() { auto a = new C, b = new C; a.v = 12; b.parent = a; a.childs ~= b; assert(a.foo(123) is b); } It passes, but prints typeof(null) It should print C or give an error with pragma or doesn't compile at all. LDC team says it's impossible to generate code from frontend data so this example doesn't work with ldc. --
[Issue 17935] [scope] auto-generated destructor not scope aware
https://issues.dlang.org/show_bug.cgi?id=17935 --- Comment #2 from github-bugzi...@puremagic.com --- Commits pushed to master at https://github.com/dlang/dmd https://github.com/dlang/dmd/commit/c9ff5810a2f449f19a39172461d511c895dcb519 fix Issue 17935 - [scope] auto-generated destructor not scope aware https://github.com/dlang/dmd/commit/0bb4ad1668fa7ea6539c2bf2c7035309afabbdd4 Merge pull request #7283 from WalterBright/fix17935 fix Issue 17935 - [scope] auto-generated destructor not scope aware merged-on-behalf-of: Mathias Lang <mathias-lang-socioman...@users.noreply.github.com> --
[Issue 17935] [scope] auto-generated destructor not scope aware
https://issues.dlang.org/show_bug.cgi?id=17935 github-bugzi...@puremagic.com changed: What|Removed |Added Status|NEW |RESOLVED Resolution|--- |FIXED --
[Issue 17968] object initializer for auto function not included when seen through 2 libraries
https://issues.dlang.org/show_bug.cgi?id=17968 --- Comment #1 from Steven Schveighoffer--- 2.075.0 still has the same problem. --
[Issue 17968] New: object initializer for auto function not included when seen through 2 libraries
https://issues.dlang.org/show_bug.cgi?id=17968 Issue ID: 17968 Summary: object initializer for auto function not included when seen through 2 libraries Product: D Version: D2 Hardware: All OS: All Status: NEW Keywords: link-failure Severity: normal Priority: P1 Component: dmd Assignee: nob...@puremagic.com Reporter: schvei...@yahoo.com I need to reduce this more. But I can't figure out easily what the trigger is. It has something to do with the auto return. Just wanting to put a bug in place so it's not forgotten. Here is the gist of the situation: I have one library that depends on another. In the first library I have a function like so: auto openDev(int fd) { return ioObject(File(fd)); } ioObject is from another library that looks like this: IOObject!IO ioObject(IO)(IO io) { return new IOObject!IO(io.move); } Where IOObject is a templated class. In a program I am compiling, I have a statement that uses openDev(0). If I compile this, I get a missing symbol, which is this: _D50TypeInfo_xC3std2io__T8IOObjectTSQvQt4file4FileZQBa6__initZ This is the initializer for the IOObject!File, that the ioObject is instantiating. However, it is never instantiated in either library. If I change the auto return to returning IOObject!File, it links and compiles. At that point, the object file of the executable (not either of the libraries) *defines* the symbol (in one case, nm says the symbol is undefined, in the successful case, it says it's defined). I'm not sure what the difference is, but clearly it should define it either way, it shouldn't look to the libraries to define it. I tried reducing to a simple 2-library solution with some simplified code. This did not exhibit the problem. The libraries in question don't compile on anything earlier than 2.076.0, so I am going to work around these issues to see if this ever worked. --
[Issue 17935] [scope] auto-generated destructor not scope aware
https://issues.dlang.org/show_bug.cgi?id=17935 --- Comment #1 from Walter Bright--- https://github.com/dlang/dmd/pull/7283 --
[Issue 17935] New: [scope] auto-generated destructor not scope aware
https://issues.dlang.org/show_bug.cgi?id=17935 Issue ID: 17935 Summary: [scope] auto-generated destructor not scope aware Product: D Version: D2 Hardware: All OS: All Status: NEW Keywords: safe Severity: normal Priority: P4 Component: dmd Assignee: bugzi...@digitalmars.com Reporter: c...@dawg.eu cat > bug.d << CODE struct ByChunk(IO) { @safe: ~this() scope {} ubyte[] buf; IO io; } struct IO { ~this() @safe scope {} } /// @safe @nogc unittest { ubyte[256] buf; auto chunks = ByChunk!IO(buf[], IO()); chunks.__xdtor(); // auto-generated inclusive (fields and struct) dtor } CODE dmd -c -dip1000 bug.d bug.d(21): Error: scope variable `chunks` assigned to non-scope parameter `this` calling bug.ByChunk!(IO).ByChunk.~this bug.d(22): Error: scope variable `chunks` assigned to non-scope parameter `this` calling bug.ByChunk!(IO).ByChunk.~this Guess we should at best always attempt to infer scope for any generate method. --
Re: what means... auto ref Args args?
On Thursday, 19 October 2017 at 01:05:28 UTC, Jonathan M Davis wrote: On Thursday, October 19, 2017 00:00:54 Dave Jones via That's likely the main reason in this case, since losing the ref-ness could definitely cause issues with some constructors, but auto ref is frequently used simply to avoid copying lvalues while not requiring lvalues (since if ref is used, the argument must be an lvalue, and if ref is not used, the argument will be copied if it's an lvalue; it will be moved if it's an rvalue). D never binds rvalues to ref like C++ does with const T&. - Jonathan M Davis Makes sense, thanks.
Re: what means... auto ref Args args?
On Thursday, October 19, 2017 00:00:54 Dave Jones via Digitalmars-d wrote: > On Wednesday, 18 October 2017 at 22:16:32 UTC, Moritz Maxeiner > > wrote: > > On Wednesday, 18 October 2017 at 21:38:41 UTC, Dave Jones wrote: > >> Poking around in the source code for emplace and I noticed... > >> > >> T* emplace(T, Args...)(T* chunk, auto ref Args args) > >> > >> what does the "auto ref" do in this situiation? Cant seem to > >> find any explanation in the docs. > > > > It means that any argument (that is an element of args) will be > > passed by reference if and only if it's an lvalue (has a memory > > address that can be taken) (it'll be passed by value otherwise). > > > > https://dlang.org/spec/template.html#auto-ref-parameters > > So it's just to make sure any "ref" in the eventual call to Ts > constructor is also reflected in the call to emplace? That's likely the main reason in this case, since losing the ref-ness could definitely cause issues with some constructors, but auto ref is frequently used simply to avoid copying lvalues while not requiring lvalues (since if ref is used, the argument must be an lvalue, and if ref is not used, the argument will be copied if it's an lvalue; it will be moved if it's an rvalue). D never binds rvalues to ref like C++ does with const T&. - Jonathan M Davis
Re: what means... auto ref Args args?
On Wednesday, 18 October 2017 at 22:16:32 UTC, Moritz Maxeiner wrote: On Wednesday, 18 October 2017 at 21:38:41 UTC, Dave Jones wrote: Poking around in the source code for emplace and I noticed... T* emplace(T, Args...)(T* chunk, auto ref Args args) what does the "auto ref" do in this situiation? Cant seem to find any explanation in the docs. It means that any argument (that is an element of args) will be passed by reference if and only if it's an lvalue (has a memory address that can be taken) (it'll be passed by value otherwise). https://dlang.org/spec/template.html#auto-ref-parameters So it's just to make sure any "ref" in the eventual call to Ts constructor is also reflected in the call to emplace?
Re: what means... auto ref Args args?
On Wednesday, 18 October 2017 at 21:38:41 UTC, Dave Jones wrote: Poking around in the source code for emplace and I noticed... T* emplace(T, Args...)(T* chunk, auto ref Args args) what does the "auto ref" do in this situiation? Cant seem to find any explanation in the docs. It means that any argument (that is an element of args) will be passed by reference if and only if it's an lvalue (has a memory address that can be taken) (it'll be passed by value otherwise). https://dlang.org/spec/template.html#auto-ref-parameters
Re: what means... auto ref Args args?
On Wednesday, 18 October 2017 at 21:38:41 UTC, Dave Jones wrote: Poking around in the source code for emplace and I noticed... T* emplace(T, Args...)(T* chunk, auto ref Args args) what does the "auto ref" do in this situiation? Cant seem to find any explanation in the docs. sorry meant to put this in learn
what means... auto ref Args args?
Poking around in the source code for emplace and I noticed... T* emplace(T, Args...)(T* chunk, auto ref Args args) what does the "auto ref" do in this situiation? Cant seem to find any explanation in the docs.
Re: template auto deduction
On Friday, 6 October 2017 at 21:42:40 UTC, Steven Schveighoffer wrote: What you need is IFTI or "Implicit Function Template Instantiation" Note the "Function" part of it, in that it's only valid for functions. So you need a factory function: auto m(T)(T x) { return M!(T)(x); } ... auto b = m(fs); // ok There is an enhancement request to make constructors have the same mechanism. Not sure if or when it would be implemented. -Steve Ha! Yes :) Thanks a lot :) That's what is meant by convenience methods inside the library, sometimes...
Re: template auto deduction
On 10/6/17 5:08 PM, Alex wrote: Hey, template gurus :) given this: struct M(alias I : S!E, alias S, E...) { R!E r; this(S)(S initStruct) // line 4 { r = R!E(initStruct); } } struct R(E...) { this(S)(S initStruct) // line 12 { // do some cool stuff } } void main() { FS!(Etype1) fs; auto m = M!(typeof(fs))(fs); // line 21. auto a = M!(fs); // does not work auto b = M(fs); // does not work } struct FS(T...){} struct Etype1{} Everything works as expected, especially line 21. The question is about syntactic sugar: What I have to change, to use auto deduction and to create the M struct like in line 22 or 23? By the way, I'm aware, that the type matching in lines 4 and 12 is lost, in the way it is written here. However, it is meant to exist, if this helps in some way... Thanks a lot in advance Alex What you need is IFTI or "Implicit Function Template Instantiation" Note the "Function" part of it, in that it's only valid for functions. So you need a factory function: auto m(T)(T x) { return M!(T)(x); } ... auto b = m(fs); // ok There is an enhancement request to make constructors have the same mechanism. Not sure if or when it would be implemented. -Steve
template auto deduction
Hey, template gurus :) given this: struct M(alias I : S!E, alias S, E...) { R!E r; this(S)(S initStruct)// line 4 { r = R!E(initStruct); } } struct R(E...) { this(S)(S initStruct)// line 12 { // do some cool stuff } } void main() { FS!(Etype1) fs; auto m = M!(typeof(fs))(fs);// line 21. auto a = M!(fs); // does not work auto b = M(fs); // does not work } struct FS(T...){} struct Etype1{} Everything works as expected, especially line 21. The question is about syntactic sugar: What I have to change, to use auto deduction and to create the M struct like in line 22 or 23? By the way, I'm aware, that the type matching in lines 4 and 12 is lost, in the way it is written here. However, it is meant to exist, if this helps in some way... Thanks a lot in advance Alex
[Issue 15492] ICE (segfault) on class { auto f() with out contract }
https://issues.dlang.org/show_bug.cgi?id=15492 Simon Na.changed: What|Removed |Added Status|NEW |RESOLVED Resolution|--- |WORKSFORME --- Comment #1 from Simon Na. --- With dmd v2.075.1, the source example from 2016-01-01 builds and links without errors, on both Windows and 64-bit Arch. Closing this issue as worksforme. --
Re: if (auto x = cast(C) x)
On Wednesday, 9 August 2017 at 21:54:46 UTC, Q. Schroll wrote: For a class/interface type `A` and a class `C` inheriting from `A` one can do A a = getA(); if (auto c = cast(C) a) { .. use c .. } to get a `C` view on `a` if it happens to be a `C`-instance. Sometimes one cannot find a good new name for `c` while there is no advantage of accessing `a` when `c` is available. D does not allow to shadow `a` in the if-auto declaration for good reasons. How about relaxing the rule for cases like these, where the rhs is the lhs with a cast to derived? if (auto a = cast(C) a) { .. use a typed as C .. } One can think of `a` being *statically* retyped to `C` as this is a (strictly) better type information. Internally, it would be a shadowing, but it does not matter as the disadvantages don't apply (if I didn't miss something). One option is to use https://dlang.org/library/std/algorithm/comparison/cast_switch.html
[Issue 17388] [scope] no escape analysis for auto return scope members
https://issues.dlang.org/show_bug.cgi?id=17388 Walter Bright <bugzi...@digitalmars.com> changed: What|Removed |Added CC||bugzi...@digitalmars.com --- Comment #1 from Walter Bright <bugzi...@digitalmars.com> --- This shrinks down a bit to: struct S { int[] // works //auto// doesn't work foo() return @safe { return x[]; } int[4] x; } @safe int[] f() { S s; return s.foo(); } --
Re: if (auto x = cast(C) x)
On Wednesday, 9 August 2017 at 21:54:46 UTC, Q. Schroll wrote: For a class/interface type `A` and a class `C` inheriting from `A` one can do A a = getA(); if (auto c = cast(C) a) { .. use c .. } to get a `C` view on `a` if it happens to be a `C`-instance. Sometimes one cannot find a good new name for `c` while there is no advantage of accessing `a` when `c` is available. D does not allow to shadow `a` in the if-auto declaration for good reasons. How often do you need this? I wouldn't go as far as saying downcasting is (always) evil, but it can be indicative of suboptimal abstractions [1]. How about relaxing the rule for cases like these, where the rhs is the lhs with a cast to derived? if (auto a = cast(C) a) { .. use a typed as C .. } One can think of `a` being *statically* retyped to `C` as this is a (strictly) better type information. Internally, it would be a shadowing, but it does not matter as the disadvantages don't apply (if I didn't miss something). While I can't see an obvious semantic issue, I would vote against such syntax because it introduces more special cases (and in this case an inconsistency w.r.t. variable shadowing) into the language and I don't see it providing enough of a benefit (downcasting should be used rarely) to justify that. [1] http://codebetter.com/jeremymiller/2006/12/26/downcasting-is-a-code-smell/
if (auto x = cast(C) x)
For a class/interface type `A` and a class `C` inheriting from `A` one can do A a = getA(); if (auto c = cast(C) a) { .. use c .. } to get a `C` view on `a` if it happens to be a `C`-instance. Sometimes one cannot find a good new name for `c` while there is no advantage of accessing `a` when `c` is available. D does not allow to shadow `a` in the if-auto declaration for good reasons. How about relaxing the rule for cases like these, where the rhs is the lhs with a cast to derived? if (auto a = cast(C) a) { .. use a typed as C .. } One can think of `a` being *statically* retyped to `C` as this is a (strictly) better type information. Internally, it would be a shadowing, but it does not matter as the disadvantages don't apply (if I didn't miss something).
[Issue 14669] auto attribute on function parameter should be error always
https://issues.dlang.org/show_bug.cgi?id=14669 --- Comment #3 from github-bugzi...@puremagic.com --- Commit pushed to dmd-cxx at https://github.com/dlang/dmd https://github.com/dlang/dmd/commit/366c8e9171b18d892a69d961ca4d8655ba28d1cf Issue 14669 - auto attribute on function parameter should be error always --
auto conversion to ascii
My Dynamic array complete show is good but when assign it's one index to a variable, it's saves ASCII of that index. writeln(myarray); // output 24 var = myarray[0]; // it assign 50 to var Why changed to ASCII and how to get rid of please...
[Issue 16953] auto-tester doesn't run rdmd_test (causes a number of regressions in each release)
https://issues.dlang.org/show_bug.cgi?id=16953 Vladimir Panteleev <dlang-bugzi...@thecybershadow.net> changed: What|Removed |Added CC||dlang-bugzilla@thecybershad ||ow.net Hardware|x86 |All Assignee|nob...@puremagic.com|dlang-bugzilla@thecybershad ||ow.net --- Comment #1 from Vladimir Panteleev <dlang-bugzi...@thecybershadow.net> --- FWIW, we do run the rdmd test suite via Travis (see https://github.com/dlang/tools/blob/master/travis.sh), but this only runs for PRs against the tools repository. We need to run the tests against PRs to all repositories to catch such issues effectively. We also have a daily cron job configured on Travis, so we can now at least be informed of such breakages shortly after they happen. Integrating the test into the auto-tester would be nice, however it currently doesn't test the tools repo at all. What might be more likely to happen instead is that I expand DAutoTest to also run the tools repository tests. --
[Issue 8204] Alias causes error: "auto can only be used for template function parameters"
https://issues.dlang.org/show_bug.cgi?id=8204 --- Comment #2 from Vladimir Panteleev <dlang-bugzi...@thecybershadow.net> --- (In reply to dlang+issues from comment #0) > void foo(T)(ref auto T v) { } > alias foo!int bar; // Error: auto can only be used for template function > parameters What is the expected type of "bar" here? The compiler can't know whether the instantiated function should take its parameter by ref or not, so I'm not sure whether this issue is valid. What is the expected behaviour? As a workaround, you can move the type to a separate outer template using the eponymous template pattern: template foo(T) { void foo()(auto ref T v) { } } alias foo!int bar; Unfortunately, this breaks calling foo (as in `foo(5)`). The type will need to be indicated explicitly (e.g. `foo!int(5)`). --
[Issue 14838] [REG 2.066] Wrong attribute inference for auto-generated class destructor with static array of non-POD type
https://issues.dlang.org/show_bug.cgi?id=14838 Vladimir Panteleevchanged: What|Removed |Added See Also||https://issues.dlang.org/sh ||ow_bug.cgi?id=8955 --
Re: Auto-decoding
On Saturday, 15 July 2017 at 18:47:25 UTC, Joakim wrote: On Saturday, 15 July 2017 at 18:14:48 UTC, aberba wrote: So what is the current plan? :) Andrei has talked about having a non-auto-decoding path for those who know what they're doing and actively choose that path, while keeping auto-decoding the default, so as not to break existing code. Jack has been submitting PRs for this, but it is probably tedious work, so progress is slow and I don't know how much more remains to be done: https://github.com/dlang/phobos/pulls?q=is%3Apr+auto-decoding+is%3Aclosed The idea is that once DIP1000 has matured, more focus on compiler support for reference-counting will be given with the aim of improving the @nogc experience. One example is DIP1008 for @nogc exceptions [1], but another one that is important in this context is RCString [2]. The idea is that RCString will be a new opt-in string type without auto-decoding and GC. Another idea in the game is `version(NoAutoDecode)`: https://github.com/dlang/phobos/pull/5513 However, here's unfortunately still unclear whether that could result in a working solution. [1] https://github.com/dlang/DIPs/blob/master/DIPs/DIP1008.md [2] https://github.com/dlang/phobos/pull/4878
Re: Auto-decoding
On Saturday, 15 July 2017 at 18:14:48 UTC, aberba wrote: On Saturday, 15 July 2017 at 05:54:32 UTC, ag0aep6g wrote: On 07/15/2017 06:21 AM, bauss wrote: [...] 1) Drop two elements from "Bär". With auto-decoding you get "r", which is nice. Without auto-decoding you get [0xA4, 'r'] where 0xA4 is the second half of the encoding of 'ä'. You have to know your Unicode to understand what is going on there. [...] So what is the current plan? :) Andrei has talked about having a non-auto-decoding path for those who know what they're doing and actively choose that path, while keeping auto-decoding the default, so as not to break existing code. Jack has been submitting PRs for this, but it is probably tedious work, so progress is slow and I don't know how much more remains to be done: https://github.com/dlang/phobos/pulls?q=is%3Apr+auto-decoding+is%3Aclosed
Re: Auto-decoding
On 07/15/2017 08:14 PM, aberba wrote: So what is the current plan? :) As far as I'm aware, there's no concrete plan to change anything. We just gotta deal with auto-decoding for the time being.
Re: Auto-decoding
On Saturday, 15 July 2017 at 05:54:32 UTC, ag0aep6g wrote: On 07/15/2017 06:21 AM, bauss wrote: [...] 1) Drop two elements from "Bär". With auto-decoding you get "r", which is nice. Without auto-decoding you get [0xA4, 'r'] where 0xA4 is the second half of the encoding of 'ä'. You have to know your Unicode to understand what is going on there. [...] So what is the current plan? :)
Re: Auto-decoding
On 07/15/2017 06:21 AM, bauss wrote: I understand what it is and how it works, but I don't understand anything of how it solves any problems? Could someone give an example of when auto-decoding actually is useful in contrast to not using it? 1) Drop two elements from "Bär". With auto-decoding you get "r", which is nice. Without auto-decoding you get [0xA4, 'r'] where 0xA4 is the second half of the encoding of 'ä'. You have to know your Unicode to understand what is going on there. 2) Search for 'ä' (one wchar/dchar) in the `string` "Bär". With auto-decoding, you pop the 'B' and then there's your 'ä'. Without auto-decoding, you can't find 'ä', because "Bär" doesn't have a single element that matches 'ä'. You have to search for "ä" (two `char`s) instead. The goal of auto-decoding was to make it so that you don't have to think about Unicode all the time when processing strings. Instead you could think in terms of "characters". But auto-decoding falls flat on that goal, which is why it's disliked. You still have to think about Unicode stuff for correctness (combining characters, graphemes), and now you also have to worry about the performance of auto-decoding.
Auto-decoding
I understand what it is and how it works, but I don't understand anything of how it solves any problems? Could someone give an example of when auto-decoding actually is useful in contrast to not using it? Just trying to get an understanding of what exactly its purpose is. I did read https://jackstouffer.com/blog/d_auto_decoding_and_you.html But I still feel like there's not a clear explanation of what issues exist when you don't have it. If I need to be more clear, just let me know.
[Issue 12372] Forward reference error with auto type inference in overloaded functions
https://issues.dlang.org/show_bug.cgi?id=12372 Vladimir Panteleevchanged: What|Removed |Added Status|NEW |RESOLVED Resolution|--- |WORKSFORME --- Comment #1 from Vladimir Panteleev --- Fixed by https://github.com/dlang/dmd/pull/5202. --
Re: auto*
On Thursday, 6 July 2017 at 23:50:24 UTC, bauss wrote: On Thursday, 6 July 2017 at 23:12:03 UTC, H. S. Teoh wrote: On Thu, Jul 06, 2017 at 10:31:10PM +, Meta via Digitalmars-d wrote: On Thursday, 6 July 2017 at 21:58:45 UTC, H. S. Teoh wrote: > On Thu, Jul 06, 2017 at 09:42:22PM +, Meta via > Digitalmars-d wrote: > > On Thursday, 6 July 2017 at 18:10:57 UTC, FoxyBrown wrote: > > > Create an auto pointer, handy in some cases and fits in > > > the language as a natural generalization. > > > > It's been suggested before (as well as more powerful > > generalization for slices and associative arrays), but > > Andrei vetoed it so it probably won't be added even if > > somebody created a formal proposal for it. > > I'm curious, what exactly was proposed? Because I have a > hard time understanding what's intended from the OP's > description. > > > T Partial type inference. `auto*` declares a point to a type that is inferred from inspecting the RHS's type. The previous proposal was for doing `auto[] a = [0, 1, 2]` (a's type is inferred as int[]). But doesn't `auto a = [0, 1, 2];` *already* infer typeof(a) as int[]? What does `auto[]` add over what `auto` already does? T It does, but I think it's more a thing of knowing what exactly the auto is. Let's say you have. auto a = foo(); You have no idea what auto actually is in that case, but auto* a = foo(); You know auto is a pointer of whatever foo returns. If you want to document the type returned, then use an explicit type. Type deduction is imho a thing to avoid redundancy in an expression, not to transform D into python (and to make templates possible). If the type of an expression becomes difficult to deduce, it is a good idea imo to explicitely write out the type. This adds a simple constraint, i.e. adds a way for the compiler to exploit the type system to make the program more secure.
Re: auto*
On Thursday, 6 July 2017 at 20:24:24 UTC, FoxyBrown wrote: On Thursday, 6 July 2017 at 18:11:13 UTC, H. S. Teoh wrote: On Thu, Jul 06, 2017 at 06:10:57PM +, FoxyBrown via Digitalmars-d wrote: Create an auto pointer, handy in some cases and fits in the language as a natural generalization. What's an auto pointer? T is it not obvious? auto x = ... auto* x = ... auto* is the pointerized version of auto. e.g., int x = ... int* x = ... typeof(x) y = ... typeof(x)* y = ... obviously the rhs must be congruent with the type. auto p = // a pointer auto* p = // a double pointer to foo. When having the need to require a pointer to a pointer, it avoids having to specify the type in a verbose way. i.e., the second line above is not valid, but to do it we must either cast to void** or use typeof and such to get the correct type and make a pointer out of it. auto* simplifies all that. Just one thing. auto in D is not a type, it's a storage class. It inherited that from C. This means auto* doesn't make any sense as the * is part of a type. So your expression lack a proper type. Type deduction works by using the type of the rhs of the expression and applying to it the storage class of the lhs. This means that auto x = ..; works but also static x = ..; works D does not implemented C's register storage class, but if it did register x = .. would also work. When you understand that you will understand why your proposition does not make sense.
Re: auto*
On Friday, 7 July 2017 at 00:58:57 UTC, jmh530 wrote: On Friday, 7 July 2017 at 00:39:32 UTC, Meta wrote: (https://github.com/dlang/dmd/pull/3615) Of course this could also get confusing pretty fast. I wish we at least had the `int[$]` syntax but it's not a huge loss. Thanks for posting the link. Made for interesting reading. This was another link on the same topic: http://forum.dlang.org/post/bewroetnschakoqjz...@forum.dlang.org Yeah, it's one of those features that seemed very nice and I, at the very least, was disappointed that it didn't get in (of course Bearophile was as well). I don't really agree with Andrei's reason for vetoing the feature (the part about adding this feature being a slippery slope, not the power to complexity ratio), but looking back on it there are a few peculiarities with this syntax. For example, `immutable[] i = [0]` has the type `immutable(int)[]`, but to get `immutable(int[])` you have to do `immutable i = [0]`. I'd say that a beginner looking at this code would assume the opposite (although it's a very easy rule to learn). It's one of the problems D has with this syntax as opposed to C++, which has the ability to declare head-const arrays/pointers.
Re: auto*
On Friday, 7 July 2017 at 00:39:32 UTC, Meta wrote: (https://github.com/dlang/dmd/pull/3615) Of course this could also get confusing pretty fast. I wish we at least had the `int[$]` syntax but it's not a huge loss. Thanks for posting the link. Made for interesting reading. This was another link on the same topic: http://forum.dlang.org/post/bewroetnschakoqjz...@forum.dlang.org
Re: auto*
On Thursday, 6 July 2017 at 23:51:13 UTC, H. S. Teoh wrote: On Thu, Jul 06, 2017 at 11:50:24PM +, bauss via Digitalmars-d wrote: [...] Let's say you have. auto a = foo(); You have no idea what auto actually is in that case, but auto* a = foo(); You know auto is a pointer of whatever foo returns. Ah, I see. So if foo() doesn't return a pointer it will be a compile error? So it's basically a kind of self-documentation? T Kenji also extended the inference to some very interesting cases. // static array type int[$] a1 = [1,2];// int[2] auto[$] a2 = [3,4,5]; // int[3] const[$] a3 = [6,7,8]; // const(int[3]) // dynamic array type immutable[] a4 = [1,2];// immutable(int)[] shared[]a5 = [3,4,5]; // shared(int)[] // partially specified part is unqualified. // pointer type auto* p1 = new int(3); // int* const* p2 = new int(3); // const(int)* // mixing auto[][$] x1 = [[1,2,3],[4,5]]; // int[][2] shared*[$] x2 = [new int(1), new int(2)]; // shared(int)*[2] (https://github.com/dlang/dmd/pull/3615) Of course this could also get confusing pretty fast. I wish we at least had the `int[$]` syntax but it's not a huge loss.
Re: auto*
On Thursday, 6 July 2017 at 23:51:13 UTC, H. S. Teoh wrote: On Thu, Jul 06, 2017 at 11:50:24PM +, bauss via Digitalmars-d wrote: [...] Let's say you have. auto a = foo(); You have no idea what auto actually is in that case, but auto* a = foo(); You know auto is a pointer of whatever foo returns. Ah, I see. So if foo() doesn't return a pointer it will be a compile error? So it's basically a kind of self-documentation? T That's my understanding yeah.
Re: auto*
On Thu, Jul 06, 2017 at 11:50:24PM +, bauss via Digitalmars-d wrote: [...] > Let's say you have. > > auto a = foo(); > > You have no idea what auto actually is in that case, but > > auto* a = foo(); > > You know auto is a pointer of whatever foo returns. Ah, I see. So if foo() doesn't return a pointer it will be a compile error? So it's basically a kind of self-documentation? T -- INTEL = Only half of "intelligence".
Re: auto*
On Thursday, 6 July 2017 at 23:12:03 UTC, H. S. Teoh wrote: On Thu, Jul 06, 2017 at 10:31:10PM +, Meta via Digitalmars-d wrote: On Thursday, 6 July 2017 at 21:58:45 UTC, H. S. Teoh wrote: > On Thu, Jul 06, 2017 at 09:42:22PM +, Meta via > Digitalmars-d wrote: > > On Thursday, 6 July 2017 at 18:10:57 UTC, FoxyBrown wrote: > > > Create an auto pointer, handy in some cases and fits in > > > the language as a natural generalization. > > > > It's been suggested before (as well as more powerful > > generalization for slices and associative arrays), but > > Andrei vetoed it so it probably won't be added even if > > somebody created a formal proposal for it. > > I'm curious, what exactly was proposed? Because I have a > hard time understanding what's intended from the OP's > description. > > > T Partial type inference. `auto*` declares a point to a type that is inferred from inspecting the RHS's type. The previous proposal was for doing `auto[] a = [0, 1, 2]` (a's type is inferred as int[]). But doesn't `auto a = [0, 1, 2];` *already* infer typeof(a) as int[]? What does `auto[]` add over what `auto` already does? T It does, but I think it's more a thing of knowing what exactly the auto is. Let's say you have. auto a = foo(); You have no idea what auto actually is in that case, but auto* a = foo(); You know auto is a pointer of whatever foo returns.
Re: auto*
On Thu, Jul 06, 2017 at 10:31:10PM +, Meta via Digitalmars-d wrote: > On Thursday, 6 July 2017 at 21:58:45 UTC, H. S. Teoh wrote: > > On Thu, Jul 06, 2017 at 09:42:22PM +, Meta via Digitalmars-d wrote: > > > On Thursday, 6 July 2017 at 18:10:57 UTC, FoxyBrown wrote: > > > > Create an auto pointer, handy in some cases and fits in the > > > > language as a natural generalization. > > > > > > It's been suggested before (as well as more powerful > > > generalization for slices and associative arrays), but Andrei > > > vetoed it so it probably won't be added even if somebody created a > > > formal proposal for it. > > > > I'm curious, what exactly was proposed? Because I have a hard time > > understanding what's intended from the OP's description. > > > > > > T > > Partial type inference. `auto*` declares a point to a type that is > inferred from inspecting the RHS's type. The previous proposal was for > doing `auto[] a = [0, 1, 2]` (a's type is inferred as int[]). But doesn't `auto a = [0, 1, 2];` *already* infer typeof(a) as int[]? What does `auto[]` add over what `auto` already does? T -- "Real programmers can write assembly code in any language. :-)" -- Larry Wall
Re: auto*
On Thursday, 6 July 2017 at 21:58:45 UTC, H. S. Teoh wrote: On Thu, Jul 06, 2017 at 09:42:22PM +, Meta via Digitalmars-d wrote: On Thursday, 6 July 2017 at 18:10:57 UTC, FoxyBrown wrote: > Create an auto pointer, handy in some cases and fits in the > language as a natural generalization. It's been suggested before (as well as more powerful generalization for slices and associative arrays), but Andrei vetoed it so it probably won't be added even if somebody created a formal proposal for it. I'm curious, what exactly was proposed? Because I have a hard time understanding what's intended from the OP's description. T Partial type inference. `auto*` declares a point to a type that is inferred from inspecting the RHS's type. The previous proposal was for doing `auto[] a = [0, 1, 2]` (a's type is inferred as int[]).
Re: auto*
On Thu, Jul 06, 2017 at 09:42:22PM +, Meta via Digitalmars-d wrote: > On Thursday, 6 July 2017 at 18:10:57 UTC, FoxyBrown wrote: > > Create an auto pointer, handy in some cases and fits in the language > > as a natural generalization. > > It's been suggested before (as well as more powerful generalization > for slices and associative arrays), but Andrei vetoed it so it > probably won't be added even if somebody created a formal proposal for > it. I'm curious, what exactly was proposed? Because I have a hard time understanding what's intended from the OP's description. T -- Obviously, some things aren't very obvious.
Re: auto*
On Thursday, 6 July 2017 at 18:10:57 UTC, FoxyBrown wrote: Create an auto pointer, handy in some cases and fits in the language as a natural generalization. It's been suggested before (as well as more powerful generalization for slices and associative arrays), but Andrei vetoed it so it probably won't be added even if somebody created a formal proposal for it.
Re: auto*
On 07/06/2017 01:24 PM, FoxyBrown wrote: > On Thursday, 6 July 2017 at 18:11:13 UTC, H. S. Teoh wrote: >> On Thu, Jul 06, 2017 at 06:10:57PM +, FoxyBrown via Digitalmars-d >> wrote: >>> Create an auto pointer, handy in some cases and fits in the language >>> as a natural generalization. >> >> What's an auto pointer? >> >> >> T > > is it not obvious? It wasn't obvious at all. :) (I even suspected C++'s std::auto_ptr but dropped the thought.) > auto p = // a pointer > auto* p = // a double pointer to foo. > > When having the need to require a pointer to a pointer, it avoids having > to specify the type in a verbose way. > > i.e., the second line above is not valid, but to do it we must either > cast to void** or use typeof and such to get the correct type and make a > pointer out of it. auto* simplifies all that. Let's say foo is type Foo... Staying with that example and assuming that p has type Foo**, what would *p provide? We have the object (foo), we have the pointer to pointer (p), but where does the pointer itself live? Only the programmer knows where that intermediate pointer is. For example: struct Foo { } void main() { auto foo = Foo(); auto x = // A local variable here auto p = } It seems to work cleanly to me. If you have something else in mind please show the troubling line with complete code. :) Ali
Re: auto*
On Thu, Jul 06, 2017 at 08:24:24PM +, FoxyBrown via Digitalmars-d wrote: [...] > auto x = ... > > auto* x = ... > > auto* is the pointerized version of auto. > > > e.g., > > int x = ... > > int* x = ... > > typeof(x) y = ... > typeof(x)* y = ... > > > obviously the rhs must be congruent with the type. > > auto p = // a pointer > auto* p = // a double pointer to foo. > > When having the need to require a pointer to a pointer, it avoids > having to specify the type in a verbose way. > > i.e., the second line above is not valid, but to do it we must either > cast to void** or use typeof and such to get the correct type and make > a pointer out of it. auto* simplifies all that. Huh? How is it even remotely valid to cast a single pointer to a double pointer implicitly? If foo is a non-pointer object, `auto p = ` already gives you a pointer. If foo itself is also a pointer, `auto p = ` will already give you a double pointer. There is no need to "specify the type in a verbose way" at all. You can't get a double pointer out of a single pointer without saving the single pointer in an addressable variable, e.g.: auto p = // takes address of foo (single pointer) auto pp =// takes address of p (double pointer) It's invalid to take the address of an rvalue, because an rvalue has no location. I.e., `&()` is illegal because is an rvalue. Before you can make a double pointer to it, you have to designate some location where it is to be stored, so that the double pointer can point to that location. T -- The two rules of success: 1. Don't tell everything you know. -- YHL
Re: auto*
On Thursday, 6 July 2017 at 18:11:13 UTC, H. S. Teoh wrote: On Thu, Jul 06, 2017 at 06:10:57PM +, FoxyBrown via Digitalmars-d wrote: Create an auto pointer, handy in some cases and fits in the language as a natural generalization. What's an auto pointer? T is it not obvious? auto x = ... auto* x = ... auto* is the pointerized version of auto. e.g., int x = ... int* x = ... typeof(x) y = ... typeof(x)* y = ... obviously the rhs must be congruent with the type. auto p = // a pointer auto* p = // a double pointer to foo. When having the need to require a pointer to a pointer, it avoids having to specify the type in a verbose way. i.e., the second line above is not valid, but to do it we must either cast to void** or use typeof and such to get the correct type and make a pointer out of it. auto* simplifies all that.
Re: auto*
On Thu, Jul 06, 2017 at 06:10:57PM +, FoxyBrown via Digitalmars-d wrote: > Create an auto pointer, handy in some cases and fits in the language > as a natural generalization. What's an auto pointer? T -- Truth, Sir, is a cow which will give [skeptics] no more milk, and so they are gone to milk the bull. -- Sam. Johnson
auto*
Create an auto pointer, handy in some cases and fits in the language as a natural generalization.
[Issue 15368] Improve error message for "auto" keyword inside "foreach"
https://issues.dlang.org/show_bug.cgi?id=15368 Vladimir Panteleevchanged: What|Removed |Added Keywords||diagnostic --
[Issue 17512] [REG 2.073] [DIP1000] Error on bad interplay of "auto ref" and "return" attribute deduction.
https://issues.dlang.org/show_bug.cgi?id=17512 Vladimir Panteleevchanged: What|Removed |Added CC||thecybersha...@gmail.com --- Comment #3 from Vladimir Panteleev --- FWIW, the error starts appearing after https://github.com/dlang/dmd/pull/6452 --
Nullable with auto-allocation on access
Is there a construct similar to Nullable that would auto-allocate upon access (set/get) if isNull is true? Use case: https://github.com/msoucy/dproto/issues/117 [getters and setters should work without calling `init` on Nullable fields, as in C++ #117] copied inline for easy reference: ``` in C++ we can write: message MyMessage{ optional Foo foo=1; } message Foo{ optional Bar bar=1; } message Bar{ optional string baz=1; } MyMessage a; a.mutable_foo()->mutable_bar()->set_baz("hello"); in dproto we need to call init on the intermediate fields foo, bar auto initialize_nullable(T:Nullable!U, U)(ref T a){ a=U.init; } MyMessage a; a.foo.initialize_nullable; a.foo.bar.initialize_nullable; a.foo.bar.baz="hello"; Would be nice to not have to call init and allow this: MyMessage a; a.foo.bar.baz="hello"; I believe this could be implemented via a modification of Nullable that would call init on 1st access to a setter. ```
[Issue 17512] [REG 2.073] [DIP1000] Error on bad interplay of "auto ref" and "return" attribute deduction.
https://issues.dlang.org/show_bug.cgi?id=17512 ZombineDev <petar.p.ki...@gmail.com> changed: What|Removed |Added Keywords||safe CC||petar.p.ki...@gmail.com Summary|[REG 2.073] Error on bad|[REG 2.073] [DIP1000] Error |interplay of "auto ref" and |on bad interplay of "auto |"return" attribute |ref" and "return" attribute |deduction. |deduction. --
[Issue 17512] [REG 2.073] Error on bad interplay of "auto ref" and "return" attribute deduction.
https://issues.dlang.org/show_bug.cgi?id=17512 johanenge...@weka.io changed: What|Removed |Added Summary|Unclear error message when |[REG 2.073] Error on bad |returning a reference to|interplay of "auto ref" and |local variable |"return" attribute ||deduction. Severity|normal |regression --
Re: auto decoding rant
On Thursday, 15 June 2017 at 15:50:42 UTC, Seb wrote: On Thursday, 15 June 2017 at 15:47:54 UTC, Jonathan Shamir wrote: Also note I can't cast to char[] in compile time? What's the reason for that? Have a look at: https://dlang.org/phobos/std_utf.html#byCodeUnit https://dlang.org/phobos/std_utf.html#byChar https://dlang.org/phobos/std_string.html#.representation Perfect, thanks!
Re: auto decoding rant
On Thursday, June 15, 2017 15:47:54 Jonathan Shamir via Digitalmars-d wrote: > I see this is a recurring rant (I apologize if this is a > repeating topic, I'm new to the forums). Here's an example of > something that should be simple in D but isn't: > > enum string PATTERN = "abcd"; > immutable char[10] repeatingPattern = > PATTERN.cycle().takeExactly(10).array(); > > The fact that front(string) returns a dchar makes some really > simple (and common) use-cases practically impossible. > > Also note I can't cast to char[] in compile time? What's the > reason for that? > > I would recommend adding something like this to phobos (and in > all fairness, it should have been the other way around): Yes, it should be the other way around, but changing it at this point without massive code breakage is very difficult if not impossible. > auto noDecode(T)(T[] str) if (isNarrowString!(T[])) { > static struct NoDecode { > private T[] str; > > @property ref T front() { > assert (!this.empty); > return str[0]; > } > @property bool empty() { > return (str.empty); > } > void popFront() { > if (!this.empty) { > str = str[1 .. $]; > } > } > NoDecode save() { > return this; > } > } > return NoDecode(str); > } Already there: http://dlang.org/phobos/std_utf.html#byCodeUnit - Jonathan M Davis
Re: auto decoding rant
On Thursday, 15 June 2017 at 15:47:54 UTC, Jonathan Shamir wrote: Also note I can't cast to char[] in compile time? What's the reason for that? Have a look at: https://dlang.org/phobos/std_utf.html#byCodeUnit https://dlang.org/phobos/std_utf.html#byChar https://dlang.org/phobos/std_string.html#.representation
auto decoding rant
I see this is a recurring rant (I apologize if this is a repeating topic, I'm new to the forums). Here's an example of something that should be simple in D but isn't: enum string PATTERN = "abcd"; immutable char[10] repeatingPattern = PATTERN.cycle().takeExactly(10).array(); The fact that front(string) returns a dchar makes some really simple (and common) use-cases practically impossible. Also note I can't cast to char[] in compile time? What's the reason for that? I would recommend adding something like this to phobos (and in all fairness, it should have been the other way around): auto noDecode(T)(T[] str) if (isNarrowString!(T[])) { static struct NoDecode { private T[] str; @property ref T front() { assert (!this.empty); return str[0]; } @property bool empty() { return (str.empty); } void popFront() { if (!this.empty) { str = str[1 .. $]; } } NoDecode save() { return this; } } return NoDecode(str); }
Re: Make enum auto castable
On Monday, 5 June 2017 at 03:15:46 UTC, Jonathan M Davis wrote: On Monday, June 05, 2017 02:14:14 Mike B Johnson via Digitalmars-d-learn wrote: On Monday, 5 June 2017 at 01:42:55 UTC, Jonathan M Davis wrote: > On Monday, June 05, 2017 01:30:47 Mike B Johnson via > > Digitalmars-d-learn wrote: >> [...] > > It's not a bug. The alias this conversion only goes one way. > It provides a way to convert _from_ the type that it's > declared on to another type, not from the other type to the > type that it's declared on. There is no way in D to declare > an implicit conversion in the direction you're trying. So, > if you have a struct that wraps an int like this, and you > want to assign it an int, you're going to need to explicitly > construct the struct - e.g. EnumX(1). > > - Jonathan M Davis That's pretty crappy! Defeats the whole point! Well, implicit conversions tend to cause a lot of bugs in C++ code, so Walter decided to restrict them quite a bit more in D than they are in C++. This therefore prevents a number of bugs in D, but it also prevents implicit conversions from being used in a number of situations where they're useful. Whether the end result is better or worse, I don't know and certainly YMMV. As it is, some of the implicit conversions that we still allow have a tendency to cause bugs (e.g. conversions between integral values and character types tend to be error-prone - especially when arrays are involved - and using implicit conversions with templated code is almost always a bad idea). So, at times, I tend to think that all implicit conversions should be banned. But at other times, it would be really nice to be able to have more than we do (e.g. it would be a lot more user-friendly if you could pass a T to a function that takes a Nullable!T). In any case, I think that the reality of the matter with D is that you tend to have to use explicit conversions rather than implicit ones, and if you're looking to do much with implicit conversions, you're usually going to be frustrated, and obviously, that sucks, but at least you're less likely to have bugs related to implicit conversions. - Jonathan M Davis The problem is bugs are only a possibility. If you remove a feature from a language the feature does not exist, period. So, throwing the baby out with the bath water because he pooped in it is not a solution. Instead, if there is a problem with implicit autonomous conversion or construction, then the solution is not to remove all implicit conversions or constructions but to remove the autonomous part. e.g., make the user specify the implicit conversion explicitly. This way, if bugs do creep in, it is due to the user. It is much easier to diagnose and fix then.
Re: Make enum auto castable
On Sun, Jun 04, 2017 at 08:15:46PM -0700, Jonathan M Davis via Digitalmars-d-learn wrote: > Well, implicit conversions tend to cause a lot of bugs in C++ code, so > Walter decided to restrict them quite a bit more in D than they are in C++. So D has plenty of implicit conversion. It is implicit *construction* that it lacks. And alas, C++'s mistake is implicit is default, so it gets used in places it wasn't intended. We should have just had explicit default with implicit as an option.
Re: Make enum auto castable
On Monday, June 05, 2017 02:14:14 Mike B Johnson via Digitalmars-d-learn wrote: > On Monday, 5 June 2017 at 01:42:55 UTC, Jonathan M Davis wrote: > > On Monday, June 05, 2017 01:30:47 Mike B Johnson via > > > > Digitalmars-d-learn wrote: > >> [...] > > > > It's not a bug. The alias this conversion only goes one way. It > > provides a way to convert _from_ the type that it's declared on > > to another type, not from the other type to the type that it's > > declared on. There is no way in D to declare an implicit > > conversion in the direction you're trying. So, if you have a > > struct that wraps an int like this, and you want to assign it > > an int, you're going to need to explicitly construct the struct > > - e.g. EnumX(1). > > > > - Jonathan M Davis > > That's pretty crappy! Defeats the whole point! Well, implicit conversions tend to cause a lot of bugs in C++ code, so Walter decided to restrict them quite a bit more in D than they are in C++. This therefore prevents a number of bugs in D, but it also prevents implicit conversions from being used in a number of situations where they're useful. Whether the end result is better or worse, I don't know and certainly YMMV. As it is, some of the implicit conversions that we still allow have a tendency to cause bugs (e.g. conversions between integral values and character types tend to be error-prone - especially when arrays are involved - and using implicit conversions with templated code is almost always a bad idea). So, at times, I tend to think that all implicit conversions should be banned. But at other times, it would be really nice to be able to have more than we do (e.g. it would be a lot more user-friendly if you could pass a T to a function that takes a Nullable!T). In any case, I think that the reality of the matter with D is that you tend to have to use explicit conversions rather than implicit ones, and if you're looking to do much with implicit conversions, you're usually going to be frustrated, and obviously, that sucks, but at least you're less likely to have bugs related to implicit conversions. - Jonathan M Davis
Re: Make enum auto castable
On Monday, 5 June 2017 at 01:42:55 UTC, Jonathan M Davis wrote: On Monday, June 05, 2017 01:30:47 Mike B Johnson via Digitalmars-d-learn wrote: [...] It's not a bug. The alias this conversion only goes one way. It provides a way to convert _from_ the type that it's declared on to another type, not from the other type to the type that it's declared on. There is no way in D to declare an implicit conversion in the direction you're trying. So, if you have a struct that wraps an int like this, and you want to assign it an int, you're going to need to explicitly construct the struct - e.g. EnumX(1). - Jonathan M Davis That's pretty crappy! Defeats the whole point!
Re: Make enum auto castable
On Monday, June 05, 2017 01:30:47 Mike B Johnson via Digitalmars-d-learn wrote: > enum X : EnumX > { > a = 1, > } > > > struct EnumX > { > int x; > alias x this; > void opAssign(int y) > { > x = y; > } > double opCall() > { > return x; > } > } > > doesn't work because "1" is not castable to EnumX, even though > EnumX is aliased to an int, and hence it should work fine. > > Seems like a bug to me. It's not a bug. The alias this conversion only goes one way. It provides a way to convert _from_ the type that it's declared on to another type, not from the other type to the type that it's declared on. There is no way in D to declare an implicit conversion in the direction you're trying. So, if you have a struct that wraps an int like this, and you want to assign it an int, you're going to need to explicitly construct the struct - e.g. EnumX(1). - Jonathan M Davis
Re: Make enum auto castable
On Monday, 5 June 2017 at 00:51:15 UTC, Jonathan M Davis wrote: On Monday, June 05, 2017 00:16:15 Mike B Johnson via Digitalmars-d-learn wrote: On Sunday, 4 June 2017 at 23:39:11 UTC, Jonathan M Davis wrote: > [...] I might be able to change the enum, I assume you mean something like enum myenum : S { } where S is the struct that implicitly converts? Yes. However, be aware that you can currently only define one alias this per type. So, the rest of the code will then need to be able to deal with the fact that the enum is a struct that implicitly converts to VARIANT and does not implicitly convert to int. So, if you're just passing the enums around and comparing them, you're fine, but if you need to treat them as ints somewhere, then you'll need to provide an explicit conversion (via overloading opCast or by creating a specific function for it or just exposing a member with the int value or whatever), and that could get annoying in the same way that you're annoyed about the VARIANT issue right now. But if you don't actually need to treat the enum as an int, and you can make it a struct that implicitly converts to VARIANT instead, then that will fix your VARIANT conversion problem. - Jonathan M Davis enum X : EnumX { a = 1, } struct EnumX { int x; alias x this; void opAssign(int y) { x = y; } double opCall() { return x; } } doesn't work because "1" is not castable to EnumX, even though EnumX is aliased to an int, and hence it should work fine. Seems like a bug to me.
Re: Make enum auto castable
On Monday, June 05, 2017 01:12:20 Mike B Johnson via Digitalmars-d-learn wrote: > Well, I do need to to treat it as an int at times and opCast only > works with cast. While I could set it up to do a cast(VARIANT), > which is better than nothing, I'd get same result as to!VARIANT, > which is shorter and effectively the same. > > When will we get multiple alias this? all I need is two? > > Hell, why not make alias this an "overloadable" function similar > to opCast and such? I don't know when we're getting multiple alias thises. TDPL talks about it being a thing, and the spec claims that it's a thing, but until someone implements it, we won't have it, and it hasn't been a priority for Walter. IIRC, someone tried to implement it at one point, but I don't know where that went. There was a thread in the main newsgroup a couple of months ago about how to simulate multiple alias thises, so you might want to check that out: https://forum.dlang.org/post/uniyvmvjopeyyxmph...@forum.dlang.org - Jonathan M Davis
Re: Make enum auto castable
On Monday, 5 June 2017 at 00:51:15 UTC, Jonathan M Davis wrote: On Monday, June 05, 2017 00:16:15 Mike B Johnson via Digitalmars-d-learn wrote: On Sunday, 4 June 2017 at 23:39:11 UTC, Jonathan M Davis wrote: > On Sunday, June 04, 2017 22:52:55 Mike B Johnson via > > Digitalmars-d-learn wrote: >> [...] > > Aside from whatever implicit conversions are built into the > language, the only way to define an implicit conversion in D > is via alias this on a user-defined type, which then tells > that type that it can convert to whatever type the result of > the alias this is. e.g. if you have > > [...] I might be able to change the enum, I assume you mean something like enum myenum : S { } where S is the struct that implicitly converts? Yes. However, be aware that you can currently only define one alias this per type. So, the rest of the code will then need to be able to deal with the fact that the enum is a struct that implicitly converts to VARIANT and does not implicitly convert to int. So, if you're just passing the enums around and comparing them, you're fine, but if you need to treat them as ints somewhere, then you'll need to provide an explicit conversion (via overloading opCast or by creating a specific function for it or just exposing a member with the int value or whatever), and that could get annoying in the same way that you're annoyed about the VARIANT issue right now. But if you don't actually need to treat the enum as an int, and you can make it a struct that implicitly converts to VARIANT instead, then that will fix your VARIANT conversion problem. - Jonathan M Davis Well, I do need to to treat it as an int at times and opCast only works with cast. While I could set it up to do a cast(VARIANT), which is better than nothing, I'd get same result as to!VARIANT, which is shorter and effectively the same. When will we get multiple alias this? all I need is two? Hell, why not make alias this an "overloadable" function similar to opCast and such?
Re: Make enum auto castable
On Monday, June 05, 2017 00:16:15 Mike B Johnson via Digitalmars-d-learn wrote: > On Sunday, 4 June 2017 at 23:39:11 UTC, Jonathan M Davis wrote: > > On Sunday, June 04, 2017 22:52:55 Mike B Johnson via > > > > Digitalmars-d-learn wrote: > >> [...] > > > > Aside from whatever implicit conversions are built into the > > language, the only way to define an implicit conversion in D is > > via alias this on a user-defined type, which then tells that > > type that it can convert to whatever type the result of the > > alias this is. e.g. if you have > > > > [...] > > I might be able to change the enum, I assume you mean something > like > > enum myenum : S { } > > where S is the struct that implicitly converts? Yes. However, be aware that you can currently only define one alias this per type. So, the rest of the code will then need to be able to deal with the fact that the enum is a struct that implicitly converts to VARIANT and does not implicitly convert to int. So, if you're just passing the enums around and comparing them, you're fine, but if you need to treat them as ints somewhere, then you'll need to provide an explicit conversion (via overloading opCast or by creating a specific function for it or just exposing a member with the int value or whatever), and that could get annoying in the same way that you're annoyed about the VARIANT issue right now. But if you don't actually need to treat the enum as an int, and you can make it a struct that implicitly converts to VARIANT instead, then that will fix your VARIANT conversion problem. - Jonathan M Davis
Re: Make enum auto castable
On Sunday, 4 June 2017 at 23:39:11 UTC, Jonathan M Davis wrote: On Sunday, June 04, 2017 22:52:55 Mike B Johnson via Digitalmars-d-learn wrote: [...] Aside from whatever implicit conversions are built into the language, the only way to define an implicit conversion in D is via alias this on a user-defined type, which then tells that type that it can convert to whatever type the result of the alias this is. e.g. if you have [...] I might be able to change the enum, I assume you mean something like enum myenum : S { } where S is the struct that implicitly converts?
Re: Make enum auto castable
On Sunday, June 04, 2017 22:52:55 Mike B Johnson via Digitalmars-d-learn wrote: > I am dealing with some COM stuff and some functions use VARIANT, > which can hold an enum. > > Instead of having to manually convert the enum(and for that > matter, other things) to VARIANT, is it possible to have them > automatically converted? > > This is because an enum is always convertible to a VARIANT but > not the other way around. So, when a enum is passed to a function > accepting a VARIANT, it should just work. Overloading is not an > option. Aside from whatever implicit conversions are built into the language, the only way to define an implicit conversion in D is via alias this on a user-defined type, which then tells that type that it can convert to whatever type the result of the alias this is. e.g. if you have struct S { int x; alias x this; } then S can implicitly convert to int, and when it does, the value of x is used (alternatively, a member function could be used, in which case, the result of the member function would be used as the result of the conversion). So, that allows you to tell how to convert a type _to_ another type, but it does not allow you to convert _from_ another type. So, if you're implicitly converting from type A to type B, it will work if type A has been told how to convert to B, but there is no way for B to say that an A can be converted to a B. Only A can define the conversion. So, if you have control of the definition of the base type of the enum, then you can define an alias this on it to convert to a VARIANT, but if you don't have control over the definition of the base type of the enum (e.g. if it's int, as is the default), then you're out of luck. And if you're dealing with COM, then I'm guessing that your enum has a base type of int, and you obviously don't control the definition of int, so you can't add an alias this to it. So, if you can't change the enum, and you can't change the function that you're calling, then you'll have to insert something in between - be it a conversion function, an explicit construction of VARIANT with the enum, or some kind of wrapper function around the one that you're calling. But unless the enum itself knows how to implicitly convert to a VARIANT thanks to alias this, there is no implicit conversion. std.typecons.Nullable has this sort of problem, which has historically forced folks to do stuff like Nullable!int(42) when passing the actual type to a function that accepts a Nullable wrapper around the type, which is pretty annoying. Recently, a nullable function was added to std.typecons which uses IFTI to infer the type of the Nullable auto nullable(T)(T t) { return Nullable!T(t); } and then you could pass nullable(42) instead of Nullable!int(42), so it's more user-friendly, but it still requires an explicit conversion unless you overload the function. It's a downside to D's stricter approach to implicit conversions. - Jonathan M Davis
Re: Make enum auto castable
On Sunday, 4 June 2017 at 22:52:55 UTC, Mike B Johnson wrote: I am dealing with some COM stuff and some functions use VARIANT, which can hold an enum. Instead of having to manually convert the enum(and for that matter, other things) to VARIANT, is it possible to have them automatically converted? This is because an enum is always convertible to a VARIANT but not the other way around. So, when a enum is passed to a function accepting a VARIANT, it should just work. Overloading is not an option. Not sure if this breaks your requirement but you could generate overloads or rather templated version of your variant accepting function with a mixin that introspects on functions with a certain uda in the module. See excel-d for an example.
Make enum auto castable
I am dealing with some COM stuff and some functions use VARIANT, which can hold an enum. Instead of having to manually convert the enum(and for that matter, other things) to VARIANT, is it possible to have them automatically converted? This is because an enum is always convertible to a VARIANT but not the other way around. So, when a enum is passed to a function accepting a VARIANT, it should just work. Overloading is not an option.