December 15, 2015
On Tuesday, 15 December 2015 at 09:57:00 UTC, ZombineDev wrote:
> On Monday, 14 December 2015 at 19:56:29 UTC, dnewbie wrote:
>> On Monday, 14 December 2015 at 19:04:46 UTC, bachmeier wrote:
>>> It's unanimous, at least among the three of us posting in this Reddit thread:
>>> ...
>>
>> Take for example C# Docs: https://msdn.microsoft.com/en-us/library/system.collections.arraylist.addrange.aspx
>>
>> Syntax C#:
>>
>> public virtual void AddRange(
>> 	ICollection c
>> )
>>
>> Parameters:
>>     c
>>     Type: System.Collections.ICollection
>>     The ICollection whose elements should be added to the end of the ArrayList. The collection itself cannot be null, but it can contain elements that are null.
>>
>> Clean, simple and instructive!
>>
>
> You are really comparing apples to oranges...

If you look here: http://forum.dlang.org/post/xiduyyulihesjgjxmgnd@forum.dlang.org

I said: "but the main focus here was about the simplicity of the layout used in the C# doc. You can see others examples there easily including templates and generics interface."

So I was talking about one example vs another, in this case isSameLength, which I suggested something like:

Syntax:
    bool isSameLength(Range1, Range2)(Range1 r1, Range2 r2)
Parameters:
    Type r1, r2 : Input range.
    Both r1, r2 : needs to be finite.

Instead of:

bool isSameLength(Range1, Range2)(Range1 r1, Range2 r2) if (isInputRange!Range1 && isInputRange!Range2 && !isInfinite!Range1 && !isInfinite!Range2);

But you know I'm newbie...

Ron.
December 15, 2015
On Monday, 14 December 2015 at 19:04:46 UTC, bachmeier wrote:
> 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);
>
> Unfortunately, that's less ugly than for a lot of functions. In some circumstances, I can see something like that reminding the author of the function about some details, but it can only confuse anyone else.
>
> There is nothing I can do about this. Who makes these decisions? Can we change it to something useful?

Maybe just try to write up some examples of what it could look like. The full signature could be an expandable section and hidden from newbies.

"
bool isSameLength(Range1, Range2)(Range1 r1, Range2 r2) if (isInputRange!Range1 && isInputRange!Range2 && !isInfinite!Range1 && !isInfinite!Range2);
"

Could be something like this:

"
isSameLength(r1, r2) -> bool
r1,r2 : finite input range
"
with a "+" icon in the margin to see the formal description.

December 15, 2015
On Tuesday, 15 December 2015 at 14:08:34 UTC, dnewbie wrote:
> But you know I'm newbie...

And that makes your input important. Didn't see your response before I wrote mine, but we seem to agree. :)

December 15, 2015
On 15.12.2015 15:03, rumbu wrote:
> There is no indication what happens if the range is undefined in D docs.
> In fact, inconsistent behavior:
> - it will return 0 in case of null arrays;
> - it will throw AccessViolation for null ranges (or probably segfault on
> Linux);

I don't think the behavior is inconsistent. A "null array" is rather different from a null pointer/reference. If anything is inconsistent, I'd say it's the meaning of `null` in the different contexts.

A null pointer may be considered "undefined", but a "null array" is certainly not undefined. A "null array" has a null pointer and a length of zero. The zero length makes it so that the null pointer won't be dereferenced.

Thinking about arrays in terms of null is probably misleading. Instead, I'd suggest to think in terms of the empty array []. It's the exact same value, but it's more obvious what's going on.
December 15, 2015
On Tuesday, 15 December 2015 at 14:03:50 UTC, rumbu wrote:
> This is a *good* documentation:
> - "Count" is a better name than "walkLength"; every other programming language will use concepts similar to count, cnt, length, len.

meh, I like walkLength. I hate it when a innocuous looking little function does a bunch of expensive work unexpectedly, "walkLength" really points out the worst case. Also, it's important to be reminded that is might actually iterate your range, which the "walk" bit really does, so if it's an inputRange then say goodbye to your data.

> - You don't need to understand computer science terms to find out what a function does;

A little nudge to understand some important concepts never hurts. It can sometimes get a bit obscure though, or be too self-referential (there are probably some non-trivial cycles in the required knowledge graph).

> - If you are really interested about more than finding out the number of elements, there is a performance hint in the Remarks section.

Considering that despite the fact my phone can perform billions of calculations per second but it still takes >2s to open up a text-editor app (on a good day), it seems worthwhile to point out performance a little more forcefully than "here's some other information if you feel like it".

> - Links are provided to concepts: even the return type (int) has a link.
>
> [ ... ]
>
> On the contrary, the D documentation, introduces a bunch of non-linked concepts, but it tells me that it's possible to perform O(n) evaluations:
> - isInputRange
> - isInfiniteRange
> - hasLength
> - empty
> - popFront

We should definitely have more links.

> There is no indication what happens if the range is undefined in D docs. In fact, inconsistent behavior:
> - it will return 0 in case of null arrays;
> - it will throw AccessViolation for null ranges (or probably segfault on Linux);

Fair point. I'd love it if phobos range functions treated arrays 100% consistently with custom ranges, but apparently that boat sailed off in multiple directions at once long ago...
December 15, 2015
Just something I want to throw out as a reminder, a part of the ranges chapter of my book is public on the packt website:

https://www.packtpub.com/books/content/ranges

and a longer things from Mike Parker's book is too:

https://www.packtpub.com/books/content/understanding-ranges

a lot of us have talked about ranges, it all ought to be nicely referenced in the docs as much as we can.
December 15, 2015
On Tuesday, 15 December 2015 at 14:03:50 UTC, rumbu wrote:
>
> We are talking about a better documentation, not about the C# vs D performance, we already know the winner. Since C# is an OOP-only language, there is only one way to do reflection - using OOP, (voluntarily ignoring the fact that NGen will reduce this call to a simple memory read in case of arrays).
>
> Your affirmation:
>
>> the docs don't even bother to mention that it is almost always O(n), because non of the Enumerable extention methods preserve the underlying ICollection interace
>
> was false and you don't need to look to the source code to find out, the Remarks section is self-explanatory:
>
> "If the type of source implements ICollection<T>, that implementation is used to obtain the count of elements. Otherwise, this method determines the count."

Sorry, I do not know how to make this clear:

NONE OF THE System.Linq.Enumerable EXTENSION METHODS PRESERVE THE STRUCTURE (THE INTERFACES THEY IMPLEMENT) OF THE SEQUENCE THEY ARE OPERATING ON. DON'T BELIEVE THAT NGEN WILL AUTOMAGICALLY MAKE YOUR CODE FASTER. IT WILL NOT. UNICORNS DO NOT EXISTS. AT LEAST THEY DO NOT IN .NET OR JAVA. DO NOT BLINDLY BELIEVE. TEST!

See for yourself: https://ideone.com/L5FatQ

This what I got on my machine:
00:00:00.0011011 for N = 1 -> 1, List<int>.Select(..).Count()
00:00:00.0000017 for N = 2 -> 2, List<int>.Select(..).Count()
00:00:00.0000009 for N = 4 -> 4, List<int>.Select(..).Count()
00:00:00.0000011 for N = 8 -> 8, List<int>.Select(..).Count()
00:00:00.0000012 for N = 16 -> 16, List<int>.Select(..).Count()
00:00:00.0000026 for N = 32 -> 32, List<int>.Select(..).Count()
00:00:00.0000018 for N = 64 -> 64, List<int>.Select(..).Count()
00:00:00.0000032 for N = 128 -> 128, List<int>.Select(..).Count()
00:00:00.0000059 for N = 256 -> 256, List<int>.Select(..).Count()
00:00:00.0000098 for N = 512 -> 512, List<int>.Select(..).Count()
00:00:00.0000190 for N = 1024 -> 1024, List<int>.Select(..).Count()
00:00:00.0000369 for N = 2048 -> 2048, List<int>.Select(..).Count()
00:00:00.0000750 for N = 4096 -> 4096, List<int>.Select(..).Count()
00:00:00.0002185 for N = 8192 -> 8192, List<int>.Select(..).Count()
00:00:00.0003551 for N = 16384 -> 16384, List<int>.Select(..).Count()
00:00:00.0005826 for N = 32768 -> 32768, List<int>.Select(..).Count()
00:00:00.0015252 for N = 65536 -> 65536, List<int>.Select(..).Count()
00:00:00.0024139 for N = 131072 -> 131072, List<int>.Select(..).Count()
00:00:00.0049246 for N = 262144 -> 262144, List<int>.Select(..).Count()
00:00:00.0096537 for N = 524288 -> 524288, List<int>.Select(..).Count()
00:00:00.0194600 for N = 1048576 -> 1048576, List<int>.Select(..).Count()
00:00:00.0422573 for N = 2097152 -> 2097152, List<int>.Select(..).Count()
00:00:00.0749799 for N = 4194304 -> 4194304, List<int>.Select(..).Count()
00:00:00.1511740 for N = 8388608 -> 8388608, List<int>.Select(..).Count()
00:00:00.3004764 for N = 16777216 -> 16777216, List<int>.Select(..).Count()
00:00:00.6018954 for N = 33554432 -> 33554432, List<int>.Select(..).Count()
00:00:01.2064069 for N = 67108864 -> 67108864, List<int>.Select(..).Count()
00:00:02.6716092 for N = 134217728 -> 134217728, List<int>.Select(..).Count()
00:00:05.1524452 for N = 268435456 -> 268435456, List<int>.Select(..).Count()
00:00:09.6481144 for N = 536870912 -> 536870912, List<int>.Select(..).Count()
00:00:00.0005440 for N = 1 -> 1, Array<int>.Select(..).Count()
00:00:00.0000010 for N = 2 -> 2, Array<int>.Select(..).Count()
00:00:00.0000008 for N = 4 -> 4, Array<int>.Select(..).Count()
00:00:00.0000009 for N = 8 -> 8, Array<int>.Select(..).Count()
00:00:00.0000013 for N = 16 -> 16, Array<int>.Select(..).Count()
00:00:00.0000015 for N = 32 -> 32, Array<int>.Select(..).Count()
00:00:00.0000020 for N = 64 -> 64, Array<int>.Select(..).Count()
00:00:00.0000035 for N = 128 -> 128, Array<int>.Select(..).Count()
00:00:00.0000061 for N = 256 -> 256, Array<int>.Select(..).Count()
00:00:00.0000107 for N = 512 -> 512, Array<int>.Select(..).Count()
00:00:00.0000209 for N = 1024 -> 1024, Array<int>.Select(..).Count()
00:00:00.0000424 for N = 2048 -> 2048, Array<int>.Select(..).Count()
00:00:00.0000822 for N = 4096 -> 4096, Array<int>.Select(..).Count()
00:00:00.0001633 for N = 8192 -> 8192, Array<int>.Select(..).Count()
00:00:00.0003263 for N = 16384 -> 16384, Array<int>.Select(..).Count()
00:00:00.0006503 for N = 32768 -> 32768, Array<int>.Select(..).Count()
00:00:00.0013024 for N = 65536 -> 65536, Array<int>.Select(..).Count()
00:00:00.0026130 for N = 131072 -> 131072, Array<int>.Select(..).Count()
00:00:00.0052041 for N = 262144 -> 262144, Array<int>.Select(..).Count()
00:00:00.0103705 for N = 524288 -> 524288, Array<int>.Select(..).Count()
00:00:00.0207945 for N = 1048576 -> 1048576, Array<int>.Select(..).Count()
00:00:00.0418217 for N = 2097152 -> 2097152, Array<int>.Select(..).Count()
00:00:00.0829522 for N = 4194304 -> 4194304, Array<int>.Select(..).Count()
00:00:00.1658241 for N = 8388608 -> 8388608, Array<int>.Select(..).Count()
00:00:00.3304377 for N = 16777216 -> 16777216, Array<int>.Select(..).Count()
00:00:00.6636190 for N = 33554432 -> 33554432, Array<int>.Select(..).Count()
00:00:01.3255121 for N = 67108864 -> 67108864, Array<int>.Select(..).Count()
00:00:02.6572163 for N = 134217728 -> 134217728, Array<int>.Select(..).Count()
00:00:05.2761961 for N = 268435456 -> 268435456, Array<int>.Select(..).Count()
00:00:10.7154543 for N = 536870912 -> 536870912, Array<int>.Select(..).Count()

> This is a *good* documentation:
> - "Count" is a better name than "walkLength"; every other programming language will use concepts similar to count, cnt, length, len.

"Length" is right there in walkLength. I don't see this as an obstacle for anybody that would want to use this function.
"walk" in walkLength informs you of the performance consequence, which for me is critical information.

> - You don't need to understand computer science terms to find out what a function does;

A major disadvantage, if you ask me :D

BTW, Array.Length uses the same notation:
https://msdn.microsoft.com/en-us/library/system.array.length(v=vs.110).aspx

> - If you are really interested about more than finding out the number of elements, there is a performance hint in the Remarks section.

No the Remarks section is so vague that it is no hint:
"... Otherwise, this method determines the count"

Determines how? I really dislike this the style of documentation written just for the sake documentation.

> - Links are provided to concepts: even the return type (int) has a link.
> - It clearly states what's happening if the range is not defined
> - It clearly states what's happening if the range contains more than int.max elements
>
> On the contrary, the D documentation, introduces a bunch of non-linked concepts, but it tells me that it's possible to perform O(n) evaluations:
> - isInputRange
> - isInfiniteRange
> - hasLength
> - empty
> - popFront

I agree that Phobos needs to do a lot better at introducing concepts such as ranges.

> There is no indication what happens if the range is undefined in D docs. In fact, inconsistent behavior:
> - it will return 0 in case of null arrays;

This is logical and doesn't need to be documented.

> - it will throw AccessViolation for null ranges (or probably segfault on Linux);

Again, this is expected, as it is a result of a programmer error. Do you document that calling methods on a null object will segfault for every single method? null.Length is not documented for System.Array and doesn't need to be.


> There is no indication what happens if the range contains more than size_t.max elements:
> - integer overflow;

Practically impossible on 64-bit and unlikely that someone will use walkLength with files on 32-bit. It's called *walk*Length for a reason.

This is more of an issue in .NET because the length / count is fixed as System.Int32, regardless of the actual amount of addressable memory.

> Like someone said: D has genius programmers, but worst marketers.

Contrary to LINQ which had super good marketing and very bad implementation. I read the blog of one of the guys that worked on Parallel LINQ that there were some instances were you could good get almost 4X improvement with the Parallel version on a 4 CPU system, and then get 100X with a single threaded C implementation :D
December 15, 2015
On 12/15/2015 09:40 AM, John Colvin wrote:
> On Tuesday, 15 December 2015 at 14:03:50 UTC, rumbu wrote:
>> This is a *good* documentation:
>> - "Count" is a better name than "walkLength"; every other programming
>> language will use concepts similar to count, cnt, length, len.
>
> meh, I like walkLength.

Me too, but don't forget that nowadays "count" with no predicate defaults to walkLength's semantics. -- Andrei

December 15, 2015
On Monday, 14 December 2015 at 19:04:46 UTC, 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);
>
> Unfortunately, that's less ugly than for a lot of functions. In some circumstances, I can see something like that reminding the author of the function about some details, but it can only confuse anyone else.
>
> There is nothing I can do about this. Who makes these decisions? Can we change it to something useful?
>
> Also, I think the documentation for functions involving ranges needs more "for dummies" examples. Too many of those functions leave the reader not having a clue what to do after calling the function. I know how that can be fixed.

I think that most of the problem is simply down to how the documentation looks. It's too dense.

I think some whitespace and some color-coding will go a long way to making the function signatures better.

bool isSameLength
   (Range1, Range2)                           // a grey color
   (Range1 r1, Range2 r2)                     // a blue
   if (isInputRange!Range1 && isInputRange!Range2 &&
   !isInfinite!Range1 && !isInfinite!Range2);  // same grey color as template args, to point out they're working on the template

I think that would make all documentation much easier to glance over, and yet easy to read if you need to.

On the examples - more examples can only be better!
December 15, 2015
On Tue, 15 Dec 2015 09:09:43 +0000, Adrian Matoga wrote:

> Fantastic example of why this strategy should be just banned.

Just as well I wasn't recommending it as a long-term solution. I was more offering it as additional evidence that template definitions can get a bit large and people have known that this is a problem for documentation for eight years now.

"Banned" is a strong term. Perhaps you simply meant it should not be recommended and should not be used in Phobos?