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.
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.
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.
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.
As the user of a package, I’d like to be able to open the main file and quickly skim the export
s and public API.
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
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.
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
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