Loop over function names to document them

I have written a set of functions, say foo!, bar!, etc., to do some operations that modify their first argument. Now say I want to have their complements foo, bar… that operate on a default value of that first argument, e.g.

foo(a, args...) = foo!(defaultobject(), args...)

Instead of repeating that line with all the functions, if I’ve got all function names as symbols in the collection fnames I can just do:

for f in fnames
    f! = Symbol(f, :!)
    @eval $f(args...) = $f!(defaultobject(), args...)
end

But now I want foo and foo!, etc. to have a common docstring. I have tried to do this but it fails:

fdocs = Dict(
    :foo => "documentation of foo and foo!",
    :bar => "documentation of bar and bar!"
    # etc.
)

for (f, docstring) in fdocs
    f! = Symbol(f, :!)
    @eval $f(args...) = $f!(defaultobject(), args...)
    @doc docstring $f
    @doc docstring $f!
end

The error message that I get is:

ERROR: LoadError: LoadError: LoadError: cannot document the following expression:
$(Expr(:$, :f))

It works well if I write directly
@doc docstring :foo
and so on. What am I doing wrong in the loop?

You also need to @eval the call to @doc.

Here is an MWE, based on your example:

fdocs = Dict(
    :foo => "returns 1",
    :bar => "returns 1 also"
    # etc.
)

for (f, docstring) in fdocs
    @eval $f() = 1
    @eval @doc $docstring $f
end
help?> foo
search: foo floor pointer_from_objref OverflowError RoundFromZero unsafe_copyto!

  returns 1

help?> bar
search: bar baremodule SubArray GlobalRef clipboard BitArray backtrace BitMatrix

  returns 1 also
1 Like