Re: dub auto-tester
On Thursday, 20 September 2018 at 05:04:49 UTC, Neia Neutuladh wrote: On Thursday, 20 September 2018 at 04:41:21 UTC, Joakim wrote: Nice, what will it take to get this integrated with the official dub website? I need to: * add JSON output to the auto-tester * get the dub registry to scrape the data (or, optionally, push the data to the registry, but that opens up trust issues that I'd rather not get into) * enable SSL on the report site (and probably get a new domain Feel free to send me a ping if you want a .dlang.io subdomain.
Re: dub auto-tester
On Thursday, 20 September 2018 at 04:41:21 UTC, Joakim wrote: Nice, what will it take to get this integrated with the official dub website? I need to: * add JSON output to the auto-tester * get the dub registry to scrape the data (or, optionally, push the data to the registry, but that opens up trust issues that I'd rather not get into) * enable SSL on the report site (and probably get a new domain for it) * alter the dub UI to include the data That's all pretty straightforward. BTW, the gitea self-hosted github-workalike you're using looks nice, too bad it's written in Go. ;) Gitea has the benefit of existing, which is surprisingly important.
dub auto-tester
On Thursday, 20 September 2018 at 04:16:41 UTC, Neia Neutuladh wrote: On Thursday, 20 September 2018 at 02:51:52 UTC, Neia Neutuladh wrote: On Monday, 10 September 2018 at 01:27:20 UTC, Neia Neutuladh wrote: Not on dlang.org anywhere, but I built a crude version of this. Results are available at http://ikeran.org/report/. A quick status update: And source code is available at https://git.ikeran.org/dhasenan/dubautotester Please don't judge me. Nice, what will it take to get this integrated with the official dub website? BTW, the gitea self-hosted github-workalike you're using looks nice, too bad it's written in Go. ;)
Re: auto: useful, annoying or bad practice?
On Sunday, 20 May 2018 at 23:01:39 UTC, Charles Hixson wrote: auto has its uses, but it's wildly overused, especially in library code and documentation, and really, really, *really* much so in documentation examples. A lot of functions in `std.algorithm` are actually quite clear about it, e.g. `splitter`: "auto splitter(alias pred = "a == b", Range, Separator)(Range r, Separator s) ... Returns: An input range of the subranges of elements between separators. If r is a forward range or bidirectional range, the returned range will be likewise. When a range is used a separator, bidirectionality isn't possible." So it obviously returns a range which you can process as a range. No need to know about the exact type (which may change). All you need to know is that it adheres to a minimal range interface (r.empty, r.front, r.popFront). Without `auto`, it'd be a solid mess and generics would become more or less useless. Even Java is moving into this direction and it makes sense for a lot of day to day issues, programmes will increasingly demand it. Code like the following is much more elegant than using the ould for loop: JSONObject jitems = new JSONObject(); data.entrySet() .forEach(i -> { jitems.put(i.getKey(), i.getValue()); });
Re: auto: useful, annoying or bad practice?
auto has its uses, but it's wildly overused, especially in library code and documentation, and really, really, *really* much so in documentation examples. On 05/01/2018 06:09 AM, Craig Dillabaugh via Digitalmars-d wrote: On Monday, 30 April 2018 at 21:11:07 UTC, Gerald wrote: I'll freely admit I haven't put a ton of thought into this post (never a good start), however I'm genuinely curious what people's feeling are with regards to the auto keyword. Speaking for myself, I dislike the auto keyword. Some of this is because I have a preference for static languages and I find auto adds ambiguity with little benefit. Additionally, I find it annoying that the phobos documentation relies heavily on auto obscuring return types and making it a bit more difficult to follow what is happening which gives me a bad taste for it. clip So I'm curious, what's the consensus on auto? As some have pointed out, it certainly has value. For example, in functions returning ranges, etc. where you wouldn't want to have to write out the whole type. However, as an infrequent D user I admit I prefer to see the actual type where it is feasible, as I find 'auto' is a barrier to understanding to someone who isn't familiar with a particular piece of code. I would never use auto in place of a basic type.
Re: auto: useful, annoying or bad practice?
On Sunday, 20 May 2018 at 14:35:21 UTC, I love Ice Cream wrote: On Sunday, 20 May 2018 at 02:34:38 UTC, Neia Neutuladh wrote: D is very hard to make an IDE for that would actually tell you what type the return value is. This might sound a little hard, but that's probably a fundamental failure of the D language and explains some of the poor tooling around the language. This is specifically when metaprogramming is going on. Most programming languages these days fall into one of three categories: * They don't support metaprogramming. * They support metaprogramming by reflection only, like Java and Go. As soon as you use any metaprogramming, your IDE can't tell you what types things are; you've got interface{} or Object and you're calling Field.get() and Method.invoke(). * They support metaprogramming by merit of being a dynamic language. As soon as you write a line of code, your IDE can't tell you what types things are. If you write D without any metaprogramming, it's as easy to write an IDE for that as for Java. The problem is that metaprogramming is useful, and in D it's not that hard, so we use it a lot. There are proposals floating around for "concepts" or "signatures" (basically, compile-time interfaces) that would help out a lot, but nobody's driven one of those proposals to completion, as far as I know.
Re: auto: useful, annoying or bad practice?
On Sunday, May 20, 2018 14:33:16 I love Ice Cream via Digitalmars-d wrote: > On Sunday, 20 May 2018 at 02:34:38 UTC, Neia Neutuladh wrote: > > The return type for range-oriented functions in std.algorithm > > is usually not terribly useful. > > So the first question that comes to my mind are what are the > 'rules' of the output. Which is really what typing is. It's a > series of rules. Your object is allowed to call these > methods/properties. It is 'this' size. Languages have generic > returns. D is not the only language with a concept of returning a > 'compiler determined type'. But the rules are always baked into > the API. If it's not, it's a design failure and more thought > should be put into it. > > The only place I wouldn't be so strict with auto returns is in > private methods. However, I still might tell someone to think > about what they are trying to return there. It's not an > unimportant piece of the API. That's where you get into a combination of needing good documentation and needing to know what set of traits to use to test the type to see what functionality it has. But for better or worse, asking a type what it can do is a key piece of Design by Introspection. The result can be extremely powerful, as Andrei has talked about on multiple occasions (I'd suggest watching his dconf 2015 talk about it if you haven't), but it does place a higher burden on the programmer to figure out how to use a type. So, there are pros and cons. Ultimately, auto can be extemely useful, and much of what we do with D really wouldn't be reasonably feasible without it, but it also needs to be used intelligently, because while it does bring some serious benefits, it can be at the cost of clarity if used poorly. - Jonathan M Davis
Re: auto: useful, annoying or bad practice?
On Sunday, 20 May 2018 at 02:34:38 UTC, Neia Neutuladh wrote: D is very hard to make an IDE for that would actually tell you what type the return value is. This might sound a little hard, but that's probably a fundamental failure of the D language and explains some of the poor tooling around the language.
Re: auto: useful, annoying or bad practice?
On Sunday, 20 May 2018 at 02:34:38 UTC, Neia Neutuladh wrote: The return type for range-oriented functions in std.algorithm is usually not terribly useful. So the first question that comes to my mind are what are the 'rules' of the output. Which is really what typing is. It's a series of rules. Your object is allowed to call these methods/properties. It is 'this' size. Languages have generic returns. D is not the only language with a concept of returning a 'compiler determined type'. But the rules are always baked into the API. If it's not, it's a design failure and more thought should be put into it. The only place I wouldn't be so strict with auto returns is in private methods. However, I still might tell someone to think about what they are trying to return there. It's not an unimportant piece of the API.
Re: auto: useful, annoying or bad practice?
On Sunday, 20 May 2018 at 00:44:13 UTC, I love Ice Cream wrote: Which brings me to where it probably is not a good place for it...in the return fadeclaration of a function/method. I'm very close to saying, even after having read some of the comments that try justifying it, that 100% of the time you want to specify the return type. When you create a function that returns something, you are actively deciding 'I need to return this thing, this is useful or the point of this function'. To not have that thing obviously spelled out in the API is a huge design mistake. Not only do you take away a self-documenting part of you function definition, you make someone have to either have a good IDE (which some people are adverse to using) or actually go read the source code. To not put the effort into thinking about the type (or constraints on the type when dealing with generic/templated code) is just lazy. And worse, it will facilitate libraries where people didn't think about their API as much as they should. The return type for range-oriented functions in std.algorithm is usually not terribly useful. You get a range whose capabilities depend on the type of range you pass in, so you have to read the source code in any case. But at least listing the actual return type lets you skip some reading. This design by introspection stuff is powerful, but it's unfriendly toward people trying to understand your code. D is very hard to make an IDE for that would actually tell you what type the return value is. `pragma(msg, typeof(foo))` is probably your best bet, and that's kind of terrible. Oh, there's also one other use of `auto` return types that I haven't seen mentioned before: it functions as a DMD pragma to include the function in generated .di files. Wretched, no?
Re: auto: useful, annoying or bad practice?
'auto' in the sense that C# and other languages use 'var' makes perfect sense. There is nothing wrong with it and it takes out redundant 'noise': var i = "This is a string"; // don't need to know two times that this is a string. var j = SomethingThatReturns(); // IDE or function docs will have my back here... FYI, I wouldn't use this for 'time saving'. It's to take out redundant noise, which can clutter code. It also enables easy switching of return types from methods which occasionally means you don't have to change any code. It is frequent the type you change it to might follow the same protocol/interface as the previous type. Or you are just not using anything special with the type (maybe just forwarding a return). I do a ton of C# code and it's common with the .NET framework that this happens (for instance when working with collections). In short 'auto' or 'var' is not for time saving. It's to increase code readability and code refactorability. Those are it's benefits worth a damn. Most people spend more time reading code than writing code so if you are worried about the time it takes to type out 'auto' vs. 'SomeObnoxiouslyLongAndOverlyVerboseTypeName' then I think you are turning an anthill into a mountain. It's one thing when a language feature takes away the need to write hundreds of lines of common boiler plate code, but when it just prevents you from typing out a really long name? Come on...please...that's not why 'auto'/'var' has gained industry recognition. There's just a lot of people that use it because it's an idiom without taking the time to understanding why it _is_ an idiom. So they say things like 'I type less, so I like it'. Which brings me to where it probably is not a good place for it...in the return fadeclaration of a function/method. I'm very close to saying, even after having read some of the comments that try justifying it, that 100% of the time you want to specify the return type. When you create a function that returns something, you are actively deciding 'I need to return this thing, this is useful or the point of this function'. To not have that thing obviously spelled out in the API is a huge design mistake. Not only do you take away a self-documenting part of you function definition, you make someone have to either have a good IDE (which some people are adverse to using) or actually go read the source code. To not put the effort into thinking about the type (or constraints on the type when dealing with generic/templated code) is just lazy. And worse, it will facilitate libraries where people didn't think about their API as much as they should.
Re: auto: useful, annoying or bad practice?
On Friday, 18 May 2018 at 16:25:52 UTC, Neia Neutuladh wrote: On Friday, 18 May 2018 at 10:09:20 UTC, Chris wrote: In a way Java has slowly been moving in that direction anyway, cf. this answer [2] that reminded me of D's `auto` return type. [2] https://stackoverflow.com/questions/1348199/what-is-the-difference-between-the-hashmap-and-map-objects-in-java Except the return type that you wrote in that case tells you almost everything you can do with that value. If you specify the return type of a function as `auto`, it tells you nothing. The Java equivalent would be to return Object. My point was about implementing an interface you can rely on, regardless of what auto returns, eg: auto name = user.name; user could be anything, but it still has the field / property 'name'.
Re: auto: useful, annoying or bad practice?
On Friday, 18 May 2018 at 10:09:20 UTC, Chris wrote: In a way Java has slowly been moving in that direction anyway, cf. this answer [2] that reminded me of D's `auto` return type. [2] https://stackoverflow.com/questions/1348199/what-is-the-difference-between-the-hashmap-and-map-objects-in-java Except the return type that you wrote in that case tells you almost everything you can do with that value. If you specify the return type of a function as `auto`, it tells you nothing. The Java equivalent would be to return Object.
Re: auto: useful, annoying or bad practice?
On Thursday, 17 May 2018 at 11:38:13 UTC, Kagamin wrote: I prefer types spelled as it helps to understand the code. In javascript I have to look around to figure out types of variables and then I can understand the code. In C# I saw surprising abuse like `var id = 0L;` - to think someone would go to such length only to insist on type inference. In part this can be due to unreasonably difficult to spell types like ptrdiff_t, so I try to design my code in a way that it's easy to spell types. I was working with Java 8 this week, and God did I miss `auto`. And now Java will get `var`[1], t'was about time, indeed! Java 8 introduced lambdas and functional style features. For lambdas and streams the compiler aleady performs automatic type inference (as it does for generics, btw). So the next logical step is local type inference with `var`. I think that a functional apporach (stream().filter().map()...) leads almost automatically to `auto` (pardon the pun). Else programming becomes very cumbersome, because you have to keep track of the types all the way down the chain. That's time better spent somewhere else. In a way Java has slowly been moving in that direction anyway, cf. this answer [2] that reminded me of D's `auto` return type. [1] http://segasolutionsinc.com/2018/03/30/var-in-java10/ [2] https://stackoverflow.com/questions/1348199/what-is-the-difference-between-the-hashmap-and-map-objects-in-java
Re: auto: useful, annoying or bad practice?
On Monday, 30 April 2018 at 21:11:07 UTC, Gerald wrote: I'll freely admit I haven't put a ton of thought into this post (never a good start), however I'm genuinely curious what people's feeling are with regards to the auto keyword. I prefer types spelled as it helps to understand the code. In javascript I have to look around to figure out types of variables and then I can understand the code. In C# I saw surprising abuse like `var id = 0L;` - to think someone would go to such length only to insist on type inference. In part this can be due to unreasonably difficult to spell types like ptrdiff_t, so I try to design my code in a way that it's easy to spell types.
Re: auto: useful, annoying or bad practice?
On Wednesday, 16 May 2018 at 10:52:42 UTC, KingJoffrey wrote: On Monday, 30 April 2018 at 21:11:07 UTC, Gerald wrote: So I'm curious, what's the consensus on auto? In the example below, what would I use, besides auto? auto is required for Voldemort types, so you would change it to not be a Voldemort type.
Re: auto: useful, annoying or bad practice?
On Monday, 30 April 2018 at 21:11:07 UTC, Gerald wrote: So I'm curious, what's the consensus on auto? In the example below, what would I use, besides auto? module test; void main () { import std.stdio : writeln; auto result = newKing("King Joffrey"); writeln(result.getName); } auto newKing(string name) { class King { private string _name; public string getName() { return this._name ~ " : the one true king!"; } this() { this._name = name; } } return new King; } --
Re: auto: useful, annoying or bad practice?
On Friday, 11 May 2018 at 18:44:25 UTC, H. S. Teoh wrote: On Fri, May 11, 2018 at 04:57:05PM +, Mark via Digitalmars-d wrote: On Wednesday, 9 May 2018 at 15:06:55 UTC, Jonathan M Davis wrote: > Ultimately, the key is that the user of the function needs > to be able to know how to use the return type. In some > cases, that means returning a specific type, whereas in > others, it means using auto and being clear in the > documentation about what kind of API the return type has. As > long as the API is clear, then auto can be fantastic, but if > the documentation is poorly written (or non-existant), then > it can be a serious problem. > > - Jonathan M Davis He also needs to know what requirements the parameters of the function should satisfy. We have template constraints for that, even though that could also have been "implemented" through documentation. This makes me wonder if it might be useful to have return-type constraints. A kind of static out-contract? Something that's part of the function declaration, that ensures that the return type satisfies certain properties. // Hypothetical syntax auto myfunc(R)(R r) if (isInputRange!R && isOutputRange!return) { ... // implementation here } The `isOutputRange!return` (this is just tentative syntax, you guys can probably think of better ways of writing this) statically enforces that the return type must satisfy `isOutputRange`, and, being part of the function signature, documents to the user what to expect of it. - T This method won't work for non-template functions (since template constraints can be used only in, well, templates). Granted, non-template functions with auto return type are pretty rare, but we probably don't want to impose an unnecessary restriction.
Re: auto: useful, annoying or bad practice?
On Fri, May 11, 2018 at 06:56:13PM +, Chris M. via Digitalmars-d wrote: > On Friday, 11 May 2018 at 18:44:25 UTC, H. S. Teoh wrote: > > On Fri, May 11, 2018 at 04:57:05PM +, Mark via Digitalmars-d wrote: > > > [...] > > > > This makes me wonder if it might be useful to have return-type > > constraints. A kind of static out-contract? Something that's part > > of the function declaration, that ensures that the return type > > satisfies certain properties. > > > > [...] > > Coincidentally, over in Rust... > > https://blog.rust-lang.org/2018/05/10/Rust-1.26.html Great minds think alike. :-D (Or fools seldom differ?) T -- The problem with the world is that everybody else is stupid.
Re: auto: useful, annoying or bad practice?
On Friday, 11 May 2018 at 18:44:25 UTC, H. S. Teoh wrote: On Fri, May 11, 2018 at 04:57:05PM +, Mark via Digitalmars-d wrote: [...] This makes me wonder if it might be useful to have return-type constraints. A kind of static out-contract? Something that's part of the function declaration, that ensures that the return type satisfies certain properties. [...] Coincidentally, over in Rust... https://blog.rust-lang.org/2018/05/10/Rust-1.26.html
Re: auto: useful, annoying or bad practice?
On Fri, May 11, 2018 at 04:57:05PM +, Mark via Digitalmars-d wrote: > On Wednesday, 9 May 2018 at 15:06:55 UTC, Jonathan M Davis wrote: > > Ultimately, the key is that the user of the function needs to be > > able to know how to use the return type. In some cases, that means > > returning a specific type, whereas in others, it means using auto > > and being clear in the documentation about what kind of API the > > return type has. As long as the API is clear, then auto can be > > fantastic, but if the documentation is poorly written (or > > non-existant), then it can be a serious problem. > > > > - Jonathan M Davis > > He also needs to know what requirements the parameters of the function > should satisfy. We have template constraints for that, even though > that could also have been "implemented" through documentation. This makes me wonder if it might be useful to have return-type constraints. A kind of static out-contract? Something that's part of the function declaration, that ensures that the return type satisfies certain properties. // Hypothetical syntax auto myfunc(R)(R r) if (isInputRange!R && isOutputRange!return) { ... // implementation here } The `isOutputRange!return` (this is just tentative syntax, you guys can probably think of better ways of writing this) statically enforces that the return type must satisfy `isOutputRange`, and, being part of the function signature, documents to the user what to expect of it. Could be valuable. Of course, we could repurpose existing out contracts for this, e.g.: auto myfunc(R)(R r) if (isInputRange!R) out(r) { static assert(isOutputRange!(typeof(r))); } do { } A little more verbose, and has issues with the semantics of -release, etc., but at least it gets the point across. T -- In order to understand recursion you must first understand recursion.
Re: auto: useful, annoying or bad practice?
On Wednesday, 9 May 2018 at 15:06:55 UTC, Jonathan M Davis wrote: Ultimately, the key is that the user of the function needs to be able to know how to use the return type. In some cases, that means returning a specific type, whereas in others, it means using auto and being clear in the documentation about what kind of API the return type has. As long as the API is clear, then auto can be fantastic, but if the documentation is poorly written (or non-existant), then it can be a serious problem. - Jonathan M Davis He also needs to know what requirements the parameters of the function should satisfy. We have template constraints for that, even though that could also have been "implemented" through documentation.
Re: auto: useful, annoying or bad practice?
On Monday, 30 April 2018 at 21:11:07 UTC, Gerald wrote: So I'm curious, what's the consensus on auto? My rule, is when I can't be bothered typing it all out, or can't be bothered working out what it is I'm actually meant to type, then I use auto (or var). i.e. I use it as a time saver, and that's all. The exception to that rule, is when it's important to the person writing/reading that code, to known what type is being used (and that's a rather subjective decision). In most cases, the type declaration is for other reasons (i.e not human consumption). btw. In 1969, John C. Reynolds published his paper/specification on GEDANKEN - a typeless programming language, and type declaration was simply not permitted. (Gedanken is German for thought experiment, more or less) http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.492.9205&rep=rep1&type=pdf I wonder whether this is where languages will eventually end up again, in the future some time.
Re: auto: useful, annoying or bad practice?
On Wednesday, May 09, 2018 14:31:00 Jesse Phillips via Digitalmars-d wrote: > On Wednesday, 9 May 2018 at 13:22:56 UTC, bauss wrote: > > Using "auto" you can also have multiple return types. > > > > auto foo(T)(T value) > > { > > > > static if (is(T == int)) return "int: " ~ to!string(value); > > else return value; > > > > } > > > > You cannot give that function a specific return type as it's > > either T or it's string. It's not a single type. > > Its funny, because you example makes this look like a very bad > feature. But there are legitimate cases which doesn't actually > chance the api of the returned type. Basically, it falls into the same situation as ranges and Voldemort types. If you have a situation where it doesn't make sense to restrict the return type to a specific type, where the return type depends on the template arguments, or where the return type should be hidden, then auto is great. But in all of those situations, the API has to be well-known, or the caller can't do anything useful. Worst case, you end up with a base API that's common to all of the return types (e.g. forward range) but where you have to test whether a particular set of template arguments results in a return type which supports more (e.g. a random-access range). Ultimately, the key is that the user of the function needs to be able to know how to use the return type. In some cases, that means returning a specific type, whereas in others, it means using auto and being clear in the documentation about what kind of API the return type has. As long as the API is clear, then auto can be fantastic, but if the documentation is poorly written (or non-existant), then it can be a serious problem. - Jonathan M Davis
Re: auto: useful, annoying or bad practice?
On Wednesday, 9 May 2018 at 13:22:56 UTC, bauss wrote: Using "auto" you can also have multiple return types. auto foo(T)(T value) { static if (is(T == int)) return "int: " ~ to!string(value); else return value; } You cannot give that function a specific return type as it's either T or it's string. It's not a single type. Its funny, because you example makes this look like a very bad feature. But there are legitimate cases which doesn't actually chance the api of the returned type.
Re: auto: useful, annoying or bad practice?
On Wednesday, 9 May 2018 at 12:44:34 UTC, Jonathan M Davis wrote: On Monday, April 30, 2018 21:11:07 Gerald via Digitalmars-d wrote: [...] I think that the overall consensus is that it's great but that you do have to be careful about using it when it reduces clarity without adding other benefits. [...] Using "auto" you can also have multiple return types. auto foo(T)(T value) { static if (is(T == int)) return "int: " ~ to!string(value); else return value; } You cannot give that function a specific return type as it's either T or it's string. It's not a single type.
Re: auto: useful, annoying or bad practice?
On Monday, April 30, 2018 21:11:07 Gerald via Digitalmars-d wrote: > I'll freely admit I haven't put a ton of thought into this post > (never a good start), however I'm genuinely curious what people's > feeling are with regards to the auto keyword. > > Speaking for myself, I dislike the auto keyword. Some of this is > because I have a preference for static languages and I find auto > adds ambiguity with little benefit. Additionally, I find it > annoying that the phobos documentation relies heavily on auto > obscuring return types and making it a bit more difficult to > follow what is happening which gives me a bad taste for it. > > Having said, the thing that really started my thinking about this > was this post I made: > > https://forum.dlang.org/thread/fytefnejxqdgotjkp...@forum.dlang.org > > Where in order to declare a public variable for the RedBlackTree > lowerBound/upperBound methods I had to fall back on using the > ReturnType template to declare a variable. Jonathan was nice > enough to point me in the right direction and maybe there's a way > to do this without having to fall back on ReturnType. However > this made be wonder if reliance on auto could discourage API > writers from having sane return types. > > So I'm curious, what's the consensus on auto? I think that the overall consensus is that it's great but that you do have to be careful about using it when it reduces clarity without adding other benefits. I remember when std.algorithm didn't use auto in any of its function signatures, because there was a bug in ddoc that made it so that functions that returned auto didn't show up in the docs. It was terrible. Seeing it would have scared off _way_ more people than any concerns over auto returns being confusing. You really, really, really don't want to know what many auto return types look like - especially if ranges are involved. You end up with templates wrapping templates, and seemingly simple stuff ends up looking ugly fast - e.g. until returns something like Until!("a == b", string, char). Having auto in the documentation is _must_ nicer. Really, auto return functions make things possible that would never be possible without it simply because the code would be too hard to read. In the cases where all you care about is what API a return type has and not what the return type is, auto is a true enabler. Voldemort types then take than a step further by removing the possibility of referring to the type by name and forcing you to go off of its API, which improves maintenance from the perspective of the person maintaining the function (because then they can change the return type as much as they like so long as its API is the same). But even without Voldemort types, auto return types simplify the information to remove all of that extra stuff that you don't care about the type. Of course, that can be taken too far and/or handled badly. The user of a function doesn't necessary have to care what the return type is, but they _do_ have to know enough to know what its API is. And that means that whenever a function returns auto, it needs to be clear in its documentation about what it's returning. If it's not, then obviously, the use auto becomes a problem. At least an explicit return type would have then made it possible for the user to look up the return type, whereas with auto and bad documentation, they're forced to use stuff like typeof and pragma(msg, ...) to figure out what the type is or to go look at the source code. So, while auto is awesome, anyone writing such a function needs to do a good job with documentation and try to put themselves in the shoes of whoever is using the function. Another thing that can be taken from that is that if a function is designed to return something specific as opposed to an arbitrary type with a specific API, then it's generally better to put the type in the signature so that it's clear rather than use auto. As for auto inside functions, I'd argue that it should be used heavily, and I think that most of us do. The cases where there's really no debate are functions that return auto, and when using the type's name would just be duplicating information. e.g. it's just bad practice to do Type foo = new Type(42); instead of auto foo = new Type(42); Avoiding auto buys you nothing and just increases your code maintenance if you change the type later. It's when you start using auto all over the place that it gets more debatable. e.g. auto foo = someFunc(); foo.doSomething(); auto bar = someOtherFunc(foo); Depending on what the codes doing, heavy use of auto can sometimes make such functions hard to read, and some common sense should be used. However, by using auto, you're frequently making it easier to refactor code when types change, as they sometimes
Re: auto: useful, annoying or bad practice?
On Monday, 30 April 2018 at 21:11:07 UTC, Gerald wrote: I'll freely admit I haven't put a ton of thought into this post (never a good start), however I'm genuinely curious what people's feeling are with regards to the auto keyword. Speaking for myself, I dislike the auto keyword. Some of this is because I have a preference for static languages and I find auto adds ambiguity with little benefit. Additionally, I find it annoying that the phobos documentation relies heavily on auto obscuring return types and making it a bit more difficult to follow what is happening which gives me a bad taste for it. Having said, the thing that really started my thinking about this was this post I made: https://forum.dlang.org/thread/fytefnejxqdgotjkp...@forum.dlang.org Where in order to declare a public variable for the RedBlackTree lowerBound/upperBound methods I had to fall back on using the ReturnType template to declare a variable. Jonathan was nice enough to point me in the right direction and maybe there's a way to do this without having to fall back on ReturnType. However this made be wonder if reliance on auto could discourage API writers from having sane return types. So I'm curious, what's the consensus on auto? Auto is useful... simple as that. If you don't like it don't use it. If you get confused about it then beef up your game in analysis. Obscurity can be done many ways so complaining about one specific way is not very thought out. myfunkytypethatyoudontknowabouthiddenthrough100layersofabstraction foo();
Re: auto: useful, annoying or bad practice?
On Monday, 30 April 2018 at 21:31:48 UTC, Giles Bathgate wrote: On Monday, 30 April 2018 at 21:11:07 UTC, Gerald wrote: [...] It takes some getting used to. Type inference is useful because often you don't care/know, or want to type out the full name of the type for every variable. It does, however, assume that the developer can also do type inference (when/if you need to know the type). When it's not clear what the type is by looking at the right-hand side perhaps the codebase has bigger problems. functions that return auto are a bit odd IMHO, that is a feature unique to D. C++14 would beg to differ. As would any language with Hindley-Milner type inference. Atila
Re: auto: useful, annoying or bad practice?
On 05/04/2018 12:54 PM, H. S. Teoh wrote: This is a good point. However, I'm failing to see it as a big problem, because for it to be a problem in the first place, you have to have *deliberately* passed an object of said type into a function that expects that particular concept. First of all, just to be clear in case I wasn't, I didn't mean that it's equally dangerous as globals, just that it's analogous. Globals are, of course, more dangerous. Regarding the need to deliberately pass an object of said type to a function in order to cause a problem, that's not always true: It could be a matter of the compiler choosing the wrong overload. Or sticking it in the wrong parameter on certain templated functions. Also, generally speaking, even without structural typing, the danger of passing an object of the wrong type to the wrong parameter/function/overload IS considered to be significant enough to help justify the whole premise of static typing. (Well, at least according to a certain faction of programmers, anyway ;) ) And ultimately, from a design standpoint, I really see no compelling reason *not* to require a formal declaration of "This deliberately implements isXYZ", other than just...some people just dislike it. So like, yea, we *can* get by without it...but...why would we want to?
Re: auto: useful, annoying or bad practice?
On Fri, May 04, 2018 at 12:12:09AM -0400, Nick Sabalausky (Abscissa) via Digitalmars-d wrote: [...] > The problem with structural typing is that it's unable to distinguish > between intended matches and accidental, unintended matches. This is > because it doesn't REQUIRE types/functions/etc to clearly state, "Yes, > I *intend* to be implementing interface XYZ". Or perhaps more > accurately: "Yes, I *intend* for this to satisfy isXYZ!T". (Where > "isXYZ" might be something like "isInputRange" or "isInfiniteRange", > or both, etc.) > > Note the all-caps "REQUIRE" in the paragraph above. That is to say, > it's not enough for the developer of struct Foo to toss in... > > static assert(isXYZ!Foo); > > ...because the problem doesn't lie with the "intended matches". The > problem lies with the "unintended matches". And that static assert > does nothing to help isXYZ figure out that some other type, Bar, from > some other package, is NOT deliberately designed to satisfy isXYZ even > if it just happens to *look* like it satisfies it purely by chance. This is a good point. However, I'm failing to see it as a big problem, because for it to be a problem in the first place, you have to have *deliberately* passed an object of said type into a function that expects that particular concept. Using your previous example, if somebody declared a JackInTheBox type that "accidentally" has .front, .popFront, .empty but not actually intending to be an input range, this is not a problem until you *explicitly* pass a JackInTheBox to something that expects an input range. Just because JackInTheBox happens to accidentally implement the input range API without intending to have input range semantics, doesn't by itself cause any problem. As long as you don't try passing it off as an input range, there's nothing to worry about. And even when this explicit passing is done, what's the worst that could happen? The JackInTheBox wouldn't actually implement input range functionality and would cause a bug. So you'd just debug it like you would debug any other problem. I'm not saying it's ideal, but it doesn't seem to be the huge big problem that people are making it out to be. [...] > So back you your question: How else would you do DoI? > > Answer: By making isXYZ!T reject all T which DO NOT satisfy a > deliberate, cannot-be-an-accident, condition of isXYZ's choosing. > > Thus, type T *cannot* satisfy isXYZ without T's developer saying "Yes, > I hereby certify it is my deliberate intention that T satisfies isXYZ > and that, if it does satisfy, it is by my own intention and not by > coincidental happenstance." > > The exact details of this condition aren't terribly important, but I > like Neia's suggestion of utilizing UDAs for this purpose. An old idea > I had before UDAs existed was to require a dummy member enum named > something like _satisfies_module_foo_bar_isXYZ, which of course would > be abstracted away by something more convenient...a mixin or such (but > nobody seemed remotely interested). But I like the UDA idea better. Yeah, the UDA idea is a pretty good one. I might even adopt it in my code. :-) T -- Fact is stranger than fiction.
Re: auto: useful, annoying or bad practice?
On 05/04/2018 03:56 AM, Laeeth Isharc wrote: On Friday, 4 May 2018 at 04:12:09 UTC, Nick Sabalausky (Abscissa) wrote: On 05/02/2018 10:05 AM, H. S. Teoh wrote: [...] I don't doubt that. Similar to global namespace, if the structural typing is only used heavily by one or two components of a project (ie, libs, etc), then it's not too difficult to avoid problems. The real danger and problems come when a project uses several components that all make heavy use of either a global namespace (which D luckily doesn't really have) or structural typing. [...] Have you seen Atila's concepts library? Yea, last I checked, it doesn't address what I'm talking about at all. That lib's basically just this: struct Foo {...} static assert(isXYX!Foo); But with more detailed diagnostics. (Plus it can help you write the isXYZ function.) Unless something's changed since last looked at it, it didn't address my #1 key point: If struct Foo's author *doesn't* include the lib's "@models!(Foo, isFoo)", then isFoo!Foo should return false.
Re: auto: useful, annoying or bad practice?
On Friday, 4 May 2018 at 04:12:09 UTC, Nick Sabalausky (Abscissa) wrote: On 05/02/2018 10:05 AM, H. S. Teoh wrote: [...] I don't doubt that. Similar to global namespace, if the structural typing is only used heavily by one or two components of a project (ie, libs, etc), then it's not too difficult to avoid problems. The real danger and problems come when a project uses several components that all make heavy use of either a global namespace (which D luckily doesn't really have) or structural typing. [...] Have you seen Atila's concepts library?
Re: auto: useful, annoying or bad practice?
On 05/02/2018 10:05 AM, H. S. Teoh wrote: I've been using structural typing / design by introspection to good success in my latest project, actually. I don't doubt that. Similar to global namespace, if the structural typing is only used heavily by one or two components of a project (ie, libs, etc), then it's not too difficult to avoid problems. The real danger and problems come when a project uses several components that all make heavy use of either a global namespace (which D luckily doesn't really have) or structural typing. Structral typing isn't "If it walks like a duck and quacks like a duck...". Structural typing is "If it walks and it talks, then it must be a duck, because ducks walk and have their own form of talk, so clearly anything that walks and talks must be a duck." How else would you do DoI, though? With Concepts? The advantage of using structural typing over concepts for DoI is that you would need an exponential number of concepts to catch up with a linear number of optional fields in a structural typing model. Sure, structural typing has its warts, but it's at least more scalable in this respect. With a slight variation on structural typing that's augmented with mandatory opt-in. I'll explain: The problem with structural typing is that it's unable to distinguish between intended matches and accidental, unintended matches. This is because it doesn't REQUIRE types/functions/etc to clearly state, "Yes, I *intend* to be implementing interface XYZ". Or perhaps more accurately: "Yes, I *intend* for this to satisfy isXYZ!T". (Where "isXYZ" might be something like "isInputRange" or "isInfiniteRange", or both, etc.) Note the all-caps "REQUIRE" in the paragraph above. That is to say, it's not enough for the developer of struct Foo to toss in... static assert(isXYZ!Foo); ...because the problem doesn't lie with the "intended matches". The problem lies with the "unintended matches". And that static assert does nothing to help isXYZ figure out that some other type, Bar, from some other package, is NOT deliberately designed to satisfy isXYZ even if it just happens to *look* like it satisfies it purely by chance. As an aside: Think you're not likely to hit false positives with structural typing? Well, in all honestly, unless you're really sloppy, you're not likely hit name collisions in the global namespace either...UNTIL you reach the point where projects are composed of many third-party packages, and most third party packages start using the global namespace in their own way. Then it becomes a distinct possibility. The same dynamic applies here because, like global namespaces, structural typing (by default) has no mechanism for scope-limiting or compartmentalization, and (intentionally) operates on unqualified names. We address the global namespace's lack of scope-limiting and compartmentalization through...well, namespaces. The namespaces may be implied by classes (old-school Java), by compilation units (D), or specified manually (C++). But how do we address structural typing's lack of scope-limiting and compartmentalization? Currently, we don't. And that's the problem. So back you your question: How else would you do DoI? Answer: By making isXYZ!T reject all T which DO NOT satisfy a deliberate, cannot-be-an-accident, condition of isXYZ's choosing. Thus, type T *cannot* satisfy isXYZ without T's developer saying "Yes, I hereby certify it is my deliberate intention that T satisfies isXYZ and that, if it does satisfy, it is by my own intention and not by coincidental happenstance." The exact details of this condition aren't terribly important, but I like Neia's suggestion of utilizing UDAs for this purpose. An old idea I had before UDAs existed was to require a dummy member enum named something like _satisfies_module_foo_bar_isXYZ, which of course would be abstracted away by something more convenient...a mixin or such (but nobody seemed remotely interested). But I like the UDA idea better.
Re: auto: useful, annoying or bad practice?
On Monday, 30 April 2018 at 21:11:07 UTC, Gerald wrote: So I'm curious, what's the consensus on auto? Speaking for myself: 1) I find auto to be useful when instantiating objects locally; eliminates redundancy, noise, and line size. 2) I avoid auto functions and despise them in API documentation. It’s difficult to work with the return type of a function when the definition is auto and the author didn’t follow up by describing exactly what was returned. 3) I avoid auto for primitive types because their type names are short, and declaring them C- and Ada-style at the beginning of a local block helps massively clarify what a function is about to do. So basically only for object instantiations. I’ve yet to find a great use for it outside of that.
Re: auto: useful, annoying or bad practice?
On Monday, 30 April 2018 at 21:11:07 UTC, Gerald wrote: I'll freely admit I haven't put a ton of thought into this post (never a good start), however I'm genuinely curious what people's feeling are with regards to the auto keyword. So I'm curious, what's the consensus on auto? I'll start with auto for declaration and then talk about auto for return types. The main issue with utilizing auto is that a type will lead you to documentation on the capabilities of the variable and to locate the implementation of the code being called. The desire to decouple from the concrete type is admirable but generally the desire for the concrete type isn't about coupling with it. What I find though is that auto doesn't increase the difficulty of the objectives I described. What I find is in other languages (generally C# and Java) is that you won't be returned a concrete type but an interface. This can be nice for capabilities of the variable but all to often I find that the API still expects you to convert to a concrete type. And you still need to track down the actually concrete type to review the actual implementation of that function. I find auto to be very useful for development as I can switch out the type be it a class/struct or interface rather easily. I have mixed feelings when it comes to debugging. For a stable and unchanging interface (concept not construct) it should be avoided. Use of auto in return type I also like but use sparingly. This is because it hides documentation of an API. And I'm not talking about the function documentation laking specification of what it returns I'm talking about types being a good way to make a point of reference. For example an auto function which returns a range can easily reference the Range API since it is the D interface for iteration. Custom/framework types don't have that luxury.
Re: auto: useful, annoying or bad practice?
On Wednesday, 2 May 2018 at 14:05:49 UTC, H. S. Teoh wrote: How else would you do DoI, though? With Concepts? The advantage of using structural typing over concepts for DoI is that you would need an exponential number of concepts to catch up with a linear number of optional fields in a structural typing model. Sure, structural typing has its warts, but it's at least more scalable in this respect. UDAs to the rescue! class JackInTheBox { // Which way is it facing? Direction front(); // Pop the box open and have the doll spring out toward the front side void popFront(); // Remove everything from the box. Return true if stuff was removed. bool empty(); } We're in for a bad time. @Range class JackInTheBox { ... } Here I just shot myself in the foot. // A document is a range of pages, maybe. @Range struct Document { // saves to disk SaveResults save(); } This is a subtler problem. struct Document { @Range SaveResults save(); } I shot myself in the foot again. It's analogous to explicit interface inheritance in C#. Thanks to D's options for applying annotations to a block or in label style, it wouldn't be terribly onerous.
Re: auto: useful, annoying or bad practice?
On Wednesday, 2 May 2018 at 14:05:49 UTC, H. S. Teoh wrote: How else would you do DoI, though? With Concepts? The advantage of using structural typing over concepts for DoI is that you would need an exponential number of concepts to catch up with a linear number of optional fields in a structural typing model. Sure, structural typing has its warts, but it's at least more scalable in this respect. T Why? I don't think concepts force you to write a specific implementation for every possible combination of compile-time values.
Re: auto: useful, annoying or bad practice?
On Wed, May 02, 2018 at 12:11:57AM -0400, Nick Sabalausky (Abscissa) via Digitalmars-d wrote: > On 04/30/2018 05:35 PM, H. S. Teoh wrote: > > > > Also, design by introspection. Dependence on explicit types is so > > last century. Design by introspection FTW! Decoupling your code > > from explicit types makes it more encapsulated, and gives you > > incentive to write more defensively, resulting in better, more > > change-resilient code. When an upstream library changes a return > > type, you can just recompile and go, rather than waste time patching > > the 150 different places where the explicit type was named. Let the > > machine do the work for you! > > > > There's a lot about that I like too, but I really wish D didn't use > structral typing to do it. I still think the only reason D's structral > typing hasn't blown up in our faces is because it's still mostly > limited to the basic ranges isn't not a prevalent part of most > internal and external APIs. Structural typing basically amounts to a > form of global namespace (which can also work out ok *if used > sparingly*, not that I'd want to try). At first, D thankfully killed > off the global namespace for the most part...but then it brings its > pitfalls right back in the form of structural typing. Grrr... I've been using structural typing / design by introspection to good success in my latest project, actually. I was writing a submodule that handled interfacing with POVRay for 3D rendering (non-realtime, obviously), and wanted a clean API that didn't force tons of boilerplate on you. The main problem here is that POVRay has so many features, knobs, and dials that either you have to dumb things down so much that you're no longer using most of its features, which defeats the purpose of using it(!), or you have to essentially reinvent SDL in your API so that your users have access to everything they might need, which makes your API so complex and hairy it would require Java-style verbosity, complete with factory classes, wrapper types, a class hierarchy, and gratuitousUnreasonablyLongIdentifiers, just to initialize it to do something as simple as rendering a couple of polygons. Eventually, I settled on DoI by specifying some basic required properties for, say, polygons to be output as a mesh, y'know, vertex coordinates and lists of vertex indices for the polygons, with many optional parameters checked by static if. So if you wanted just to output a couple of polygons with flat textures, all you have to do is to pass in an array of vectors and an array of int[]'s, and off you go. If you wanted different textures for each polygon, make a struct that aliases int[] to this (or overloads opIndex) plus a .texture field to specify the texture. If you wanted surface normal interpolation, wrap your vectors in a struct that has a .normal field specifying the normals to interpolate. On the implementation side, it's just a bunch of static if's that optionally checks if a property is present, and provide implementation for it if it is. If it weren't for DoI, I would've ended up with a big, complicated API with tons of boolean switches or a class hierarchy to provide for all the variations that might be needed, and it would have required a ton of boilerplate just to output a couple of flat polygons. With DoI, I get to scale the amount of initialization code I need according to how many features I will actually use. > Structral typing isn't "If it walks like a duck and quacks like a > duck...". Structural typing is "If it walks and it talks, then it > must be a duck, because ducks walk and have their own form of talk, so > clearly anything that walks and talks must be a duck." How else would you do DoI, though? With Concepts? The advantage of using structural typing over concepts for DoI is that you would need an exponential number of concepts to catch up with a linear number of optional fields in a structural typing model. Sure, structural typing has its warts, but it's at least more scalable in this respect. T -- What do you call optometrist jokes? Vitreous humor.
Re: auto: useful, annoying or bad practice?
On Wednesday, 2 May 2018 at 00:01:42 UTC, Nick Sabalausky wrote: Now, all that said, using auto for a function signature's return type shouldn't usually be done, except in very careful, specific "voldemort type" kinds of situations (and even then, I dont see a real big point). I do it all the time because of attribute inference. D has way to many attributes, so I'm willing to automatically let the Compiler interfere which are appropriate, he knows it better anyway.
Re: auto: useful, annoying or bad practice?
On 04/30/2018 05:35 PM, H. S. Teoh wrote: Also, design by introspection. Dependence on explicit types is so last century. Design by introspection FTW! Decoupling your code from explicit types makes it more encapsulated, and gives you incentive to write more defensively, resulting in better, more change-resilient code. When an upstream library changes a return type, you can just recompile and go, rather than waste time patching the 150 different places where the explicit type was named. Let the machine do the work for you! There's a lot about that I like too, but I really wish D didn't use structral typing to do it. I still think the only reason D's structral typing hasn't blown up in our faces is because it's still mostly limited to the basic ranges isn't not a prevalent part of most internal and external APIs. Structural typing basically amounts to a form of global namespace (which can also work out ok *if used sparingly*, not that I'd want to try). At first, D thankfully killed off the global namespace for the most part...but then it brings its pitfalls right back in the form of structural typing. Grrr... Structral typing isn't "If it walks like a duck and quacks like a duck...". Structural typing is "If it walks and it talks, then it must be a duck, because ducks walk and have their own form of talk, so clearly anything that walks and talks must be a duck."
Re: auto: useful, annoying or bad practice?
On Monday, 30 April 2018 at 21:11:07 UTC, Gerald wrote: So I'm curious, what's the consensus on auto? For local variables, it's not an unalloyed good, but it is good. When I use Java, everything is explicit, and sometimes that's nice. In D, I think I overuse `auto` for local variables. Sometimes I find myself switching it out for an explicit type, just because I want the compiler to check that the right-hand side is of the type I expect (eg with numeric conversion rules). For function return types, though? The consensus among Phobos devs is it's a "here be dragons" sign. It's a sign that there could be breaking changes to your code without warning if you use that return type in a nontrivial way. Of course, this isn't made clear anywhere, and they don't actually make these changes all that often. But even for that purpose, it's broken. Like your example was basically: RBRange!(RBNode!long*) divide(RedBlackTree!long tree, long pivot, bool first) { if (first) return tree.upperBound(pivot); return tree.lowerBound(pivot); } If the range type were public, your code would work. If subsequently the Phobos devs needed to change the range type, they could provide an alias, and your code would still work. If they needed to change upperBound to return a different type than lowerBound, there's nothing they can do about it; your code is broken. But since the return type for both functions is `auto`, they can tell you you were wrong to write that code and they were right to make it stop working.
Re: auto: useful, annoying or bad practice?
I'm a die-hard static typing fan, hate dynamic languages, heck I dont even like structural typing (ex, as used by D ranges). And that's exactly why I *love* auto. It lets you have static typing without turning programming into a 2000's-era C++/Java-style royal anti-DRY PITA. I also think auto is especially nice for NOT requiring a heavy-weight IDE, because it makes refactorings and type renaming much simpler. In the very rare case that I'm not clear what type a var is, first of all, that's usually a sign something else is wrong with the code, and secondly, that's trivially answered by tossing in a "pragma(msg, typeof(xxxx))". Now, all that said, using auto for a function signature's return type shouldn't usually be done, except in very careful, specific "voldemort type" kinds of situations (and even then, I dont see a real big point).
Re: auto: useful, annoying or bad practice?
I'm a die-hard static typing fan, hate dynamic languages, heck I dont even like structural typing (ex, as used by D ranges). And that's exactly why I *love* auto. It lets you have static typing without turning programming into a 2000's-era C++/Java-style royal anti-DRY PITA. I also think auto is especially nice for NOT requiring a heavy-weight IDE, because it makes refactorings and type renaming much simpler. In the very rare case that I'm not clear what type a var is, first of all, that's usually a sign something else is wrong with the code, and secondly, that's trivially answered by tossing in a "pragma(msg, typeof(xxxx))". Now, all that said, using auto for a function signature's return type shouldn't usually be done, except in very careful, specific "voldemort type" kinds of situations (and even then, I dont see a real big point).
Re: auto: useful, annoying or bad practice?
On Monday, 30 April 2018 at 21:11:07 UTC, Gerald wrote: I'll freely admit I haven't put a ton of thought into this post (never a good start), however I'm genuinely curious what people's feeling are with regards to the auto keyword. Speaking for myself, I dislike the auto keyword. Some of this is because I have a preference for static languages and I find auto adds ambiguity with little benefit. Additionally, I find it annoying that the phobos documentation relies heavily on auto obscuring return types and making it a bit more difficult to follow what is happening which gives me a bad taste for it. clip So I'm curious, what's the consensus on auto? As some have pointed out, it certainly has value. For example, in functions returning ranges, etc. where you wouldn't want to have to write out the whole type. However, as an infrequent D user I admit I prefer to see the actual type where it is feasible, as I find 'auto' is a barrier to understanding to someone who isn't familiar with a particular piece of code. I would never use auto in place of a basic type.
Re: auto: useful, annoying or bad practice?
On Monday, 30 April 2018 at 21:56:23 UTC, H. S. Teoh wrote: On Mon, Apr 30, 2018 at 09:31:48PM +, Giles Bathgate via Digitalmars-d wrote: [...] [...] T On Monday, 30 April 2018 at 21:56:23 UTC, H. S. Teoh wrote: [...] Appart from the good points Teoh has made, imagine you would have to statically type in for loops: foreach (i; items) writefln("%s", i); And, yeah, chainig would indeed be a PIA: auto items = myRange.filter!(a => a.length); Most of the time you don't really care about the exact type, only at the end of the block (e.g. it should be `string[]`). And the compiler always tells you about the types, e.g. something like "cannot implicitly convert `words` of type MapResult to string[]". And then, _at the end_, you can use something like items.array; to get `string[]`. I think the problem is not `auto`, the problem is thinking in old ways. If you think old-style Java where you declare loads of statically typed class variables at the beginning, then you're in trouble. But in order to use `auto`, you have to use a different approach. Java: String name; String address; int uiid; ... String getName() { return name; } [...] In D, you are more likely to use home made structs / ranges / tuples as return types that all have the same properties, so auto makes more sense (incomplete code): auto byUser(R)(R entries) { struct User { private { R entries; } this(R entries) { this.entries = entries; } @property bool empty() { return range empty? (true|false) } @property void popFront() { // e.g. entries = entries[1..$]; } @property auto front() { return whatever; // e.g. struct UserInfo { string name; size_t uuid; } } } return User(entries); } The struct `User` can perform whatever is necessary, it can be changed, even renamed but the return type will always conform to the range interface: empty, popFront, front, so the caller can be sure s/he can use it as a range. Also, the type of `entries` can change, but the code will still work. No need to redefine all the variables as a different type. Now auto users = entries.byUser(); can be whatever and you can perform other range based algorithms [1] auto herberts = entries.byUser.filter!(a => a.name == 'Herbert')...etc.etc. Imagine having to use handwritten static typing for that! [1] https://tour.dlang.org/tour/en/gems/range-algorithms
Re: auto: useful, annoying or bad practice?
On Mon, Apr 30, 2018 at 09:31:48PM +, Giles Bathgate via Digitalmars-d wrote: [...] > functions that return auto are a bit odd IMHO, that is a feature > unique to D. But I don't have a problem with type inference in > general, all language have it including C#, C++, TypeScript, > Rust...etc not that that is a good argument, but just that its > something you have to get used to, because people will use the feature > whether you like it or not. [...] To me, a function that returns auto is basically saying "you should not need to know, nor should you depend on, the dirty details of the actual return type". There's a time and place for that, and I don't recommend liberally sprinkling auto return types everywhere just for laziness' sake. But when it's used, it should be used for improving encapsulation, by reducing the leakage of implementation details of the return type, and limiting the calling code to using only agreed-upon properties (i.e., via documentation, contract, etc.) or introspection using static if (meaning that your code is explicitly checking for a certain property before using it, which is a good defensive design, and presumably will be able to handle the case where said property no longer holds). Basically, it's stepping away from the bad old practice of the caller code digging into the innards of your data types that were never meant for public use, and consequently you being locked into a particular implementation because changing said innards will break existing code, even if existing code isn't using the type "properly"; and stepping into a better world of more encapsulated and flexible code. It's stepping away from that old world of code depending on "undocumented features" and "hidden calls", to a better world of code that will Just Work(tm) even if the underlying library changes a return type, and code that can adapt itself to the return type by using introspection to discover what is/isn't available without hardcoding anything or making unfounded assumptions about what the return type has/doesn't have. T -- Music critic: "That's an imitation fugue!"
Re: auto: useful, annoying or bad practice?
On Monday, 30 April 2018 at 21:11:07 UTC, Gerald wrote: I'll freely admit I haven't put a ton of thought into this post (never a good start), however I'm genuinely curious what people's feeling are with regards to the auto keyword. Speaking for myself, I dislike the auto keyword. Some of this is because I have a preference for static languages and I find auto adds ambiguity with little benefit. Additionally, I find it annoying that the phobos documentation relies heavily on auto obscuring return types and making it a bit more difficult to follow what is happening which gives me a bad taste for it. It takes some getting used to. Type inference is useful because often you don't care/know, or want to type out the full name of the type for every variable. It does, however, assume that the developer can also do type inference (when/if you need to know the type). When it's not clear what the type is by looking at the right-hand side perhaps the codebase has bigger problems. functions that return auto are a bit odd IMHO, that is a feature unique to D. But I don't have a problem with type inference in general, all language have it including C#, C++, TypeScript, Rust...etc not that that is a good argument, but just that its something you have to get used to, because people will use the feature whether you like it or not.
Re: auto: useful, annoying or bad practice?
On Mon, Apr 30, 2018 at 09:11:07PM +, Gerald via Digitalmars-d wrote: [...] > So I'm curious, what's the consensus on auto? Don't know what others think, but personally, it's one of the best things about D: all the safety of static typing, yet with the convenience of automatic type inference, so that I don't have to keep repeating myself. When I'm using chained range-based algorithms, I really do *not* want to have to name every intermediate type explicitly. That would be so cumbersome that the idiom would be essentially useless. Also, design by introspection. Dependence on explicit types is so last century. Design by introspection FTW! Decoupling your code from explicit types makes it more encapsulated, and gives you incentive to write more defensively, resulting in better, more change-resilient code. When an upstream library changes a return type, you can just recompile and go, rather than waste time patching the 150 different places where the explicit type was named. Let the machine do the work for you! As for ReturnType: I actually find it completely worthless. It adds needless template bloat, where typeof() (specifically, typeof(return)) would do just fine. And as for the documentation issue: either (1) the docs are b0rken and need to be rewritten because they didn't describe the returned type sufficiently well, in which case either the docs need to be fixed, or the library is poorly written and you should find another one; or (2) it is an indication that your code has extraneous dependencies on explicit return types and therefore is flaky and will break with the slightest upstream changes, in which case the code should be restructured and the needless assumptions / dependencies removed. T -- 2+2=4. 2*2=4. 2^2=4. Therefore, +, *, and ^ are the same operation.
Re: auto: useful, annoying or bad practice?
On Monday, 30 April 2018 at 21:11:07 UTC, Gerald wrote: Speaking for myself, I dislike the auto keyword. Some of this is because I have a preference for static languages and I find auto adds ambiguity with little benefit. Additionally, I find it annoying that the phobos documentation relies heavily on auto obscuring return types and making it a bit more difficult to follow what is happening which gives me a bad taste for it. I'm of the same opinion. I think auto (or var in other languages) obscures the types and requires an IDE to reveal what the real type is (hopefully the IDE can figure it out). But it seems we are in minority. Even Java is adopting auto (called var there) and everyone is cheering for that :)
auto: useful, annoying or bad practice?
I'll freely admit I haven't put a ton of thought into this post (never a good start), however I'm genuinely curious what people's feeling are with regards to the auto keyword. Speaking for myself, I dislike the auto keyword. Some of this is because I have a preference for static languages and I find auto adds ambiguity with little benefit. Additionally, I find it annoying that the phobos documentation relies heavily on auto obscuring return types and making it a bit more difficult to follow what is happening which gives me a bad taste for it. Having said, the thing that really started my thinking about this was this post I made: https://forum.dlang.org/thread/fytefnejxqdgotjkp...@forum.dlang.org Where in order to declare a public variable for the RedBlackTree lowerBound/upperBound methods I had to fall back on using the ReturnType template to declare a variable. Jonathan was nice enough to point me in the right direction and maybe there's a way to do this without having to fall back on ReturnType. However this made be wonder if reliance on auto could discourage API writers from having sane return types. So I'm curious, what's the consensus on auto?
Re: understanding Auto-Test
On Thursday, 22 March 2018 at 05:00:07 UTC, John Belmonte wrote: On Thursday, 22 March 2018 at 04:25:00 UTC, Seb wrote: - Every time a PR is merged at dmd, druntime or phobos ALL auto-tester results get invalidated If a change on the destination branch causes a PR to require an automatic merge, certainly build and tests should be rerun. But if the two changes are unrelated do the results of all pending PR's need to be invalidated? Well, auto-tester is in place for a few years already. Its git history [1] goes back to 2010, but I assume the auto-tester to be even older. Back in these old, dark ages, a commit in another PR (even if it's a different repo), was a bit more likely to break the current PR. Nowadays, that's a lot less common, but still happens from time to time (e.g. you make a PR to deprecate sth., but in the meanwhile a new usage got added to Phobos or a new @safe-ty violation got added). Anyhow, the idea is to guarantee that `master` is always buildable and passes all tests no matter what and this constant invalidation is the only way to deal with this as there's no way to automatically determine whether the new changes in master are really unrelated. Note that what the auto-tester does for you automatically, is very similar to GitHub's "Require branches to be up to date before merging" branch setting, except that instead of manually needing to rebase the branch all the time, auto-tester does the rebases automatically and is "cross-repository aware". [1] https://github.com/braddr/at-client
Re: understanding Auto-Test
On Thursday, 22 March 2018 at 04:25:00 UTC, Seb wrote: - Every time a PR is merged at dmd, druntime or phobos ALL auto-tester results get invalidated If a change on the destination branch causes a PR to require an automatic merge, certainly build and tests should be rerun. But if the two changes are unrelated do the results of all pending PR's need to be invalidated? Did this clarify things for you? Yes, thank you for taking the time to explain the system.
Re: understanding Auto-Test
On Thursday, 22 March 2018 at 04:17:52 UTC, Mike Franklin wrote: On Thursday, 22 March 2018 at 04:12:00 UTC, John Belmonte wrote: I'm still rather puzzled. My pull request remains with 8 tests pending after several hours. I can't find any confirmation on the pulls display https://auto-tester.puremagic.com/pulls.ghtml?projectid=1 that it intends to run the tests. Surely being listed in the "Old results" table doesn't imply pending runs against a new SHA, otherwise why would there be entries there dated 2017? I see. It appears GitHub didn't pick of the latest status (or the auto-tester didn't notify GitHub; Everything is working as expected. Every time a PR gets merged, ALL pull requests get invalidated and are moved to "Old results" as their results have been calculated against an old head. Then auto-tester starts to reduce the "Old results" list by building them again. It's a constant fight. I'm not which way the data flows). GitHub -> CIs (via hooks) (though especially auto-tester queries back a lot) Let's see what happens after the auto-tester starts testing it again. I'll keep an eye on it. No need to keep an eye on this. auto-tester will constantly rebuild the PR and invalidate it. The only way interaction is possible is via: - manually invalidating builds (called "delete" at the auto-tester) - not really useful as builds are automatically invalidated - "auto-merge" priority builds. The PR has super-priority in the build queue. That's happening currently with the four builds at the top: https://imgur.com/a/29Ohn
Re: understanding Auto-Test
On Thursday, 22 March 2018 at 04:12:00 UTC, John Belmonte wrote: On Thursday, 22 March 2018 at 01:51:49 UTC, Mike Franklin wrote: I believe what happened is a different PR was merged. When a PR is merged, all tests are invalidated, and the autotester begins testing them again. There is also a priority affecting which PRs get tested first. Those that are labeled with "AutoMerge" are given a higher priority. I'm still rather puzzled. My pull request remains with 8 tests pending after several hours. I can't find any confirmation on the pulls display https://auto-tester.puremagic.com/pulls.ghtml?projectid=1 that it intends to run the tests. Surely being listed in the "Old results" table doesn't imply pending runs against a new SHA, otherwise why would there be entries there dated 2017? I give it a shot: - Every time a PR is merged at dmd, druntime or phobos ALL auto-tester results get invalidated - The auto-tester constantly tries to build PRs which have now results based on his queue (it's sorted after merge priority + last pushed timestamp) The traffic is usually so high that your PR will always be at pending. That's really not a big deal. On the contrary, once your PR has been approved and gets on the merge queue, it will receive higher priority and usually will be merged within 1-3 hours. Also all reviewers are familiar with auto-tester and pending tests have zero effect on the reviewers. All the other CIs already give a good feedback and if they want to, they can check the history of auto-tester for permanent failures I can't find any confirmation on the pulls display that it intends to run the tests. There's none. It _constantly_ reruns your PR. Surely being listed in the "Old results" table doesn't imply pending runs against a new SHA, otherwise why would there be entries there dated 2017? The timestamp you see on pulls.ghtml?projectid=1 is GitHub's last modified timestamp which essentially is timestamp of the last push to the respective branch. And yep there are a few old PRs, but the auto-tester newer tests them as its working queue order is sorted by the "Last Commited" timestamp. Did this clarify things for you?
Re: understanding Auto-Test
On Thursday, 22 March 2018 at 04:12:00 UTC, John Belmonte wrote: I'm still rather puzzled. My pull request remains with 8 tests pending after several hours. I can't find any confirmation on the pulls display https://auto-tester.puremagic.com/pulls.ghtml?projectid=1 that it intends to run the tests. Surely being listed in the "Old results" table doesn't imply pending runs against a new SHA, otherwise why would there be entries there dated 2017? I see. It appears GitHub didn't pick of the latest status (or the auto-tester didn't notify GitHub; I'm not which way the data flows). Let's see what happens after the auto-tester starts testing it again. I'll keep an eye on it. Mike
Re: understanding Auto-Test
On Thursday, 22 March 2018 at 04:17:52 UTC, Mike Franklin wrote: Let's see what happens after the auto-tester starts testing it again. Note that it could be a while, as there are PRs that will be getting merged in the next 24 hours that will restart the test queue. Mike
Re: understanding Auto-Test
On Thursday, 22 March 2018 at 01:51:49 UTC, Mike Franklin wrote: I believe what happened is a different PR was merged. When a PR is merged, all tests are invalidated, and the autotester begins testing them again. There is also a priority affecting which PRs get tested first. Those that are labeled with "AutoMerge" are given a higher priority. I'm still rather puzzled. My pull request remains with 8 tests pending after several hours. I can't find any confirmation on the pulls display https://auto-tester.puremagic.com/pulls.ghtml?projectid=1 that it intends to run the tests. Surely being listed in the "Old results" table doesn't imply pending runs against a new SHA, otherwise why would there be entries there dated 2017?
Re: understanding Auto-Test
On Thursday, 22 March 2018 at 01:46:08 UTC, John Belmonte wrote: I'm trying to understand why my pull request was queued in D2 Auto-Test for only 2 of 8 tests, with the remaining left in pending state. https://auto-tester.puremagic.com/pull-history.ghtml?projectid=1&repoid=1&pullid=8051 Since there are pending tests, I'd expect it to appear in the standard priority pull queue under "Has passes". https://auto-tester.puremagic.com/pulls.ghtml?projectid=1 What I'm I overlooking? Kindly, --John I believe what happened is a different PR was merged. When a PR is merged, all tests are invalidated, and the autotester begins testing them again. There is also a priority affecting which PRs get tested first. Those that are labeled with "AutoMerge" are given a higher priority. Mike
understanding Auto-Test
I'm trying to understand why my pull request was queued in D2 Auto-Test for only 2 of 8 tests, with the remaining left in pending state. https://auto-tester.puremagic.com/pull-history.ghtml?projectid=1&repoid=1&pullid=8051 Since there are pending tests, I'd expect it to appear in the standard priority pull queue under "Has passes". https://auto-tester.puremagic.com/pulls.ghtml?projectid=1 What I'm I overlooking? Kindly, --John
Re: template auto value
On Monday, 5 March 2018 at 13:03:50 UTC, Steven Schveighoffer wrote: On 3/2/18 8:49 PM, Jonathan Marler wrote: On Saturday, 3 March 2018 at 00:20:14 UTC, H. S. Teoh wrote: On Fri, Mar 02, 2018 at 11:51:08PM +, Jonathan Marler via Digitalmars-d wrote: [...] Not true: template counterexample(alias T) {} int x; string s; alias U = counterexample!x; // OK alias V = counterexample!1; // OK alias W = counterexample!"yup"; // OK alias X = counterexample!s; // OK alias Z = counterexample!int; // NG The last one fails because a value is expected, not a type. If you *really* want to accept both values and types, `...` comes to the rescue: template rescue(T...) if (T.length == 1) {} int x; string s; alias U = rescue!x; // OK alias V = rescue!1; // OK alias W = rescue!"yup"; // OK alias X = rescue!s; // OK alias Z = rescue!int; // OK! T Ah thank you...I guess I didn't realize that literals like 1 and "yup" were considered "symbols" when it comes to alias template parameters. Well, they aren't. But template alias is a bit of a mess when it comes to the spec. It will accept anything except keywords AFAIK. Would be nice if it just worked like the variadic version. The variadic version is what is usually needed (you see a lot of if(T.length == 1) in std.traits). But, if you wanted to ensure values (which is more akin to your proposal), you can do: template rescue(alias val) if(!is(val)) // not a type -Steve Thanks for the tip, it looks like the spec does mention "literals" but "alias" parameters are even more versatile than that (https://dlang.org/spec/template.html#TemplateAliasParameter). For example you can pass a function call. I've created an issue to make sure we update the spec to reflect the true capabilities: https://issues.dlang.org/show_bug.cgi?id=18558
Re: template auto value
On 3/2/18 8:49 PM, Jonathan Marler wrote: On Saturday, 3 March 2018 at 00:20:14 UTC, H. S. Teoh wrote: On Fri, Mar 02, 2018 at 11:51:08PM +, Jonathan Marler via Digitalmars-d wrote: [...] Not true: template counterexample(alias T) {} int x; string s; alias U = counterexample!x; // OK alias V = counterexample!1; // OK alias W = counterexample!"yup"; // OK alias X = counterexample!s; // OK alias Z = counterexample!int; // NG The last one fails because a value is expected, not a type. If you *really* want to accept both values and types, `...` comes to the rescue: template rescue(T...) if (T.length == 1) {} int x; string s; alias U = rescue!x; // OK alias V = rescue!1; // OK alias W = rescue!"yup"; // OK alias X = rescue!s; // OK alias Z = rescue!int; // OK! T Ah thank you...I guess I didn't realize that literals like 1 and "yup" were considered "symbols" when it comes to alias template parameters. Well, they aren't. But template alias is a bit of a mess when it comes to the spec. It will accept anything except keywords AFAIK. Would be nice if it just worked like the variadic version. The variadic version is what is usually needed (you see a lot of if(T.length == 1) in std.traits). But, if you wanted to ensure values (which is more akin to your proposal), you can do: template rescue(alias val) if(!is(val)) // not a type -Steve
Re: template auto value
On Saturday, 3 March 2018 at 00:20:14 UTC, H. S. Teoh wrote: On Fri, Mar 02, 2018 at 11:51:08PM +, Jonathan Marler via Digitalmars-d wrote: [...] Not true: template counterexample(alias T) {} int x; string s; alias U = counterexample!x; // OK alias V = counterexample!1; // OK alias W = counterexample!"yup"; // OK alias X = counterexample!s; // OK alias Z = counterexample!int; // NG The last one fails because a value is expected, not a type. If you *really* want to accept both values and types, `...` comes to the rescue: template rescue(T...) if (T.length == 1) {} int x; string s; alias U = rescue!x; // OK alias V = rescue!1; // OK alias W = rescue!"yup"; // OK alias X = rescue!s; // OK alias Z = rescue!int; // OK! T Ah thank you...I guess I didn't realize that literals like 1 and "yup" were considered "symbols" when it comes to alias template parameters.
Re: template auto value
On 03.03.2018 01:20, H. S. Teoh wrote: On Fri, Mar 02, 2018 at 11:51:08PM +, Jonathan Marler via Digitalmars-d wrote: I believe I found small hole in template parameter semantics. [...] you can't create a template that accepts a value of any type. Not true: template counterexample(alias T) {} int x; string s; alias U = counterexample!x; // OK alias V = counterexample!1; // OK alias W = counterexample!"yup"; // OK alias X = counterexample!s; // OK alias Z = counterexample!int; // NG The last one fails because a value is expected, not a type. No, it fails because a "symbol" is expected, not a basic type. There really is no good reason why int should not be accepted -- a class or struct type would be accepted. IIRC Walter has agreed to this, and it's just pending implementation.
Re: template auto value
On Fri, Mar 02, 2018 at 11:51:08PM +, Jonathan Marler via Digitalmars-d wrote: > I believe I found small hole in template parameter semantics. > [...] you can't create a template that accepts a value of any type. Not true: template counterexample(alias T) {} int x; string s; alias U = counterexample!x; // OK alias V = counterexample!1; // OK alias W = counterexample!"yup"; // OK alias X = counterexample!s; // OK alias Z = counterexample!int; // NG The last one fails because a value is expected, not a type. If you *really* want to accept both values and types, `...` comes to the rescue: template rescue(T...) if (T.length == 1) {} int x; string s; alias U = rescue!x; // OK alias V = rescue!1; // OK alias W = rescue!"yup"; // OK alias X = rescue!s; // OK alias Z = rescue!int; // OK! T -- In a world without fences, who needs Windows and Gates? -- Christian Surchi
template auto value
I believe I found small hole in template parameter semantics. I've summarized it here (https://github.com/marler8997/dlangfeatures#template-auto-value-parameter). Wanted to get feedback before I look into creating a PR for it. -- COPY/PASTED from https://github.com/marler8997/dlangfeatures#template-auto-value-parameter -- If you reference the D grammar for templates (See https://dlang.org/spec/template.html), there are currently 5 categories of template parameters: TemplateParameter: TemplateTypeParameter TemplateValueParameter TemplateAliasParameter TemplateSequenceParameter TemplateThisParameter However there is a hole in this list, namely, generic template value parameters. The current TemplateValueParameter grammar node must explicitly declare a "BasicType": TemplateValueParameter: BasicType Declarator BasicType Declarator TemplateValueParameterSpecialization BasicType Declarator TemplateValueParameterDefault BasicType Declarator TemplateValueParameterSpecialization TemplateValueParameterDefault For example: --- template foo(string value) { } foo!"hello"; --- However, you can't create a template that accepts a value of any type. This would a good use case for the auto keyword, i.e. --- template foo(auto value) { } foo!0; foo!"hello"; --- This would be a simple change to the grammar, namely, BasicTemplateType: BasicType auto TemplateValueParameter: BasicTemplateType Declarator BasicTemplateType Declarator TemplateValueParameterSpecialization BasicTemplateType Declarator TemplateValueParameterDefault BasicTemplateType Declarator TemplateValueParameterSpecialization TemplateValueParameterDefault
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.
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.
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.
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.
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...
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 = &foo; // a pointer auto* p = &foo; // 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 = &foo; // a pointer > auto* p = &foo; // 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 = &foo;// A local variable here auto p = &x; } 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 = &foo; // a pointer > auto* p = &foo; // 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 = &foo;` already gives you a pointer. If foo itself is also a pointer, `auto p = &foo;` 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 = &foo; // takes address of foo (single pointer) auto pp = &p; // takes address of p (double pointer) It's invalid to take the address of an rvalue, because an rvalue has no location. I.e., `&(&foo)` is illegal because &foo 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 = &foo; // a pointer auto* p = &foo; // 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