docstrings implementation

I was looking for some ideas on auto generating help documents and ran accross docstrings which python uses. This allows you to add meta info to a function without modifying the function itself. I’m finding it very useful for my library functions that I have forgotten what parameters to pass.

--docstrings
docstrings = setmetatable({}, {__mode = "kv"})

function document(str)
  return function(obj) docstrings[obj] = str; return obj end
end
 
function help(obj)
  print(docstrings[obj])
end

function setup()
    document[[Print the documentation for a given object]](help)
    document[[Add a string as documentation for an object]](document)
 
    help(help)
    help(document)

    help(test)
    test("Hello World")

    help(test1)
    str =test1(4,5,6)
    print(str)
end

--function test
test = document[[This prints a simple string]](
  function(str)
    print(str)
  end
)

--function test1
test1 = document[[
Name: test1
Description: this adds a,b and c
@Param a (int)
@Param b (int)
@Param c (int)
returns int
]](function(a,b,c)
         return a+b+c
    end)
    
    



@-)

I think one line in the code above says it best - help(help)

I think I understand most of this, but first, there seems to be a simpler way of doing it, like so

docs={}. --table for help text

--function that adds help text to a new function, using the function address as a key
function addDoc(d,f)
    docs[f]=d
    return f
end
    
--function that prints help notes for function f
function help(f)  print(docs[f]) end

--test function
a=addDoc(
[[These are help notes for function a]],
function () 
    print("Test function") 
end
)

function setup()   
    --print help notes
    help(a)
    --run the function
    a()
end

All either method does is, to store some notes in a table, using the function name (actually it’s memory address) as the lookup key.

In my method above, the addDoc function takes two parameters, the help text (enclosed in two square brackets so that it can be multi-line, otherwise I would use “”), and the other parameter is the function itself.

It uses the function address as a key and adds the help text to the docs table, then returns the function it was given, which then gets put into the variable a.

So this is the same as defining function a normally, then saying docs[a]=help text.

The metatables method is more elegant in that the use of “weak tables” (the first line, _mode=“kv”) means that if the function is deleted, the help notes will also disappear when garbage is next collected.

However, I seriously doubt that many, if any, of us, are likely to be deleting functions very often, and the sheer complexity of the code is very offputting to the general Codea user.

So I prefer the simple method.

lol This ties a string to describe a function to that function. If the function is cleared from from memory via collectgarbage so is the table ref to the string.

@Briarfox very good topic. I have the same concern about an embedded documentation of functions. The method you show is a bit confusing to me. However, if it is a copy/paste from what python does, maybe there is no simpler solution?
Could you explain a little bit this syntax?
document[[Print the documentation for a given object]](help).
It is the first time i see it and i dont understand what it does.

That has all of us fooled, so far. Document seems to take 2 parameters, the help string, which it calls str, and the function address, which it calls obj. But how that syntax works I don’t know, why not say document( [[help text]], function ) instead

I have understood how it works now, but it is a bit stange way to proceed.
I think the interest of this syntax is that it allows to write the documentation just before the function, and still be included someway with the function. Usually i write the doc just after the beginning of the function, which is ok. Or is it not?
Also a detail puzzles me: you always write parameter declaration wit a ‘@’, @Param a (int) and you dont for ‘name’. What does this @ means? Is there a reason for it?

Actually, this approach defines the documentation at the same time as the function. But so does my simpler alternative.

The @looks like a documentation convention, perhaps to make it clear what is a parameter. It isn’t part of Lua itself.

The mysterious code line also works as

document(“Print the documentation for a given object”)(help)

Because [[ are the same as "

But how you can have two separate argument lists beats me…

@Igntaz Now that bit is exceedingly clever. If you return a function from a function but do not assign it then it gets called. Try:

function rtfn()
    return function(s) print(s) end
end

rtfn()("hello world")

@Andrew_Stacey - thank you, I see it now.

But I think I will stick to the simple way of doing things.