December 14, 2015
On Mon, 14 Dec 2015 19:38:26 +0000, Jack Stouffer wrote:
> If you're trying to use Phobos without knowing what template constraints and ranges are, you're going to have a bad time.

I completely agree about ranges.

On that note, it would be nice if std.range actually told you what interface a range has to honor. It points you to Andrei's article, but that uses C++.

It would also be awesome if std.algorithm reminded you of that interface right there in the package documentation, seeing as it makes such extensive use of ranges. It does better than std.range by linking to Ali's book, but Ali introduces things to you rather slowly.

Yes, std.range.primitives defines isInputRange and friends. However, it's not defining ranges in general, just a collection of specific types of ranges. It's not telling you that foreach works with ranges. And it's using odd terminology -- the module is called "primitives" when it really defines the interface that a range must adhere to (and provides a random smattering of convenience methods that don't seem to belong), and it calls the methods and properties that a range must define "primitives" for maximum confusion.

So for ranges.

Template constraints, on the other hand? Not so much. You can ignore them and hope that your stuff works and get confused when it doesn't. Or you can glance at a method's signature and see that it's two or three lines long and get scared. And when you decide, a few weeks or months into using D, to use templates, you'll quickly discover it's far less work not to use constraints and you get much better error messages.

> I'm not sure what else to say here. You can't expect to use the language to it's fullest without understanding these features.

Right, but std.algorithm is full of stuff that novices need to use early on. They're not trying to use the language to its fullest; they're just trying to use the basic parts of the standard library.

There's also the problem that the template constraint is made so prominent when the examples are far more useful for most people.
December 14, 2015
On Mon, 14 Dec 2015 20:53:53 +0000, Andrei Alexandrescu wrote:

> One thing we definitely need to do is make the template constraints rendered better in documentation, and also allow user content in them. We've discussed this several times but no clear path emerged so far. Maybe a strong champion would come forward?
> 
> I'm thinking along the lines of:
> 
> * Change ddoc to output the constraint separately under a DDOC_CONSTRAINT macro.
> 
> * Allow ddoc comments inside macros:
> 
> bool isSameLength(Range1, Range2)(Range1 r1, Range2 r2)
> if (isInputRange!Range1 && isInputRange!Range2 && !isInfinite!Range1 &&
> !isInfinite!Range2 /**
> `Range1` and `Range2` must be both non-infinite input ranges.
> */
> );
> 
> then format that comment as a DDOC_CONSTRAINT_USERTEXT or something.
> 
> These would be good steps to take.
> 
> 
> Andrei

From your lips to God's ears.
December 14, 2015
On Monday, 14 December 2015 at 20:52:15 UTC, Jack Stouffer wrote:

> You don't: array1.length == array2.length. isSameLength is designed for comparing input ranges but optimizes down to length checks if either range has a defined length. If you are dealing with strings or arrays you don't need this function at all.
>

All of the examples that *you wrote* for isSameLength are for arrays and strings.

>> There's a difference between using all the features of a language and the documentation of the standard library. The documentation should be accessible to new users of the language.
>
> I disagree.

That doesn't make much sense - are those new to the language supposed to learn Phobos by reading the source code?

I don't want to debate this. If it's the official position that Phobos documentation is written for experienced users of the language, then so be it. I'll have to tell others to use a practical language.
December 14, 2015
On Mon, 14 Dec 2015 20:52:15 +0000, Jack Stouffer wrote:
> C++ is doomed if you have to understand templates and iterators to use the STL

C++ existed long before the STL. But a putative C++ clone that had sorely lacking documentation about iterators and put them everywhere in its standard library would struggle more than it would otherwise. It would be worse if what documentation existed were cluttered with dense syntax that novices agree is confusing. And doom would be assured if the standard library authors were dismissive of the needs of programmers who are not as familiar with the language as the core development team.

> Also, most of Phobos doesn't use ranges.

Quick survey by module:

std.algorithm: 6/6 modules.
std.array: yes.
std.ascii: no.
std.base64: yes.
std.bigint: no.
std.bitmanip: yes.
std.compiler: no.
std.complex: no.
std.concurrency: no.
std.container: 5/6 modules.
std.conv: yes.
std.csv: yes.
std.datetime: yes.
std.demangle: no.

At this point I got bored, but suffice it to say, a *lot* of Phobos uses ranges. And a lot more will. Ranges are central to modern D and to making composable functions.

Plus a lot of the stuff that does use ranges is pretty important and widely used and useful. It's the sort of thing that new programmers are pointed to and told "You should be using this."

Finally, requests for better documentation or to bear in mind people who have not been living and breathing D for months should not be controversial.
December 14, 2015
On Monday, 14 December 2015 at 22:31:33 UTC, bachmeier wrote:
> On Monday, 14 December 2015 at 20:52:15 UTC, Jack Stouffer wrote:
>> You don't: array1.length == array2.length. isSameLength is designed for comparing input ranges but optimizes down to length checks if either range has a defined length. If you are dealing with strings or arrays you don't need this function at all.
>>
>
> All of the examples that *you wrote* for isSameLength are for arrays and strings.

Yes, they are, because strings and arrays are the most simple input ranges. But the fact that you didn't know that arrays have a length parameter tells me you tried using the language raw and you got confused. I don't know why it's surprising to you that trying to use a systems language without reading any tutorials is going to end up with you hitting walls when the inevitable complexity rears its head.

>> I disagree.
>
> That doesn't make much sense - are those new to the language supposed to learn Phobos by reading the source code?

No you're supposed to learn it by reading the official tutorial that is linked on every single page in dlang.org in the sidebar.

> I don't want to debate this.

Then why create the thread in the first place? Did you really expect everyone to just accept your idea at face value and there wouldn't be no discussion at all?

> If it's the official position that Phobos documentation is written for experienced users of the language, then so be it. I'll have to tell others to use a practical language.

It's not the official position. I'm just a contributor and have no power what so ever.
December 15, 2015
On 14.12.2015 23:31, bachmeier wrote:
> I don't want to debate this. If it's the official position that Phobos
> documentation is written for experienced users of the language, then so
> be it. I'll have to tell others to use a practical language.

Relax, Jack Stouffer is not the spokesman for D or phobos. He doesn't express official positions. (Not implying that you tried to give the impression, Jack.)

As far as I see, people generally agree with you that the current way of displaying the signatures is too cryptic. What to do exactly about it is open for debate, of course. And then someone actually has to do the work, of course.
December 14, 2015
On 12/14/15 2:04 PM, bachmeier wrote:
> It's unanimous, at least among the three of us posting in this Reddit
> thread:
>
> https://www.reddit.com/r/programming/comments/3wqt3p/programming_in_d_ebook_is_at_major_retailers_and/cxyqxuz
>
>
> Something has to be done with the documentation for Phobos functions
> that involve ranges and templates. The example I gave there is
>
> bool isSameLength(Range1, Range2)(Range1 r1, Range2 r2) if
> (isInputRange!Range1 && isInputRange!Range2 && !isInfinite!Range1 &&
> !isInfinite!Range2);

This is by far, one of the least problematic examples.

A while back, I wanted to use std.algorithm.find to search for something. I wasn't sure what order to call the parameters with, so I looked at the documentation. After about 10-15 minutes of trying to deduce whatever template overload was going to match, if any at all, I just decided to write the call and see if it worked (it did).

The documentation for IFTI functions like this needs to be simplified greatly. Essentially, I need to know what types of things I can use, and what order I need to pass them. But I don't need all the details of which overload will be called depending on some obscure template constraint.

I don't know if there's an automated way to do this. IFTI functions are so powerfully useful, that it's almost impossible to have this done automatically.

In the example of find, a possible way to do this is to wrap the whole set of overloads into one simplified call:

Range1 find(Range1 haystack, N needle)

And then explain what Range1 and N can be. Then allow one to expand the docs to see all the true signatures if I want to.

In std.conv, there is a global template to that forwards to all the different toImpl, with the majority of docs on the to template. That is kind of the model I was thinking of, but allow ddoc to hide all the implementation details and show on demand.

-Steve
December 15, 2015
On Mon, 14 Dec 2015 18:45:28 -0500, Steven Schveighoffer wrote:

> On 12/14/15 2:04 PM, bachmeier wrote:
>> It's unanimous, at least among the three of us posting in this Reddit thread:
>>
>> https://www.reddit.com/r/programming/comments/3wqt3p/
programming_in_d_ebook_is_at_major_retailers_and/cxyqxuz
>>
>>
>> Something has to be done with the documentation for Phobos functions that involve ranges and templates. The example I gave there is
>>
>> bool isSameLength(Range1, Range2)(Range1 r1, Range2 r2) if
>> (isInputRange!Range1 && isInputRange!Range2 && !isInfinite!Range1 &&
>> !isInfinite!Range2);
> 
> This is by far, one of the least problematic examples.
> 
> A while back, I wanted to use std.algorithm.find to search for something. I wasn't sure what order to call the parameters with, so I looked at the documentation. After about 10-15 minutes of trying to deduce whatever template overload was going to match, if any at all, I just decided to write the call and see if it worked (it did).
> 
> The documentation for IFTI functions like this needs to be simplified greatly. Essentially, I need to know what types of things I can use, and what order I need to pass them. But I don't need all the details of which overload will be called depending on some obscure template constraint.
> 
> I don't know if there's an automated way to do this. IFTI functions are so powerfully useful, that it's almost impossible to have this done automatically.
> 
> In the example of find, a possible way to do this is to wrap the whole set of overloads into one simplified call:
> 
> Range1 find(Range1 haystack, N needle)
> 
> And then explain what Range1 and N can be. Then allow one to expand the docs to see all the true signatures if I want to.

This reminds me of the Tango strategy for this kind of thing.

tango.core.Array was arranged like this:

version(TangoDoc) {
  /** Documentation comment. */
  bool isSameLangth(Range1, Range2)(Range1 r1, Range2 r2) {
    return true;
  }
} else {
  bool isSameLength(Range1, Range2)(Range1 r1, Range2 r2)
    if (
      isInputRange!Range1 &&
      isInputRange!Range2 &&
      !isInfinite!Range1 &&
      !isInfinite!Range2) {
    // actual implementation
  }
}

Of course, this was before template constraints -- which in turn means that the templates they were doing this for were much more succinct than what you find in std.algorithm, and they still felt it important to simplify for the sake of documentation.

It's not ideal because it relies on prose documentation, which might be far from the implementation, to stay up to date. On the other hand, it's something that can be done today, without any changes to ddoc.

An outer template that forwards to specialized templates would be cleaner.
December 15, 2015
On Tuesday, 15 December 2015 at 01:10:01 UTC, Chris Wright wrote:
> On Mon, 14 Dec 2015 18:45:28 -0500, Steven Schveighoffer wrote:
>
>> On 12/14/15 2:04 PM, bachmeier wrote:
>>> It's unanimous, at least among the three of us posting in this Reddit thread:
>>>
>>> https://www.reddit.com/r/programming/comments/3wqt3p/
> programming_in_d_ebook_is_at_major_retailers_and/cxyqxuz
>>>
>>>
>>> Something has to be done with the documentation for Phobos functions that involve ranges and templates. The example I gave there is
>>>
>>> bool isSameLength(Range1, Range2)(Range1 r1, Range2 r2) if
>>> (isInputRange!Range1 && isInputRange!Range2 && !isInfinite!Range1 &&
>>> !isInfinite!Range2);
>> 
>> This is by far, one of the least problematic examples.
>> 
>> A while back, I wanted to use std.algorithm.find to search for something. I wasn't sure what order to call the parameters with, so I looked at the documentation. After about 10-15 minutes of trying to deduce whatever template overload was going to match, if any at all, I just decided to write the call and see if it worked (it did).
>> 
>> The documentation for IFTI functions like this needs to be simplified greatly. Essentially, I need to know what types of things I can use, and what order I need to pass them. But I don't need all the details of which overload will be called depending on some obscure template constraint.
>> 
>> I don't know if there's an automated way to do this. IFTI functions are so powerfully useful, that it's almost impossible to have this done automatically.
>> 
>> In the example of find, a possible way to do this is to wrap the whole set of overloads into one simplified call:
>> 
>> Range1 find(Range1 haystack, N needle)
>> 
>> And then explain what Range1 and N can be. Then allow one to expand the docs to see all the true signatures if I want to.
>
> This reminds me of the Tango strategy for this kind of thing.
>
> tango.core.Array was arranged like this:
>
> version(TangoDoc) {
>   /** Documentation comment. */
>   bool isSameLangth(Range1, Range2)(Range1 r1, Range2 r2) {
>     return true;
>   }
> } else {
>   bool isSameLength(Range1, Range2)(Range1 r1, Range2 r2)
>     if (
>       isInputRange!Range1 &&
>       isInputRange!Range2 &&
>       !isInfinite!Range1 &&
>       !isInfinite!Range2) {
>     // actual implementation
>   }
> }
>
> Of course, this was before template constraints -- which in turn means that the templates they were doing this for were much more succinct than what you find in std.algorithm, and they still felt it important to simplify for the sake of documentation.
>
> It's not ideal because it relies on prose documentation, which might be far from the implementation, to stay up to date. On the other hand, it's something that can be done today, without any changes to ddoc.
>
> An outer template that forwards to specialized templates would be cleaner.

Hiding conditionals does not seem like to be solution. Here is my idea:

Show the function:
bool isSameLength(Range1, Range2)(Range1 r1, Range2 r2)

Then show the conditions separately:
if(
  isInputRange!Range1 &&
  isInputRange!Range2 &&
  !isInfinite!Range1 &&
  !isInfinite!Range2
)

I am not sure whether ddoc supports/can support this, but being able to do this, and
even adding separate comment on function and its conditionals separately could be quite useful. I know just talking doesn't make anything working, but idea is needed first.

By the way, I wish "and", "or", "xor" were in the language as in Pascal. Things could be more human friendly maybe.
December 15, 2015
On Tuesday, 15 December 2015 at 01:50:07 UTC, tcak wrote:
> On Tuesday, 15 December 2015 at 01:10:01 UTC, Chris Wright wrote:
>> [...]
>
> Hiding conditionals does not seem like to be solution. Here is my idea:
>
> Show the function:
> bool isSameLength(Range1, Range2)(Range1 r1, Range2 r2)
>
> Then show the conditions separately:
> if(
>   isInputRange!Range1 &&
>   isInputRange!Range2 &&
>   !isInfinite!Range1 &&
>   !isInfinite!Range2
> )
>
> I am not sure whether ddoc supports/can support this, but being able to do this, and
> even adding separate comment on function and its conditionals separately could be quite useful. I know just talking doesn't make anything working, but idea is needed first.
>
> By the way, I wish "and", "or", "xor" were in the language as in Pascal. Things could be more human friendly maybe.

I think a first step can be taken that doesn't even need changing DDOC's output: just add syntax highlighting to the line in order to emphasize "bool isSameLength(Range1, Range2)(Range1 r1, Range2 r2)" and make it look distinct from the template constraint part. It won't solve every problems but to a beginners eye it reads like "this is what the important stuff is".