Is Compat.jl worth it for the `public` keyword?

I thought so too at first, but I got worried after some people asked me to remove the SparseArrays stdlib from DifferentiationInterface.jl because it adds 300ms of load time ^^ Didn’t think stdlibs would be such a sensitive issue.

4 Likes

Why not just do

macro public(ex)
    if VERSION >= v"1.11.0-DEV.469"
        args = ex isa Symbol ? (ex,) : Base.isexpr(ex, :tuple) ? ex.args : error("something informative")
        esc(Expr(:public, args...))
    else
        nothing
    end
end

@public x, y

?

I strongly doubt this is worth bringing in Compat.jl for, that package is quite hefty with lots of piracy and invalidations.

7 Likes

Why that macro, and where to put it? Or why not the subtly different public macro (I’m not sure which is better, and it also has a bit more code) in the (“unpopular”) unregistered package:

Why that macro

… So that you can use public on versions that support it without dropping support for old versions?

and where to put it?

In your package if you really feel the need to use public and support old versions.

Or why not the subtly different public macro (I’m not sure which is better, and it also has a bit more code) in the (“unpopular”) unregistered package:

Well, one reason I suggested the above macro is that I had never heard of that package before. Another reason would be that, as you said, its unregistered, so actually using it might end up being tricky.

Besides, this is really just such a simple macro I don’t think it particularly needs to be a dependency.

Some Julia packages include a src/compat.jl file that contains relevant snippets from Compat.jl to avoid a full dependency. You could add this macro to such a file.

2 Likes

AFAIK that did not go anywhere and recommended solution is either Compat.jl, or manually including the macro (as in the examples above). see the discussion for

I choose to recommend Meta.parse over manual Expr creation because Meta.parse is more clearly a public API while manual Expr creation is more ambiguously public.

I’m sorry but I still don’t understand why macros or manual parsing would be better than the conditional include suggested earlier. Does anyone have a simple explanation?

I suppose it depends on whether you want to have all your public declarations collected in one file or if you want to declare things public close to their definition.

4 Likes

As the user of a package, I’d like to be able to open the main file and quickly skim the exports and public API.

1 Like

In general there’s something fishy with the parsing of public, regardless of compat considerations. One would expect it to parse similar to export, but it doesn’t.

julia> begin
           export foo
       end

julia> begin
           public foo
ERROR: ParseError:
# Error @ REPL[3]:2:12
begin
    public foo
#          └─┘ ── Expected `end`
Stacktrace:
 [1] top-level scope
   @ REPL:1

and

julia> :(export foo)
:(export foo)

julia> :(public foo)
ERROR: ParseError:
# Error @ REPL[5]:1:10
:(public foo)
#        └─┘ ── Expected `)`
Stacktrace:
 [1] top-level scope
   @ REPL:1
2 Likes

Would you mind submitting that as an issue to JuliaSyntax.jl?

Done.

I believe it was intentional to not be breaking: public is only a keyword at toplevel). Was discussed in https://youtu.be/2o8MhoN-3NE?si=KHs9yiHmV6b6C4Hq too.

4 Likes

See also: Add alternative compat for public other than Compat.jl by LilithHafner · Pull Request #55097 · JuliaLang/julia · GitHub which adds

VERSION >= v"1.11.0-DEV.469" && eval(Meta.parse("public a, b, c"))

to the manual at Modules · The Julia Language

4 Likes

One known side effect of unnecessairly importing Compat.jl is this package compiler issue, but it’s a pretty niche use case, so it’s unlikely to be a problem for you Type piracy on `Base` fails incremental sysimage builds (1.9 -> 1.10 regression) · Issue #924 · JuliaLang/PackageCompiler.jl · GitHub

I’m personally not a fan of Compat.jl. It changes the global execution environment for users without their knowledge (if it lands in their Manifest) and it’s basically a type piracy factory (on Base) if used with a lower than latest Julia version.

I would rather avoid adding it to packages unless absolutely necessary. There are a few issues about side effects of Compat.jl being present implicitly in user environments, so I’d rather not contribute more to the issue

1 Like