Re: dub auto-tester

2018-09-20 Thread Seb via Digitalmars-d
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

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

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

2018-09-19 Thread Joakim via Digitalmars-d
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?

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&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?

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 

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-01 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(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?

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(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?

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?


Re: understanding Auto-Test

2018-03-21 Thread Seb via Digitalmars-d

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

2018-03-21 Thread John Belmonte via Digitalmars-d

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

2018-03-21 Thread Seb via Digitalmars-d

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

2018-03-21 Thread Seb via Digitalmars-d

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

2018-03-21 Thread Mike Franklin via Digitalmars-d

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

2018-03-21 Thread Mike Franklin via Digitalmars-d

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

2018-03-21 Thread John Belmonte via Digitalmars-d

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

2018-03-21 Thread Mike Franklin via Digitalmars-d

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

2018-03-21 Thread John Belmonte via Digitalmars-d
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

2018-03-05 Thread Jonathan Marler via Digitalmars-d
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

2018-03-05 Thread Steven Schveighoffer via Digitalmars-d

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

2018-03-02 Thread Jonathan Marler via Digitalmars-d

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

2018-03-02 Thread Timon Gehr via Digitalmars-d

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

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

2018-03-02 Thread Jonathan Marler via Digitalmars-d
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

2017-12-28 Thread Mark via Digitalmars-d

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

2017-12-27 Thread H. S. Teoh via Digitalmars-d
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

2017-12-27 Thread Neia Neutuladh via Digitalmars-d

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

2017-12-27 Thread H. S. Teoh via Digitalmars-d
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

2017-12-26 Thread Piotr Klos via Digitalmars-d

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

2017-12-26 Thread Mark via Digitalmars-d

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

2017-12-25 Thread Neia Neutuladh via Digitalmars-d

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

2017-12-25 Thread H. S. Teoh via Digitalmars-d
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

2017-12-25 Thread Piotr Klos via Digitalmars-d

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

2017-12-24 Thread rikki cattermole via Digitalmars-d

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

2017-12-24 Thread Neia Neutuladh via Digitalmars-d
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?

2017-10-19 Thread Dave Jones via Digitalmars-d
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?

2017-10-18 Thread Jonathan M Davis via Digitalmars-d
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?

2017-10-18 Thread Dave Jones via Digitalmars-d
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?

2017-10-18 Thread Moritz Maxeiner via Digitalmars-d

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?

2017-10-18 Thread Dave Jones via Digitalmars-d

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?

2017-10-18 Thread Dave Jones via Digitalmars-d

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

2017-07-25 Thread Zaheer Ahmed via Digitalmars-d
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*

2017-07-06 Thread Patrick Schluter via Digitalmars-d

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*

2017-07-06 Thread Patrick Schluter via Digitalmars-d

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*

2017-07-06 Thread Meta via Digitalmars-d

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*

2017-07-06 Thread jmh530 via Digitalmars-d

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*

2017-07-06 Thread Meta via Digitalmars-d

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*

2017-07-06 Thread bauss via Digitalmars-d

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*

2017-07-06 Thread H. S. Teoh via Digitalmars-d
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*

2017-07-06 Thread bauss via Digitalmars-d

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*

2017-07-06 Thread H. S. Teoh via Digitalmars-d
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*

2017-07-06 Thread Meta via Digitalmars-d

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*

2017-07-06 Thread H. S. Teoh via Digitalmars-d
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*

2017-07-06 Thread Meta via Digitalmars-d

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*

2017-07-06 Thread Ali Çehreli via Digitalmars-d

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*

2017-07-06 Thread H. S. Teoh via Digitalmars-d
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*

2017-07-06 Thread FoxyBrown via Digitalmars-d

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*

2017-07-06 Thread H. S. Teoh via Digitalmars-d
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


  1   2   3   4   5   6   7   8   9   10   >