Misunderstanding documentation output using Revise and a Package

Hi,

I’ve been trying to get back to basics after being away from Julia for quite a while and I am struggling with some basic concepts, as it seems.

My question is, when I am using Revise and Packages does the function documentation also get updated? I see something which I believe is inconsistency but it could also be just my misunderstanding.

Here is my example. I have written the following function in a file named "AR_functions.jl" ( I deleted parts of the code to make the example short, they aren’t important)

"""
    mlag(X::Array,p::Int64; cnst=1)
Creates a lagged matrix of X with p lags. 
Returns **Xlag** and **Y**, such that size(Xlag,1) = T-p and **Y** = X[p+1:end,:]
Adds a constant to the last column by default, can be disabled by cnst=0.
"""
function mlag(X::Array,p::Int64; cnst=1)
    ...
end

Then, if I have in my main file

using Revise
includet("AR_functions.jl")

After typing mlag I get

mlag (generic function with 1 method)

and I get the documentation printed in the REPL with the β€œ?” sign:

help?> mlag
search: mlag muladd similar accumulate accumulate! @atomicreplace maxintfloat

  (Xlag,Y) = mlag(X::Array,p::Int64; cnst=1)

  Creates a lagged matrix of X with p lags. 
  Returns Xlag and Y, such that size(Xlag,1) = T-p and Y = X[p+1:end,:]
  Adds a constant to the last column by default, can be disabled by cnst=0.

If I change the function above by specifying the Float64

"""
    mlag(X::Array{Float64},p::Int64; cnst=1)
"""
function mlag(X::Array{Float64},p::Int64; cnst=1)

and again rerun the includet and type mlag in the REPL get generic function with 2 methods, and if I type ?mlag I get the two methods:

help?> mlag
search: mlag muladd similar accumulate accumulate! @atomicreplace maxintfloat

  (Xlag,Y) = mlag(X::Array,p::Int64; cnst=1)

  Creates a lagged matrix of X with p lags. 
  Returns Xlag and Y, such that size(Xlag,1) = T-p and Y = X[p+1:end,:]
  Adds a constant to the last column by default, can be disabled by cnst=0.
  ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────  

  (Xlag,Y) = mlag(X::Array{Float64},p::Int64; cnst=1)

  Creates a lagged matrix of X with p lags.
  Returns Xlag and Y, such that size(Xlag,1) = T-p and Y = X[p+1:end,:]
  Adds a constant to the last column by default, can be disabled by cnst=0.

So far so good, I added a second method. Now, for me, I want to stay with only one of the methods, because I am trying things out but I don’t want to restart Julia all the time. So after reading the documentation and the forums I realized that packages&Revise should do the trick. So I followed this and created MyPkg which includes the following code, simply β€œexport” and then the first function simply pasted from the other file

module MyPkg
export mlag, ols
# Write your package code here.
"""
    (Xlag,Y) = mlag(X::Array,p::Int64; cnst=1)
"""
function mlag(X::Array,p::Int64; cnst=1)
   ....
end

which I then add to my code using

using Revise
using MyPkg

and running the same statements mlag and ?mlag result in Julia telling me I have a function with 1 method and the docs, respectively.

Here is the weird part

If I go through and make the same change above (adding β€œFloat64” to the function and to the docs), when I get a discrepancy. I now get 1 method, but have both documentations as if it has 2

julia> mlag
mlag (generic function with 1 method)

help?> mlag
search: mlag muladd similar accumulate accumulate! @atomicreplace maxintfloat

  (Xlag,Y) = mlag(X::Array,p::Int64; cnst=1)

  Creates a lagged matrix of X with p lags. 
  Returns Xlag and Y, such that size(Xlag,1) = T-p and Y = X[p+1:end,:]
  Adds a constant to the last column by default, can be disabled by cnst=0.
  ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────  

  (Xlag,Y) = mlag(X::Array{Float64},p::Int64; cnst=1)

  Creates a lagged matrix of X with p lags.
  Returns Xlag and Y, such that size(Xlag,1) = T-p and Y = X[p+1:end,:]
  Adds a constant to the last column by default, can be disabled by cnst=0.

It says 1 method but gives me two documentations. Is this normal? Can I be sure that the function is now updated?

And finally, is there a better way for development without having to restart Julia?

Thanks!

I may well be missing you point completely, but if you make your .jl file a module and do using AR_functions instead of includet("AR_functions.jl") then Revise should work fine. If AR_functions is a package, you will probably need to dev it rather than add it.

Thanks! I tried that but Revise didn’t work as it does when it is in a package. This is confusing to me as a newcomer but it is what it is. Spent 2-3 hours reading today about it.

In short, If I make a module and use it with using .AR_functions, AND in that module if I export mlag, then I cannot change the functions anymore

WARNING: using test.mlag in module Main conflicts with an existing identifier

If I do not export the function mlag, I can call the function via AR_functions.mlag and then Revise works as expected (this how it is in the docs of Revise), but this type of calling functions annoys me somehow. This is why I went for a package.

My point with the post was, that, if I have Revise and if I add a method to a function in a package but delete another method, I still get the message that I have 1 method (opposed to 2 methods as one would have with include) BUT if I type in the help ?mlag, I get an output as if I have two methods. So I am wondering if this is a bug or I am missing something.

That is really strange.

Could it be the difference between

using .AR_functions

and

using AR_functions

ie without the dot?

That’s probably a bug in Revise, or possibly in Julia’s documentation system. Revise and the docsystem both use method signatures to keep track of methods and to associate docstrings to them, but your specific edit is changing the signature of the method. Revise is smart enough to realize you’ve deleted the method without the Float64 parameter and deletes the old one (you can check with methods(mlag)) but it probably fails to delete the docstring for the old signature.

But the bottom line is your code should be working as you expect, and the documentation bug should automatically fix itself when you start a fresh session. So you can keep doing development and make many changes, and then verify that indeed all is OK with the docstrings at the end by restarting your session (once).

1 Like

Okay, a bug makes sense.

Is just that as a newcomer I approach it usually as not a bug but a misunderstanding of my part (which it usually is :smiley: ).

I know it’s minor, and it goes away on its own of course, so it doesn’t matter in practice.

@ctkelley Without the dot a local module doesn’t work at all or am I missing something? Here is the excerpt from the docs:

β€œTo load a module from a package, the statement using ModuleName can be used. To load a module from a locally defined module, a dot needs to be added before the module name like using .ModuleName .”

OK. I put directories I’m working on in my LOAD_PATH and then the dot is not necessary.

And then it works differently? I have to figure out how to do this, i have literally two files in the working folder and the second is the module for testing. I would also prefer to have them there and not in a package somewhere (I am still exploring and playing around).

I have never had to use the dot. This is a mystery to me.

This command in my startup.jl file adds the current directory (wherever you are) to the load path

push!(LOAD_PATH,".")
1 Like