digitalmars.D - Human unreadable documentation - the ugly seam between simple D and
- Idan Arye (145/145) Mar 26 2015 There is a discussion about D vs Go going on in several
- Alex Parrill (5/6) Mar 26 2015 So tl;dr; make the template constraints in ddoc less prominent?
- Steven Schveighoffer (4/10) Mar 26 2015 Yes, it's so unprominent, I can't find it :)
- rumbu (18/24) Mar 26 2015 This will not solve the readability problem:
- Israel (5/18) Mar 26 2015 Wouldnt that just be "Further documentation" for advanced
- H. S. Teoh via Digitalmars-d (12/34) Mar 26 2015 There has already been a recent push to add hyperlinks in Phobos docs
- Panke (3/20) Mar 27 2015 Never heard that complain about python's protocols which have no
- rumbu (38/62) Mar 27 2015 I've never used Python, so take this as a live experiment:
- Tobias Pankrath (21/35) Mar 27 2015 Yes the output is awful, but that does not imply some kind of
- Tobias Pankrath (2/4) Mar 27 2015 Why would I need a locale for startsWith? Please file a bug, if
- rumbu (12/16) Mar 27 2015 Because in German, "Köln" can start with "Kö", but also with
- Tobias Pankrath (13/25) Mar 27 2015 You may have a point that schwartzSort has a bad name (I
- w0rp (4/10) Mar 27 2015 https://w0rp.com/project/dstruct/dstruct/weak_reference/
- H. S. Teoh via Digitalmars-d (8/27) Mar 26 2015 This is not a new idea:
- Dominikus Dittes Scherkl (7/21) Mar 27 2015 I think the documentation should simply contain the unittests -
- CraigDillabaugh (17/31) Mar 27 2015 Unittests are helpful, but I think examples aimed at demonstrating
- CraigDillabaugh (3/13) Mar 27 2015 for functions taking ranges or other non-trivial inputs.
- Xavier Bigand (7/36) Mar 27 2015 Just a little point :
- CraigDillabaugh (9/19) Mar 27 2015 That is a good point. Ideally when building a library all the
- David Nadlinger (6/13) Mar 27 2015 D has documented unittests (they appear in the docs as if part of
- CraigDillabaugh (2/17) Mar 27 2015 Does that force the examples to be unittests though?
- Tobias Pankrath (3/9) Mar 28 2015 I added some just recently, because it wasn't possible to add
- Shammah Chancellor (5/166) Mar 27 2015 This is very good. I consider myself well-versed in D, and able to
There is a discussion about D vs Go going on in several threads(yey for multithreading!), and one thread is about an article by Gary Willoughby that claims that Go is not suitable for sophisticated programmers(http://forum.dlang.org/thread/mev7ll$mqr$1 digitalmars.com). What's interesting about this one is the reddit comments, which turned into an argument between simple languages that average programmers can use and complex languages that only the top 1% of intelligent programmers can use, but they can extract more out of them. But the thing is - the world of the top programmers is not really separate from that of average programmers. Professional development teams can have a few top programmers and many average one, all be working on the same project. Open source projects can have top programmers working on the core while allowing average programmers to contribute some simple features. Top programmers can write libraries that can be used by average programmers. To allow these things, top programmers and average programmers should be able to work on the same language. Of course, any language that average programmers can master should be easy for a top programmer to master - but the thing is, we also want the top programmer to be able to bring more out of the language, without limiting them by it's over-simplicity. This will also benefit the average programmers, since they also improve the quality of the libraries and modules they are using. This idea is nothing new, and was mentioned in the main(=biggest) current D vs Go thread(http://forum.dlang.org/thread/mdtago$em9$1 digitalmars.com?page=3#post-jeuhtlocousxtezoaqqh 40forum.dlang.org). What I want to talk about here is the seams. The hurdles that in practice make this duality harder. Let's compare it to another duality that D(and many other languages, mainly modern systems languages) promotes - the duality between high-level and low-level. Between write-code-fast and write-fast-code. The transition between high-level and low-level code in D consists by a change of the things uses - which language constructs, which idioms, which functions. But there aren't any visible seams. You don't need to use FFI or to dynamically load a library file written in another language or anything like that - you simply write the high-level parts like you would write high-level code and the low-level parts like you would write low-level code, and they just work together. The duality between high-level D and low-level D is seamless. The duality between simple D and complex D - not so much. The seams here exist mainly in understanding how to use complex code from simple code. Let's take std.algorithm(.*) for example. The algorithms' implementations there are complex and use advanced D features, but using them is very simple. Provided, of course, that you know how to use them(and no - not everything that you know becomes simple. I know how to solve regular differential equations, but it's still very complex to do so). The problem, as Andrei Alexandrescu pointed out(http://forum.dlang.org/thread/mdtago$em9$1 digitalmars.com?page=6#post-mduv1i:242169:241 40digitalmars.com), is learning how to use them. Ideally you'd want to be able to look at a function's signature and learn from that how to use it. It's name and return type should tell you what it does and it's argument names and types should tell you what to send to it. The documentation only there for a more through description and to warn you about pitfalls and edge cases. But when it comes to heavily templated functions - understanding the signature is HARD. It's hard enough for the top programmers that can handle the complex D features - it's much harder for the average programmers that could have easily used these functions if they could just understand the documentation. Compare it, for example, to Jave. Even if a library doesn't contain a single documentation comment, the auto-generated javadoc that contains just the class tree and method signatures is usually enough to get an idea of what's going where. In D, unless the author has provided some actual examples, you are going to have a hard time trying to sort out these complex templated signatures... That's quite an hurdle to go though when wanting to use complex code from simple code(or even from other complex code). That's the ugly seam I'm talking about. Now, if you are working on a big project(be it commercial or open-source), you can find lot's of examples how to use these complex functions, and that's probably how you'd tackle the problem. When you are using some library you usually don't have that luxury - but these libraries usually have the generated ddoc at their website. Of course - that generated ddoc is full with complex templated signatures, so that's not very helpful... So, what can be done? Maybe the ddoc generator, instead of writing the whole signature as-is, can emit a more human-readable version of it? Let's look at the example Andrei mentioned - startsWith. Let's take a look at the first overloaded signature: uint startsWith(alias pred = "a == b", Range, Needles...)(Range doesThisStart, Needles withOneOfThese) if (isInputRange!Range && Needles.length > 1 && is(typeof(.startsWith!pred(doesThisStart, withOneOfThese[0])) : bool) && is(typeof(.startsWith!pred(doesThisStart, withOneOfThese[1..$])) : uint)); Let's break it down and see what the user needs in order to use the function: `uint` - the return type. Needed. `startsWith` - the function name. Needed. `(alias pred = "a == b",` - a template argument that the user might want to supply - Needed. `Range, Needles...)` - template arguments that should usually be inferable. The function won't work without them, but since the user doesn't actually supply them - I'll mark them as not needed. `(Range doesThisStart, Needles withOneOfThese)` - the function's arguments. Needed. The rest are constraints that check the template arguments. They aren't needed when you try to use the function - though they might be helpful at figuring out why the compiler yells at you when you use it wrong. So, if we take only the needed parts, we get this signature: uint startsWith(alias pred = "a == b")(Range doesThisStart, Needles withOneOfThese); Well, doesn't this look much easier to grasp? Of course, it omits some very critical information. It doesn't tell you what are `Range` and `Needles` - you can look for these types in the docs and find nothing. It also doesn't tell you that `Needles` is variadic. Well - what's stopping us from adding this information *below* the signature? What if ddoc would generate something like this: uint startsWith(alias pred = "a == b")(Range doesThisStart, Needles... withOneOfThese); where: Range is an inferred template argument Needles is a variadic inferred template argument isInputRange!Range Needles.length > 1 is(typeof(.startsWith!pred(doesThisStart, withOneOfThese[0])) : bool) is(typeof(.startsWith!pred(doesThisStart, withOneOfThese[1..$])) : uint) We've broken the signature into the parts required to use the function and the parts required to FULLY understand the previous parts. The motivation is that the second group of parts is also important, so it needs to be there, but it creates a lot of unneeded noise so it shouldn't be a direct part of the signature(at least not in the doc). It's similar to the docs of other types used in the signature - it's important to have these docs somewhere accessible, but you don't want to add them in the middle of the signature because it'll make it unreadable. This idea, of course, is not a finally cooked proposal yet. We need a way to tell ddoc which template arguments are supposed to be inferred(can this always be done automatically?) and the last two entries in my example are not super-trivial to grok(I can rewrite them by-hand to make them super-simple - but can ddoc do it automatically? and how?). The point of this thread is to start a discussion about making ddoc generate documentations that are more... well... human readable.
Mar 26 2015
On Thursday, 26 March 2015 at 19:32:53 UTC, Idan Arye wrote:...snip...So tl;dr; make the template constraints in ddoc less prominent? The "new library reference preview" under Resources seems to already have this (example: http://dlang.org/library/std/algorithm/searching/starts_with.html)
Mar 26 2015
On 3/26/15 3:45 PM, Alex Parrill wrote:On Thursday, 26 March 2015 at 19:32:53 UTC, Idan Arye wrote:Yes, it's so unprominent, I can't find it :) I don't think this was intentional... -Steve...snip...So tl;dr; make the template constraints in ddoc less prominent? The "new library reference preview" under Resources seems to already have this (example: http://dlang.org/library/std/algorithm/searching/starts_with.html)
Mar 26 2015
On Thursday, 26 March 2015 at 19:45:19 UTC, Alex Parrill wrote:On Thursday, 26 March 2015 at 19:32:53 UTC, Idan Arye wrote:This will not solve the readability problem: - what is a range? - what is a needle? - what is a predicate? Phobos is reinventing the OOP encapsulation without providing the minimal tools. IMHO, something similar to "interface" is mandatory to define constraints for "range" and the relationship between "needle" and "range". In another topic, someone proposed the keyword "constraint" - or - extend the concept of "interface" to other kind of types than classes and this will allow some compile-time interface implementation. Therefore, when I write: void foo(IInputRange range) { ... }, range can be a class implementing IInputRange or any other type which supports the same calls described by IInputRange. Another approach is to provide enough overloads for most used scenarios, like testing for prefixes in a string with case sensivity or not....snip...So tl;dr; make the template constraints in ddoc less prominent? The "new library reference preview" under Resources seems to already have this (example: http://dlang.org/library/std/algorithm/searching/starts_with.html)
Mar 26 2015
On Thursday, 26 March 2015 at 21:36:56 UTC, rumbu wrote:On Thursday, 26 March 2015 at 19:45:19 UTC, Alex Parrill wrote:Wouldnt that just be "Further documentation" for advanced programming concepts? Only simple easy to understand examples are needed to begin with. It should flow like a tree.On Thursday, 26 March 2015 at 19:32:53 UTC, Idan Arye wrote:This will not solve the readability problem: - what is a range? - what is a needle? - what is a predicate?...snip...So tl;dr; make the template constraints in ddoc less prominent? The "new library reference preview" under Resources seems to already have this (example: http://dlang.org/library/std/algorithm/searching/starts_with.html)
Mar 26 2015
On Thu, Mar 26, 2015 at 11:05:28PM +0000, Israel via Digitalmars-d wrote:On Thursday, 26 March 2015 at 21:36:56 UTC, rumbu wrote:There has already been a recent push to add hyperlinks in Phobos docs whenever "input range", "output range", etc., are mentioned, to the definitions of these terms. Well, currently they point to the isInputRange, isOutputRange, etc., templates in std.range.primitives, which may not be the best introduction to the concept of ranges, but at least it will tell you which methods must be supported by these ranges. Perhaps there should be a glossary page on dlang.org where these terms can link to, instead. T -- The richest man is not he who has the most, but he who needs the least.On Thursday, 26 March 2015 at 19:45:19 UTC, Alex Parrill wrote:Wouldnt that just be "Further documentation" for advanced programming concepts? Only simple easy to understand examples are needed to begin with. It should flow like a tree.On Thursday, 26 March 2015 at 19:32:53 UTC, Idan Arye wrote:This will not solve the readability problem: - what is a range? - what is a needle? - what is a predicate?...snip...So tl;dr; make the template constraints in ddoc less prominent? The "new library reference preview" under Resources seems to already have this (example: http://dlang.org/library/std/algorithm/searching/starts_with.html)
Mar 26 2015
On Thursday, 26 March 2015 at 21:36:56 UTC, rumbu wrote:On Thursday, 26 March 2015 at 19:45:19 UTC, Alex Parrill wrote:Never heard that complain about python's protocols which have no language support whatsoever.On Thursday, 26 March 2015 at 19:32:53 UTC, Idan Arye wrote:This will not solve the readability problem: - what is a range? - what is a needle? - what is a predicate? Phobos is reinventing the OOP encapsulation without providing the minimal tools. IMHO, something similar to "interface" is mandatory to define constraints for "range" and the relationship between "needle" and "range"....snip...So tl;dr; make the template constraints in ddoc less prominent? The "new library reference preview" under Resources seems to already have this (example: http://dlang.org/library/std/algorithm/searching/starts_with.html)
Mar 27 2015
On Friday, 27 March 2015 at 13:07:30 UTC, Panke wrote:On Thursday, 26 March 2015 at 21:36:56 UTC, rumbu wrote:I've never used Python, so take this as a live experiment: I googled for "startswith python": str.startswith(prefix[, start[, end]]) Return True if string starts with the prefix, otherwise return False. prefix can also be a tuple of prefixes to look for. With optional start, test string beginning at that position. With optional end, stop comparing string at that position. In 3 seconds, I understood the basic usage, without ANY knowledge about Python. Even if I don't know Python, the brackets told me that "start" and "end" are optional. str, prefix, start, end - comprehensible simple words. The only thing remaining is the "tuple" thing. But I can use this function without knowing what a "tuple" is. Looked also in the source code to find out that startsWith is locale sensitive, something ignored in phobos. https://hg.python.org/cpython/file/4ebe1ede981e/Objects/stringobject.c#l2903 Now compare with this: uint startsWith(alias pred = "a == b", Range, Needles...)(Range doesThisStart, Needles withOneOfThese) if (isInputRange!Range && Needles.length > 1 && is(typeof(.startsWith!pred(doesThisStart, withOneOfThese[0])) : bool) && is(typeof(.startsWith!pred(doesThisStart, withOneOfThese[1..$])) : uint)); bool startsWith(alias pred = "a == b", R1, R2)(R1 doesThisStart, R2 withThis) if (isInputRange!R1 && isInputRange!R2 && is(typeof(binaryFun!pred(doesThisStart.front, withThis.front)) : bool)); bool startsWith(alias pred = "a == b", R, E)(R doesThisStart, E withThis) if (isInputRange!R && is(typeof(binaryFun!pred(doesThisStart.front, withThis)) : bool)); *Checks whether the given input range starts with (one of) the given needle(s).* I'm not a native English speaker, but a range can start with a needle? Where is the haystack? :) Anyway, in the Python built-in lib I didn't find any levenshtheinDistance, boyermooreFinder or schschchcscshshscscshshscscssscsshcswarzSort.On Thursday, 26 March 2015 at 19:45:19 UTC, Alex Parrill wrote:Never heard that complain about python's protocols which have no language support whatsoever.On Thursday, 26 March 2015 at 19:32:53 UTC, Idan Arye wrote:This will not solve the readability problem: - what is a range? - what is a needle? - what is a predicate? Phobos is reinventing the OOP encapsulation without providing the minimal tools. IMHO, something similar to "interface" is mandatory to define constraints for "range" and the relationship between "needle" and "range"....snip...So tl;dr; make the template constraints in ddoc less prominent? The "new library reference preview" under Resources seems to already have this (example: http://dlang.org/library/std/algorithm/searching/starts_with.html)
Mar 27 2015
[skip] I'm not a native English speaker, but a range can start with a needle? Where is the haystack? :)Yes the output is awful, but that does not imply some kind of concepts is needed to make the documentation easier to understand. And Python's startsWith makes no use of a protocol. See here http://www.rafekettler.com/magicmethods.html for an explanation.Now that we're talking about creating your own sequences in Python, it's time > to talk about protocols. Protocols are somewhat similar to interfaces in other > languages in that they give you a set of methods you must define. However, in > Python protocols are totally informal and require no explicit declarations to > implement. Rather, they're more like guidelines.It's similar to what we have, just with even less help from the language. (We can at least statically check that some arguments is e.g. a range).Anyway, in the Python built-in lib I didn't find any levenshtheinDistancePlease calculate the levenshtein distance of "aaabc" and "ababc" both in python and D. Then come back and tell me it was too hard in D compared to Python., boyermooreFinder or schschchcscshshscscshshscscssscsshcswarzSort.Both are well known and useful algorithms. You might not know them but that's actually no argument not to include them in phobos. Their presence does not make the documentation any harder to understand or harder to find a startsWith function. I don't buy this "There is a function I don't know, it's so hard to understand thing". That's like saying: I only need XML, don't put JSON in the stdlib because I will get confused! How should I anticipate that I don't need std.json when I just want to parse XML? I cannot even google that for me.
Mar 27 2015
Looked also in the source code to find out that startsWith is locale sensitive, something ignored in phobos.Why would I need a locale for startsWith? Please file a bug, if that's actually needed for unicode strings.
Mar 27 2015
On Friday, 27 March 2015 at 14:39:48 UTC, Tobias Pankrath wrote:Because in German, "Köln" can start with "Kö", but also with "Koe" and "K\u0308o" ? Regarding the scscscshghshshshhswarzThing, here we discuss the readability and accessibility of the documentation, not the power of the library. Every other language will use a variation of "sortBy" instead of the scscshwcwscThing. I'm happy that D has in the default lib functions like levenshteinDistance, but this will not attract the average or "just starting to learn" developer. On the contrary, sorting correctly some names is a more common task than calculating the Levenshtein distance, but there is no function for it in phobos.Looked also in the source code to find out that startsWith is locale sensitive, something ignored in phobos.Why would I need a locale for startsWith? Please file a bug, if that's actually needed for unicode strings.
Mar 27 2015
Regarding the scscscshghshshshhswarzThing, here we discuss the readability and accessibility of the documentation, not the power of the library. Every other language will use a variation of "sortBy" instead of the scscshwcwscThing. I'm happy that D has in the default lib functions like levenshteinDistance, but this will not attract the average or "just starting to learn" developer. On the contrary, sorting correctly some names is a more common task than calculating the Levenshtein distance, but there is no function for it in phobos.You may have a point that schwartzSort has a bad name (I disagree), but putting another algorithm does not make the documentation worse per se. Dunno, what problem you have with the levenshteinDistance.On the contrary, sorting correctly some names is a more common task than calculating the Levenshtein distance, but there is no function for it in phobos.What do you mean by correct? http://unicode.org/reports/tr10/? "We even have something obscure like levenshteinDistance but no implementation for the unicode collation algorithm, which all newcomers are looking for!" is a) a questionable comparison between a relative simple algorithm and a monster and b) wrong, because 99% of programmers don't even know about the algorithm itself, thus they aren't looking for it. BTW. python's startwith does the Köln example wrong. Kö and Ko\u0308 dont match.
Mar 27 2015
On Friday, 27 March 2015 at 16:55:34 UTC, Tobias Pankrath wrote:schwartzSort it's a nice name only if you are German. You got me wrong, I have nothing against the function itself, nor against the presence in the stdlib, but I play the role of the devil's advocate and I try to walk in the D's new user shoes who's expecting probably something more readable than 4 stuffed consonants. Personally, I know what a Schwartz transform is and I speak some German :)Regarding the scscscshghshshshhswarzThing, here we discuss the readability and accessibility of the documentation, not the power of the library. Every other language will use a variation of "sortBy" instead of the scscshwcwscThing. I'm happy that D has in the default lib functions like levenshteinDistance, but this will not attract the average or "just starting to learn" developer. On the contrary, sorting correctly some names is a more common task than calculating the Levenshtein distance, but there is no function for it in phobos.You may have a point that schwartzSort has a bad name (I disagree), but putting another algorithm does not make the documentation worse per se. Dunno, what problem you have with the levenshteinDistance.From the link you posted: "Collation is not aligned with character sets or repertoires of characters. Swedish and German share most of the same characters, for example, but have *very different* sorting orders."On the contrary, sorting correctly some names is a more common task than calculating the Levenshtein distance, but there is no function for it in phobos.What do you mean by correct? http://unicode.org/reports/tr10/?"We even have something obscure like levenshteinDistance but no implementation for the unicode collation algorithm, which all newcomers are looking for!" is a) a questionable comparison between a relative simple algorithm and a monster and b) wrong, because 99% of programmers don't even know about the algorithm itself, thus they aren't looking for it.I explained this in another topic regarding portability obsession, it's a monster probably on Linux, on Windows/Mac it's exactly one line of code, already done it: https://github.com/rumbu13/sharp/blob/master/src/internals/locale.d#L518BTW. python's startwith does the Köln example wrong. Kö and Ko\u0308 dont match.Today was my first contact with Python, I cannot comment on this, may be Python is not aware of normalization forms and is not combining o with the diaeresis (u0308).
Mar 27 2015
On Friday, 27 March 2015 at 18:38:32 UTC, rumbu wrote:schwartzSort it's a nice name only if you are German.Hardly. The name's just as meaningless on its own. It may be easier for us Germans to remember the spelling, but even we have to memorize that "tz", as "schwarz" (black) is more common a word.
Mar 28 2015
On Thursday, 26 March 2015 at 19:45:19 UTC, Alex Parrill wrote:On Thursday, 26 March 2015 at 19:32:53 UTC, Idan Arye wrote:https://w0rp.com/project/dstruct/dstruct/weak_reference/ I've got a "Toggle Contraints" button on my site for showing and hiding them dynamically. It kind of works....snip...So tl;dr; make the template constraints in ddoc less prominent? The "new library reference preview" under Resources seems to already have this (example: http://dlang.org/library/std/algorithm/searching/starts_with.html)
Mar 27 2015
On Thu, Mar 26, 2015 at 07:32:51PM +0000, Idan Arye via Digitalmars-d wrote: [...]uint startsWith(alias pred = "a == b")(Range doesThisStart, Needles... withOneOfThese); where: Range is an inferred template argument Needles is a variadic inferred template argument isInputRange!Range Needles.length > 1 is(typeof(.startsWith!pred(doesThisStart, withOneOfThese[0])) : bool) is(typeof(.startsWith!pred(doesThisStart, withOneOfThese[1..$])) : uint) We've broken the signature into the parts required to use the function and the parts required to FULLY understand the previous parts. The motivation is that the second group of parts is also important, so it needs to be there, but it creates a lot of unneeded noise so it shouldn't be a direct part of the signature(at least not in the doc). It's similar to the docs of other types used in the signature - it's important to have these docs somewhere accessible, but you don't want to add them in the middle of the signature because it'll make it unreadable.This is not a new idea: https://issues.dlang.org/show_bug.cgi?id=13676 The question is, who's gonna implement it? T -- If you want to solve a problem, you need to address its root cause, not just its symptoms. Otherwise it's like treating cancer with Tylenol...
Mar 26 2015
On Thursday, 26 March 2015 at 19:32:53 UTC, Idan Arye wrote:The problem, as Andrei Alexandrescu pointed out(http://forum.dlang.org/thread/mdtago$em9$1 digitalmars.com?page=6#post-mduv1i:242169:241 40digitalmars.com), is learning how to use them. Ideally you'd want to be able to look at a function's signature and learn from that how to use it. It's name and return type should tell you what it does and it's argument names and types should tell you what to send to it. The documentation only there for a more through description and to warn you about pitfalls and edge cases. But when it comes to heavily templated functions - understanding the signature is HARD. It's hard enough for the top programmers that can handle the complex D features - it's much harder for the average programmers that could have easily used these functions if they could just understand the documentation.I think the documentation should simply contain the unittests - they show quite well how to call the template, from minimal cases to the complex ones. Ok, they tend to show a lot of edge-cases, but even the very simplest usages of a function should be unit-tested, so at least those have to be part of the documentation.
Mar 27 2015
On Friday, 27 March 2015 at 10:10:37 UTC, Dominikus Dittes Scherkl wrote:On Thursday, 26 March 2015 at 19:32:53 UTC, Idan Arye wrote:Unittests are helpful, but I think examples aimed at demonstrating usage are of more value if possible. Unittests and examples have subtly different purposes. When writing a Unittest the programmer will likely take whatever shortcuts they can to get data into the tested function in the correct format, with the least amount of code/effort legally possible. Whereas examples (hopefully) will try to present inputs in 'real life' scenarios. If the function inputs are trivial (ie. takes an integer or basic string) then this isn't an issue. But for functions taking complex inputs it can be a bit baffling for someone new to the language. I must admit when I was new to phobos I struggled with the use of unittests as examples, especially for functions taking Anyway, unittests are better than nothing - if that is the other option.But when it comes to heavily templated functions - understanding the signature is HARD. It's hard enough for the top programmers that can handle the complex D features - it's much harder for the average programmers that could have easily used these functions if they could just understand the documentation.I think the documentation should simply contain the unittests - they show quite well how to call the template, from minimal cases to the complex ones. Ok, they tend to show a lot of edge-cases, but even the very simplest usages of a function should be unit-tested, so at least those have to be part of the documentation.
Mar 27 2015
On Friday, 27 March 2015 at 14:02:55 UTC, CraigDillabaugh wrote: clipIf the function inputs are trivial (ie. takes an integer or basic string) then this isn't an issue. But for functions taking complex inputs it can be a bit baffling for someone new to the language. I must admit when I was new to phobos I struggled with the use of unittests as examples, especially for functions takingfor functions taking ranges or other non-trivial inputs.Anyway, unittests are better than nothing - if that is the other option.
Mar 27 2015
Le 27/03/2015 15:02, CraigDillabaugh a écrit :On Friday, 27 March 2015 at 10:10:37 UTC, Dominikus Dittes Scherkl wrote:Just a little point : I find some much examples not tested on Internet, so to me examples have to by played by the compiler in the same time as unittest. Maybe it must have a new keyword? But that true unittest doesn't have exactly the same purpose and some risk to be hard to read for a beginner.On Thursday, 26 March 2015 at 19:32:53 UTC, Idan Arye wrote:Unittests are helpful, but I think examples aimed at demonstrating usage are of more value if possible. Unittests and examples have subtly different purposes. When writing a Unittest the programmer will likely take whatever shortcuts they can to get data into the tested function in the correct format, with the least amount of code/effort legally possible. Whereas examples (hopefully) will try to present inputs in 'real life' scenarios. If the function inputs are trivial (ie. takes an integer or basic string) then this isn't an issue. But for functions taking complex inputs it can be a bit baffling for someone new to the language. I must admit when I was new to phobos I struggled with the use of unittests as examples, especially for functions taking Anyway, unittests are better than nothing - if that is the other option.But when it comes to heavily templated functions - understanding the signature is HARD. It's hard enough for the top programmers that can handle the complex D features - it's much harder for the average programmers that could have easily used these functions if they could just understand the documentation.I think the documentation should simply contain the unittests - they show quite well how to call the template, from minimal cases to the complex ones. Ok, they tend to show a lot of edge-cases, but even the very simplest usages of a function should be unit-tested, so at least those have to be part of the documentation.
Mar 27 2015
On Friday, 27 March 2015 at 19:36:23 UTC, Xavier Bigand wrote:Le 27/03/2015 15:02, CraigDillabaugh a écrit :clipOn Friday, 27 March 2015 at 10:10:37 UTC, Dominikus Dittes Scherkl wrote:That is a good point. Ideally when building a library all the 'examples' in the documentation should be built too to make sure they are still valid. Example code should be marked as such, extracted and run through the compiler with each new release. I seem to recall reading in places that some D resources (Ali's book perhaps) do this with their source code. As things stand that would be a mark in favor of unittests.Just a little point : I find some much examples not tested on Internet, so to me examples have to by played by the compiler in the same time as unittest. Maybe it must have a new keyword? But that true unittest doesn't have exactly the same purpose and some risk to be hard to read for a beginner.
Mar 27 2015
On Friday, 27 March 2015 at 19:44:10 UTC, CraigDillabaugh wrote:That is a good point. Ideally when building a library all the 'examples' in the documentation should be built too to make sure they are still valid. Example code should be marked as such, extracted and run through the compiler with each new release. I seem to recall reading in places that some D resources (Ali's book perhaps) do this with their source code. As things stand that would be a mark in favor of unittests.D has documented unittests (they appear in the docs as if part of the Examples section). The only excuses for example code in Phobos to be untested are supposed to be that it is an incomplete fragment or that it is old code from before we had the feature. — David
Mar 27 2015
On Friday, 27 March 2015 at 19:47:47 UTC, David Nadlinger wrote:On Friday, 27 March 2015 at 19:44:10 UTC, CraigDillabaugh wrote:Does that force the examples to be unittests though?That is a good point. Ideally when building a library all the 'examples' in the documentation should be built too to make sure they are still valid. Example code should be marked as such, extracted and run through the compiler with each new release. I seem to recall reading in places that some D resources (Ali's book perhaps) do this with their source code. As things stand that would be a mark in favor of unittests.D has documented unittests (they appear in the docs as if part of the Examples section). The only excuses for example code in Phobos to be untested are supposed to be that it is an incomplete fragment or that it is old code from before we had the feature. — David
Mar 27 2015
D has documented unittests (they appear in the docs as if part of the Examples section). The only excuses for example code in Phobos to be untested are supposed to be that it is an incomplete fragment or that it is old code from before we had the feature. — DavidI added some just recently, because it wasn't possible to add unittest to the module level. https://github.com/D-Programming-Language/phobos/blob/master/std/container/package.d
Mar 28 2015
On 2015-03-26 19:32:51 +0000, Idan Arye said:There is a discussion about D vs Go going on in several threads(yey for multithreading!), and one thread is about an article by Gary Willoughby that claims that Go is not suitable for sophisticated programmers(http://forum.dlang.org/thread/mev7ll$mqr$1 digitalmars.com). What's interesting about this one is the reddit comments, which turned into an argument between simple languages that average programmers can use and complex languages that only the top 1% of intelligent programmers can use, but they can extract more out of them. But the thing is - the world of the top programmers is not really separate from that of average programmers. Professional development teams can have a few top programmers and many average one, all be working on the same project. Open source projects can have top programmers working on the core while allowing average programmers to contribute some simple features. Top programmers can write libraries that can be used by average programmers. To allow these things, top programmers and average programmers should be able to work on the same language. Of course, any language that average programmers can master should be easy for a top programmer to master - but the thing is, we also want the top programmer to be able to bring more out of the language, without limiting them by it's over-simplicity. This will also benefit the average programmers, since they also improve the quality of the libraries and modules they are using. This idea is nothing new, and was mentioned in the main(=biggest) current D vs Go thread(http://forum.dlang.org/thread/mdtago$em9$1 digitalmars.com?page=3#post-jeuhtlocousxtezoaqqh 40forum.dlang.org). What I want to talk about here is the seams. The hurdles that in practice make this duality harder. Let's compare it to another duality that D(and many other languages, mainly modern systems languages) promotes - the duality between high-level and low-level. Between write-code-fast and write-fast-code. The transition between high-level and low-level code in D consists by a change of the things uses - which language constructs, which idioms, which functions. But there aren't any visible seams. You don't need to use FFI or to dynamically load a library file written in another language or anything like that - you simply write the high-level parts like you would write high-level code and the low-level parts like you would write low-level code, and they just work together. The duality between high-level D and low-level D is seamless. The duality between simple D and complex D - not so much. The seams here exist mainly in understanding how to use complex code from simple code. Let's take std.algorithm(.*) for example. The algorithms' implementations there are complex and use advanced D features, but using them is very simple. Provided, of course, that you know how to use them(and no - not everything that you know becomes simple. I know how to solve regular differential equations, but it's still very complex to do so). The problem, as Andrei Alexandrescu pointed out(http://forum.dlang.org/thread/mdtago$em9$1 digitalmars.com?page=6#post-mduv1i:242169:241 40digitalmars.com), is learning how to use them. Ideally you'd want to be able to look at a function's signature and learn from that how to use it. It's name and return type should tell you what it does and it's argument names and types should tell you what to send to it. The documentation only there for a more through description and to warn you about pitfalls and edge cases. But when it comes to heavily templated functions - understanding the signature is HARD. It's hard enough for the top programmers that can handle the complex D features - it's much harder for the average programmers that could have easily used these functions if they could just understand the documentation. Compare it, for example, to Jave. Even if a library doesn't contain a single documentation comment, the auto-generated javadoc that contains just the class tree and method signatures is usually enough to get an idea of what's going where. In D, unless the author has provided some actual examples, you are going to have a hard time trying to sort out these complex templated signatures... That's quite an hurdle to go though when wanting to use complex code from simple code(or even from other complex code). That's the ugly seam I'm talking about. Now, if you are working on a big project(be it commercial or open-source), you can find lot's of examples how to use these complex functions, and that's probably how you'd tackle the problem. When you are using some library you usually don't have that luxury - but these libraries usually have the generated ddoc at their website. Of course - that generated ddoc is full with complex templated signatures, so that's not very helpful... So, what can be done? Maybe the ddoc generator, instead of writing the whole signature as-is, can emit a more human-readable version of it? Let's look at the example Andrei mentioned - startsWith. Let's take a look at the first overloaded signature: uint startsWith(alias pred = "a == b", Range, Needles...)(Range doesThisStart, Needles withOneOfThese) if (isInputRange!Range && Needles.length > 1 && is(typeof(.startsWith!pred(doesThisStart, withOneOfThese[0])) : bool) && is(typeof(.startsWith!pred(doesThisStart, withOneOfThese[1..$])) : uint)); Let's break it down and see what the user needs in order to use the function: `uint` - the return type. Needed. `startsWith` - the function name. Needed. `(alias pred = "a == b",` - a template argument that the user might want to supply - Needed. `Range, Needles...)` - template arguments that should usually be inferable. The function won't work without them, but since the user doesn't actually supply them - I'll mark them as not needed. `(Range doesThisStart, Needles withOneOfThese)` - the function's arguments. Needed. The rest are constraints that check the template arguments. They aren't needed when you try to use the function - though they might be helpful at figuring out why the compiler yells at you when you use it wrong. So, if we take only the needed parts, we get this signature: uint startsWith(alias pred = "a == b")(Range doesThisStart, Needles withOneOfThese); Well, doesn't this look much easier to grasp? Of course, it omits some very critical information. It doesn't tell you what are `Range` and `Needles` - you can look for these types in the docs and find nothing. It also doesn't tell you that `Needles` is variadic. Well - what's stopping us from adding this information *below* the signature? What if ddoc would generate something like this: uint startsWith(alias pred = "a == b")(Range doesThisStart, Needles... withOneOfThese); where: Range is an inferred template argument Needles is a variadic inferred template argument isInputRange!Range Needles.length > 1 is(typeof(.startsWith!pred(doesThisStart, withOneOfThese[0])) : bool) is(typeof(.startsWith!pred(doesThisStart, withOneOfThese[1..$])) : uint) We've broken the signature into the parts required to use the function and the parts required to FULLY understand the previous parts. The motivation is that the second group of parts is also important, so it needs to be there, but it creates a lot of unneeded noise so it shouldn't be a direct part of the signature(at least not in the doc). It's similar to the docs of other types used in the signature - it's important to have these docs somewhere accessible, but you don't want to add them in the middle of the signature because it'll make it unreadable. This idea, of course, is not a finally cooked proposal yet. We need a way to tell ddoc which template arguments are supposed to be inferred(can this always be done automatically?) and the last two entries in my example are not super-trivial to grok(I can rewrite them by-hand to make them super-simple - but can ddoc do it automatically? and how?). The point of this thread is to start a discussion about making ddoc generate documentations that are more... well... human readable.This is very good. I consider myself well-versed in D, and able to write these sorts of functions. However, reading the signatures is next to impossible. -Shammah
Mar 27 2015