Re: auto: useful, annoying or bad practice?

2018-05-21 Thread Chris via Digitalmars-d

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?

2018-05-20 Thread Charles Hixson via Digitalmars-d
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?

2018-05-20 Thread Neia Neutuladh via Digitalmars-d

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?

2018-05-20 Thread Jonathan M Davis via Digitalmars-d
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?

2018-05-20 Thread I love Ice Cream via Digitalmars-d

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?

2018-05-20 Thread I love Ice Cream via Digitalmars-d

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?

2018-05-19 Thread Neia Neutuladh via Digitalmars-d

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?

2018-05-19 Thread I love Ice Cream via Digitalmars-d
'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?

2018-05-19 Thread Chris via Digitalmars-d

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?

2018-05-18 Thread Neia Neutuladh via Digitalmars-d

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?

2018-05-18 Thread Chris via Digitalmars-d

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?

2018-05-17 Thread Kagamin via Digitalmars-d

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?

2018-05-16 Thread Neia Neutuladh via Digitalmars-d

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?

2018-05-16 Thread KingJoffrey via Digitalmars-d

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?

2018-05-12 Thread Mark via Digitalmars-d

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?

2018-05-11 Thread H. S. Teoh via Digitalmars-d
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?

2018-05-11 Thread Chris M. via Digitalmars-d

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?

2018-05-11 Thread H. S. Teoh via Digitalmars-d
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?

2018-05-11 Thread Mark via Digitalmars-d

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?

2018-05-10 Thread KingJoffrey via Digitalmars-d

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=rep1=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?

2018-05-09 Thread Jonathan M Davis via Digitalmars-d
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?

2018-05-09 Thread Jesse Phillips via Digitalmars-d

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?

2018-05-09 Thread bauss via Digitalmars-d

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?

2018-05-09 Thread Jonathan M Davis via Digitalmars-d
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 do. In that snippet, so long as I can call
doSomething on foo (be it as a member function or via UFCS) and so long as
someOtherFunc accepts whatever type foo is, I don't necessarily care if the
type of foo 

Re: auto: useful, annoying or bad practice?

2018-05-06 Thread IntegratedDimensions via Digitalmars-d

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?

2018-05-05 Thread Atila Neves via Digitalmars-d

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?

2018-05-05 Thread Nick Sabalausky (Abscissa) via Digitalmars-d

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?

2018-05-04 Thread H. S. Teoh via Digitalmars-d
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?

2018-05-04 Thread Nick Sabalausky (Abscissa) via Digitalmars-d

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?

2018-05-04 Thread Laeeth Isharc via Digitalmars-d
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?

2018-05-03 Thread Nick Sabalausky (Abscissa) via Digitalmars-d

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?

2018-05-03 Thread Nerve via Digitalmars-d

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?

2018-05-02 Thread Jesse Phillips via Digitalmars-d

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?

2018-05-02 Thread Neia Neutuladh via Digitalmars-d

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?

2018-05-02 Thread Mark via Digitalmars-d

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?

2018-05-02 Thread H. S. Teoh via Digitalmars-d
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?

2018-05-02 Thread Dgame via Digitalmars-d

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?

2018-05-01 Thread Nick Sabalausky (Abscissa) via Digitalmars-d

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?

2018-05-01 Thread Neia Neutuladh via Digitalmars-d

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?

2018-05-01 Thread Nick Sabalausky via Digitalmars-d
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())".


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?

2018-05-01 Thread Nick Sabalausky via Digitalmars-d
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())".


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?

2018-05-01 Thread Craig Dillabaugh via Digitalmars-d

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?

2018-05-01 Thread Chris via Digitalmars-d

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?

2018-04-30 Thread H. S. Teoh via Digitalmars-d
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?

2018-04-30 Thread Giles Bathgate via Digitalmars-d

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?

2018-04-30 Thread H. S. Teoh via Digitalmars-d
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?

2018-04-30 Thread JN via Digitalmars-d

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?

2018-04-30 Thread Gerald via Digitalmars-d
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?