Like Perl, the original POD had flaws, but Raku’s POD6 is much more flexible, while looking similar.
Table of Contents
- Blatant advertisement, yet …
- In the beginning, the prophet was silent
- Literate programming
- Commenting
- I want my own blah-blah-blah
- No XML 😦 or perhaps 🙂
- Streams, but not data
- What’s ahead?
Blatant advertisement, yet …
Although this article is supposed to be about how the original RFCs for changing Perl’s POD turned into Raku’s POD6, a few words about how I got to know Raku’s POD quite well seem appropriate now, and I have some thoughts about how POD6 could be utilised further, much more than it is now.
My experience of POD6 started when I asked how I could help the documentation system. JJ pointed me at issues in Pod::To::HTML
. I thought it unusual to find a major language module to have comments in the code like ‘Fix me’.
Ultimately, I rewrote the whole module – Raku::Pod::Render
is still a work in progress as it is too slow – but along the way, I had to really learn POD6. I also wanted to write a simple tool to convert the POD6 in a module into a README.md file that accompanies a github repo (I hate having to write in POD6 for the module, then rewrite a README.md file. And that took me into a look at MarkDown, and how much better POD6 is than MarkDown.
In the beginning, the prophet was silent
Larry Wall did not write an apocalypse for POD, so there was no Exegesis. By the time the Synopses were written, it was clear that there were missing topics. Damian Conway wrote Synopsis 26 for POD, and nearly all of Synopsis 26 ended up in the PDD document in Raku’s document set. So lets look at the the ten RFC’s (out of 361) submitted relating to POD. Here are their titles and a brief comment of mine.
- RFC 11 Examples encoded with =also for|begin|end POD commands Define a way of showing Perl code that can be run (literate programming)
- RFC 65 Add change bar functionality to pod Add a char at start of a line that has been altered, but isn’t this what a CVS does?
- RFC 79 The Predefined POD Streams are perl, data, and doc Add streams of documentation, data and code
- RFC 216 POD should tolerate white space Reduce the white space requirements around pod commands
- RFC 217 POD needs a reorder command Allow the POD to be re-ordered when output (literate programming)
- RFC 280 Tweak POD’s C<> Remove a problem passing “ format code
- RFC 286 Add a “emit pod” runtime option to Perl Have the compiler emit the POD in the code
- RFC 306 User-definable POD handling A syntax for extending POD
- RFC 325 POD and comments handling in perl Combine # and POD type comments
- RFC 357 Perl should use XML for documentation instead of POD Dump POD for XML
The RFCs incorporated into POD6 are actually less interesting than those which were not.
Briefly, the treatment of white space became more consistent, the bracketing of Format Codes (e. g. C<> ) was specified correctly, and a compiler flag --doc=XXX
was added so that any POD6 in a module is rendered into XXX
if there is a Pod::To::XXX
module installed. I will say more about # comments and extensibility, but in fact POD6 does more with #
than the RFC suggested, and Pod::Blocks are inherently extensible.
The idea to have a char to show changes did not fly.
Literate programming
Two of the RFCs explicitly refer to ‘literate programming’.
I remember vividly when I was reading the comments about Synopsis 26 that there was a heated discussion about POD6 and Literate Programming. Unfortunately, I could not quickly find the emails. But here is a recent article referring to Perl’s POD and how it is NOT literate programing. This recent blog seems to me close to the arguments I remember, and I remember the passion of the argument that POD6 could make Perl into a true literate programming language.
Neither of the RFC suggestions were incorporated into POD6.
Looking back, however, it seems to me that Damian’s design combined with the fluency of Raku’s syntax accomplishes far more of the underlying intent of literate programming. Donald Knuth introduced the term, and here is an except from the Literate Programming website:
“I believe that the time is ripe for significantly better documentation of programs, and that we can best achieve this by considering programs to be works of literature. Hence, my title:”Literate Programming.”
“Let us change our traditional attitude to the construction of programs: Instead of imagining that our main task is to instruct a computer what to do, let us concentrate rather on explaining to human beings what we want a computer to do.
“The practitioner of literate programming can be regarded as an essayist, whose main concern is with exposition and excellence of style. Such an author, with thesaurus in hand, chooses the names of variables carefully and explains what each variable means. He or she strives for a program that is comprehensible because its concepts have been introduced in an order that is best for human understanding, using a mixture of formal and informal methods that reinforce each other.”
Raku facilitates many of these aims by allowing a programmer a great deal of flexibility over names. In addition, Raku has removed many of the ‘ordering’ problems by allowing for stubs to be written before the code is written. The focus in Raku on Object Orientation (including the division between Roles and Classes) fundamentally changes the way programs are written.
But POD6 too facilitates the aims of literate programming. A Pod6 renderer collects all the =header
commands and collects them into a Table of Contents, and the X<> Format Code marks words that are to be used in an Index (I prefer the word ‘glossary’), that is a table separate from the Contents in which terms can be collected together (often at the back of a book), so that you can see where the same term occurs in multiple different places. For example, say
is associated with many classes.
A Pod6 renderer can then collect this information and present it in a different way than it occurs in the software.
Another aspect of POD6 is that program snippets can be written in =begin code / =end code
sections. These can be processed when a Renderer is parsing the pod in a file. For example, the standard Pod::To::HTML
contains a callback that is activate by a code
block. It is mostly used to call an external highlighter so that the documentation on the Raku site is coloured in a syntactically meaningful way.
It could also be used to test the code to see if it works. Indeed I think one of the extra tests in the documentation does that.
Briefly, although the literate programming RFCs were not incorporated per se, Raku can be used in the way Knuth originally intended, I would quite firmly suggest.
Commenting
The RFC concerning the use of #
basically says POD should incorporate #
> more. At the same time, other languages had a very useful feature that allowed comments associated with a function to be extracted as help tips for that function.
The POD6 specification provide for #|
and #=
“comments”. Currently, the Comma Raku IDE uses this attribute of POD6. Declare a variable with my $xxx
and precede it with a #| xxx is not suitable for work
and everywhere else in the program – so long as that declaration of $xxx
is in scope, you will be told that $xxx is not suitable for work whenever you hover the mouse over the variable.
The same is true of any other declaration. As soon as I discovered Comma does this, I went and commented on every variable, method, sub etc declaration.
I want my own blah-blah-blah
Whenever, Raku comes across a =command
, it creates a new Pod::Block
, and gives it a name. Hence =head1
creates a Pod::Block::Named.new(name=>'head', level=>1, contents=>'....')
. So all you need to do is write =Diagram
and you get a new diagram.
In addition, if instead of =Diagram
, you use either of the forms =begin Diagram :some-meta-data<oops>
you will get a Pod::Block::Named(name=>'Diagram', meta=>%( :some-meta-data<oops> ), contents=>'....'
.
Given that Raku provides all this information, all that is needed is for the Renderer to use it. For example, the approach I have chosen for my Raku::Pod::Render
is to have a template for each type of Pod::Block
. So the Renderer can pass into the Pod::To::HTML
object the name of a custom block, and a template with the same name. The Renderer will then pass all the configuration data to the template, and so render that block in any way the programmer wants.
So my Pod::To::HTML
has an Image
block and image
template, so the command =for Image :class<float right> :source<some/path/to/image.png> :width<100px>
will generate <img href="some/path/to/image.png" class="float right" width="100px" height="auto"><img>
The goal of extensibility is accomplished within the design of POD6.
No XML 😦 or perhaps 🙂
Apparently (that is according to the text of the RFC) the last suggestion was hotly debated. In the end, a specification for POD6 was written, and it is not XML.
It seems to me that XML went though a bit of a fashion period. It was used for everything. And yet, like all paradigms, XML has limitations. For me, the ability to read documentation in raw form is important. I am writing this article in POD6 straight into the computer. There will be some syntax errors, but it will convert well into HTML and MarkDown. I cannot write XML directly into a computer as it is almost certain some missing or extra whitespace, comma, etc. will prevent the text being rendered.
Another early POD6 renderer was Pod::To::BigPage
. It has sections for XML, but they were never used.
Streams, but not data
The pod in a program can be accessed by the program itself, via the $=pod variable. However, it is not possible do use POD6 to provide data to the program, in the same way as Perl’s __DATA__
statement.
Personally, I don’t think it matters. I accomplish the same thing with a combination of a sub data
at the end of the program that evaluates to the desired data. A quoting construct provides a clear way to structure the data.
In addition, I think it would be confusing to provide data from a construct that is for documentation.
What’s ahead?
The Raku documentation already uses configuration data in the starting =begin pod
stanza to generate the page in the correct category and to provide information to the search engine on the Raku documentation site.
The configuration data, together with arbitrary Pod::Block
s means that Raku’s POD could be used in many innovative ways.
It seems to me that POD6 is so much richer than MarkDown that it could be used as the content files for website design, and for text that will be published in book form.
Rendered from arc/POD6 for Advent.pod6 at 2020-08-02T08:50:54Z
An index and a glossary are two fundamentally different things. An index tells you where in the document you can find information about, or at least occurrences of, the word you looked up; a glossary just tells you what the word means. So I think the POD6 Index is appropriately named.
LikeLike
The comment is true, so far as it goes. The problem, and the reason for the change of name, is due to semantic over-loading. Currently, POD6 is rendered into HTML, where an ‘index.html’ is a landing page. If a web-site is a metaphor for a book, then the landing page is more a metaphor for a Table of Contents. But ‘index.html’ is neither a Table of Contents, nor an Index in terms of the book metaphor. When I was trying to discuss how to handle the X<> format code with another developer, I used the word ‘index; to begin with. It confused the conversation because it is not related, even remotely to the ‘index.html’ of a web-site. The next best word was ‘glossary’. This is a choice I recognise that I made since prior to this article / blog and your comment, there it has not been a topic of conversation. Using the word ‘index’ was confusing, so another word was needed.
At the same time, a ‘glossary’ is not a place that tells what a word means. That would be a dictionary, and yet ‘dictionary’ is also semantically over-loaded in the software world. A glossary in the terms of a book is more like a commentary about the contents of the book, or a summary of terms used in a book. The point about the X<> format is to provide to a text writer using POD with a tool for collecting information about terms that do not need to be in the TOC, but which should be collected somewhere else. Further, the aim is for that term to be seachable in multiple ways, and for the same term in mutiple places to be shown together. This multiplicity in both directions is not really an index either. In software terms, an index is at most a many to one mapping. That is, ‘say’ and ‘put’ could map to a description about IO. But the intent is, for example, for ‘say’, ‘how to output’, ‘print’ to point to ‘IO’, ‘IO::Path’, ‘Cool’, or any other module that over-loads ‘say’.
At present, the X<> contents are picked up for the search engine and not placed in a separate ‘index’ or (in my terms) a ‘glossary’.
The interesting thing about this topic, just stepping back a bit, is that POD6 is much richer and offers more functionality than previous documentation systems.
LikeLike
I’ve been wondering about the relationship between POD-r and MarkDown – please can you point me to a good exemplar / article on best practice??
LikeLike
@p6steve ‘Best practice’ for whom? For writing ‘POD-r ‘ (Podr? – better than rakupod 🙂 )? Or best practice for writing ‘MarkDown’? Or best practice for writing Podr that will be turned into MarkDown?
LikeLike