Been back at coding in Nim after some time doing a job in C#.
And the whole unfriendly documentation just frustrates me more and more...
Example: Google "nim split string".
Page Result: http://nim-lang.org/docs/strutils.html
First of all its a massive documentation dump page. Why load all this information when you are looking for a specific function.
Find the "split" in the nav bar:
Page Result: http://nim-lang.org/docs/strutils.html#split,string,set[char],int
split(s: string; seps: set[char] = Whitespace; maxsplit: int = - 1): seq[string] {.
noSideEffect, gcsafe, extern: "nsuSplitCharSet", raises: [], tags: [].}
The same as the split iterator, but is a proc that returns a sequence of substrings.
proc split(s: string; sep: char; maxsplit: int = - 1): seq[string] {.noSideEffect,
gcsafe, extern: "nsuSplitChar", raises: [], tags: [].}
The same as the split iterator, but is a proc that returns a sequence of substrings.
proc split(s: string; sep: string; maxsplit: int = - 1): seq[string] {.noSideEffect,
gcsafe, extern: "nsuSplitString", raises: [], tags: [].}
Splits the string s into substrings using a string separator.
Substrings are separated by the string sep. This is a wrapper around the split iterator.
This is the resulting information set.
Lets compare that with lets say PHP ...
Description ¶
array explode ( string $delimiter , string $string [, int $limit = PHP_INT_MAX ] )
Returns an array of strings, each of which is a substring of string formed by splitting it on boundaries formed by the string delimiter.
Parameters ¶
delimiter
The boundary string.
string
The input string.
limit
If limit is set and positive, the returned array will contain a maximum of limit elements with the last element containing the rest of string.
If the limit parameter is negative, all components except the last -limit are returned.
If the limit parameter is zero, then this is treated as 1.
Note:
Although implode() can, for historical reasons, accept its parameters in either order, explode() cannot. You must ensure that the delimiter argument comes before the string argument.
Return Values ¶
Returns an array of strings created by splitting the string parameter on boundaries formed by the delimiter.
If delimiter is an empty string (""), explode() will return FALSE. If delimiter contains a value that is not contained in string and a negative limit is used, then an empty array will be returned, otherwise an array containing string will be returned.
Examples: .......
The same stuff in Golang:
func Split
func Split(s, sep string) []string
Split slices s into all substrings separated by sep and returns a slice of the substrings between those separators. If sep is empty, Split splits after each UTF-8 sequence. It is equivalent to SplitN with a count of -1.
▹ Example
func SplitAfter
func SplitAfter(s, sep string) []string
SplitAfter slices s into all substrings after each instance of sep and returns a slice of those substrings. If sep is empty, SplitAfter splits after each UTF-8 sequence. It is equivalent to SplitAfterN with a count of -1.
▹ Example
func SplitAfterN
func SplitAfterN(s, sep string, n int) []string
SplitAfterN slices s into substrings after each instance of sep and returns a slice of those substrings. If sep is empty, SplitAfterN splits after each UTF-8 sequence. The count determines the number of substrings to return:
n > 0: at most n substrings; the last substring will be the unsplit remainder.
n == 0: the result is nil (zero substrings)
n < 0: all substrings
▹ Example
func SplitN
func SplitN(s, sep string, n int) []string
SplitN slices s into substrings separated by sep and returns a slice of the substrings between those separators. If sep is empty, SplitN splits after each UTF-8 sequence. The count determines the number of substrings to return:
n > 0: at most n substrings; the last substring will be the unsplit remainder.
n == 0: the result is nil (zero substrings)
n < 0: all substrings
▹ Example
Please tell me what is more readable? Newbie friendly? Examples? Everything in the {} needs not even be listed and only frustrates a person there eyes.
My frustration level just keeps going up after a while. More & more i run into simple but stupid documentation that is just not intuitive and is simply a source documentation dump.
Maybe plenty of other people are geniuses that instantly understand the language and have loads of time. But for me when i switch between projects, there is no "learn everything by head" going on. And it frustrates the hell out of me.
Too much is simply based upon single comments and figure it out yourself. Just venting my frustration that something so simple is so unreadable in the documentation. I run into them again and again ... Frankly, thinking about going back to GoLang just because there documentation is better and its way more easy to find examples ( even with some of the disadvantages ).
I said it months ago that the project is too much elitist & not newbie friendly. And so far not a darn thing has changed. /Frustrated
The documentation is not ideal, but in this case you haven't found the "real documentation" of split on the same page: http://nim-lang.org/docs/strutils.html#split.i,string,set[char],int
The discoverability could certainly be improved, but [Ctrl-F + enter several times] finds the right proc in most cases. (I think the procs should be grouped by argument types in the index)
Although I am personally quite happy with Nim's documentation, I can see sense in your arguments.
Here are a couple concrete changes that may improve the usability of the documentation:
The issue is zielmicha, that the first thing you see if not the "real documentation". It so frustrating how the documentation is done.
In my opinion each function needs a summery with a sub-page separate for each function. So Google can instant link to the correct function page.
It drives me personally bonkers, when it takes too long to load / find the function information that is needed. Its also on other functions:
proc isLower(c: char): bool {.noSideEffect, procvar, gcsafe, extern: "nsuIsLowerChar",
raises: [], tags: [].}
Checks whether or not c is a lower case character.
This checks ASCII characters only.
Way more redable of it was simple:
proc isLower(c: char): bool
Checks whether or not c is a lower case character.
This checks ASCII characters only
Example:
xxx
Full Function:
proc isLower(c: char): bool {.noSideEffect, procvar, gcsafe, extern: "nsuIsLowerChar", raises: [], tags: [].}
Simple is better in my eyes. Separate pages per function. No "junk" visible. Only the needed function call. Put the more detailed function to a sub page.
Looking at https://docs.python.org/3/library/string.html I don't see too many things wrong with Nim's documentation. Yes you can ignore stuff in {. .} (and we should hide it). On the other hand, at least every parameter has its type listed (unlike Python's docs). A separate page for every single proc would be total overkill and only encourages documentation like:
proc foo(bar: Bar): Baz ## foo a bar. ## ## Parameters: ## bar the Bar. ## ## Returns: ## a Baz.
Which is the ultimate waste of time, wasting writers' and readers' time.
Having dealt with C#'s documentation extensively, it often doesn't mention crucial edge cases and examples and instead focusses on the obvious. I really like to avoid that. It doesn't mean that Nim is not for newbies, it means newbies need at least to be able to read Nim proc headers.
Having said that, we should really expand the pragma annotations only after a mouse click. Should be easy to do, PRs welcome. :-)
Having said that, we should really expand the pragma annotations only after a mouse click.
The problem with this is that users won't be able to search for certain pragmas in the documentation. But perhaps it's not that big of a deal.
The reason why i mention separate pages Araq is not because its waste of time but because it allows Google & other search engines to directly link to the answer people search for.
The Foo example you write above is indeed a wast of time. Its a wast to even document that because its useless. The idea of user friendly documentation is directly point to the information the user needs. Explain in detail what it does. What each function calls that a object has does. One or more examples for each and all. I simply used the "split" as one easy example of just bad documentation flow.
I come bearing examples:
http://nim-lang.org/docs/selectors.html
Do do please tell what that does? If i did not have the code as a example, you will not know what to use that function for.
http://nim-lang.org/docs/threadpool.html
Again ... if one does not know its part of the async code or finds a example of its usage. Good luck using it as a non-initiate.
Example usage? lol ... where ...
Those documentation are written by people who know the ins & outs of the code and more or less write the documentation for themselves. Nim when you understand is not ultra hard ( sometimes ) but lets be honest, it puts a 1000f wall in front of people. It starts to feel more like trying to learn Perl. When you know it, its not hard. But it simply scares away people in droves. And it bothers me a LOT running into these constant problems because the language is good Araq but its so unfriendly to learn ( from the documentation ) if you have very little experience or come from a kuch php /vb / whatever background.
Focusing on the obvious is what brings in new people. Making it easy to learn. Edges cases etc are things that people need to stumble upon or needs as "extra's" in the documentation. But simply dumping the most problematic answer in front of people and say: "He, learn from this". People there answer is: "I go somewhere else".
Said it before, marketing. The biggest fail of many products. And Nim is a product. Too many underestimate the market. You think that people will register and post how they do not understand your product or get too fast stuck in it. A lot simply quit without saying a word or give up. Let me use the restaurant analogy. Why do a lot of restaurants not understand why people do not come back. People have a less stellar experience, and simply move on to the next restaurant. But they do not tell the restaurant because they do not want to look bad. They simply vote with there actions.
There is still a lot of work left to make it a more attractive product ( especially compare to some of its competitors ). To put it in simple terms, you can make the most advanced car in the world but if it takes people too long time to read the manual & drive the car, they will simply prefer a Volkswagen beetle instead.
Anyway, my monthly rant limit is reached with this i think. ;)
I definitely agree the documentation needs a bit of work - some more examples certainly wouldn't hurt, and improving the search ability (not just on-site but via Google too) would be a massive bonus. For instance, it took me a while (and I eventually asked on IRC) to work out that indexOf in Nim was called find and was in the struts module. Ideally, a search for Nim indexOf would have taken me somewhere explaining the actual proc with an example of its usage (and it's variations grouped in one place).
I did notice that Crystal uses GitBook to generate their docs, which are very well laid out, easy to read, searchable and seem to be surfaced on Google much more readily. Possibly there's a way to optionally hook into that somehow?
I like this (docset for nim) ...
And I am really using: http://nim-lang.org/docs/theindex.html#pli normally when I search stuff.
BUT... that all can be better.
FWIW, on our team, we ask developers to put as much documentation inline as possible - and only use external documents when absolutely necessary.
The reason being simply this: documentation needs updates. When the code changes, often the documentation should too - and it's really easy to forget that, if the documentation for the code is in an entirely different system. If you weren't the original author, you might not even realize that external documentation exists.
As part of our development process, during code review, we look for changes that require documentation updates - a pull request isn't merged until it's complete with documentation updates. It doesn't work 100% of the time, but it works pretty well - a lot better than the documentation for our old platform, which was located in an external system.
IMO, information overload in the source code is a problem that can be managed - either by folding in the editor (which may increase the risk of forgetting to update the documentation!) or by writing smaller files, e.g. fewer members per file, which is usually a good thing either way.
In my experience, external documentation always rots. Inline documentation has a better chance of actually receiving the maintenance it requires.
Just my two cents.
After the 1.0 release, the language and standard libraries SHOULD be pretty stable. So external documentation should not be a problem in this regard.
cpp reference is THE best language and stdlib reference I've ever seen, much much better than the Python/NodeJS ones. And it's external documentation.
And yes, it's a C++ reference, so how it handles templates (more like generics in Nim), tons of overloads and version updates etc can be valuable to us. It's human crafted and curated, it's detailed and cares what professionals care (like when will iterators/pointers be invalidated, who will be responsible to free the memory, what is the time/space complexity can we expect from a particular container instead of just "suitable for blah blah situation" or even worse "fast enough for general usage", etc), and it's based on the C++ standards and is written by the language lawyers who do understand the standards instead of "out of experience" (making it neutral about implementations between vendors and resistant to compiler bugs and undefined behaviors, though Nim is defined by implementation and has no multi-vendor problems).
The cppreference website itself is also very featureful (based on MediaWiki anyway). It has a proper "search". It has a navigation bar (with everything grouped/categorized). Functions are grouped by human, even under the same namespace (modules in Nim). And exploring the website by clicking into different categories works damn well because everything is mostly in one screen until you click inside for a more detailed list or content. Examples are runnable on the cloud (through an external service that provides various implementations/compilers to test on) and it shows the expected output AND examples can be edited by users to try out their ideas (not committed/saved to the page, just "edit and run"). Symbols in examples are cross-referenced. It has enough redundancy, mostly for showing functions in a different format (for example, the table at the end of the page is redundant to the content of each container's page, but it's pretty damn useful.
We can just steal the design. We can even ask the webmaster of cppreference on how it is maintained by the community and how they manages redundancy and learn from it.
this thing works like a charm compared to just about anything I ever saw
Thank you! It's been 5 years of improvements. ;-)
Found myself here after spinning wheels for 20 minutes on a simple string matching loop. Python allowed me to learn and implement this with ZERO stress in less than 2 minutes.
from <https://docs.python.org/3/library/glob.html>
For example, consider a directory containing the following files: 1.gif, 2.txt, card.gif and a subdirectory sub which contains only the file 3.txt. glob() will produce the following results. Notice how any leading components of the path are preserved.
I know Python is probably the easiest and in some ways an unfair comparison, but things this rudimentary should be straightforward in any language claiming to cater to filesystem operations. I'm a noob with Nim, but I hoped that 10+ years between javascript, python, matlab, C, and bash would allow me to get started with less friction.
I fell in love with the concept of Nim instantly, but I'll be honest, I get borderline angry just trying to parse the syntax of the docs, and they are the biggest and possibly only thing holding me back from committing to Nim.
(and alas, simply trying to post this comment required me to learn a new language: RST) D- for ease of use.
Over time it will make the code less readable if developers need to jump 50 pages just to get to specific functions. Unless a person uses a IDE like Intelli/Phpstorm that can fold all documentation by default ( fat chance as there is no proper nim plugin ). Or even worse when your using VIM.
What? It would be very easy to automatically fold doc comments in Vim.
even the Nim name is obviously better, walkFiles walkDirs walkPattern is way more descriptive than glob. You only have zero stress because you know what a "glob" is.
(Funny sidenote, glob sounds a little like a German dialect word in Hesse: Klobbe which means beating.)
I've had this project on the back burner ever since I discovered Nim. When I've tried to do it in the past I've been foiled by poor jsondoc support, but I think with my latest changes merged it should now be possible.
The idea is simple, run nim jsondoc on the entire standard library. Then write a small program which ingests these JSON objects and adds everything into a database. Finally create a much more dynamic website where you can have separate pages for all procedures, search across all modules, support different ways of sorting procedures (e.g. by first argument, by name), ability to show all procedures which works on a type, etc. When all that is built we can add user submitted content such as further explanations and usage examples, similar to how the Clojure documentation works. These could of course be merged back into the Nim documentation in time.
The basic idea is simple enough, but it requires a bit of time to do it. I've recently done a similar project with ingesting jsondoc, so I might give this a shot soon.
I've had this project on the back burner ever since I discovered Nim. When I've tried to do it in the past I've been foiled by poor jsondoc support, but I think with my latest changes merged it should now be possible.
Cool, I didn't even know about jsondoc. Lots of potential for different kinds of documentation with that.