What does the new "public" keyword actually do?

Continuing from

Does the new public keyword actually do anything? From the current 1.11 documentation and release notes, I don’t see that public has any effect on using/import.

It seems that maybe Documenter would be the primary consumer of the public information: I could see docstrings for public/private members being formatted differently, or @autodocs being able to filter on public/private/exported. I don’t think there’s a PR branch yet in Documenter to add those features, though.

Without that, it seems like public would really only surface when inspecting the source code of a package.

This is not to criticize the new feature. I very much like the idea of marking members as public non-public independently of other conventions such as underscore prefixes or hidden documentation. But it would seem to be relevant for how urgently one would want to adopt this feature and drop pre-1.11 support in packages. If there has to be slow-growing adoption by Documenter or similar tools (VSCode, I’d imagine) after the 1.11 release, this does not seem as pressing.

So what are the plans for any downstream effects of public?

8 Likes

I’d appreciate the reflection, in other words I can identify public or internal names with function calls instead of searching or reading the much longer documentation. It’s also quicker to identify public names in my own code this way than it is to write out documentation, when I’m likely at a stage where I’m not certain what to write down.

It affects names(module), which now includes by default identifiers that are non-exported but marked public.

So, basically, it gives an automated way to list the API of a module that is intended to be documented and non-private, whether or not it is exported into your namespace by using.

There is also a new Docs.undocumented_names(module) function that can be used in testing to check whether there are any names that are “public” (including exported symbols) that don’t have a docstring, i.e. with @test isempty(Docs.undocumented_names(MyModule)).

(In the future, one could imagine QA tools that check whether a package uses any non-public symbols from another package.)

7 Likes

One of the potential impacts of public that I’ve heard mentioned is on new packages that are being registered. If they are accessing private names from their dependencies, they may need to compat-limit these to specific minor versions. This includes minor releases of Julia. This will hopefully ensure fewer breakages, as only packages that are using public APIs will be allowed to upgrade to new versions.

3 Likes

Could be nice in the ideal world, but so many packages use stuff like Core.Compiler.return_type that putting these restrictions is probably infeasible for now.

2 Likes
2 Likes

This sounds like a cool feature but honestly is not the groundbreaking thing that the LTS thread makes it sound like, in my opinion. Thanks for starting this thread and asking the question.

2 Likes

Yes, the responses here pretty much confirm my suspicion. The new names behavior is not nothing, but the real benefit of public is to put the ecosystem on a long-term path for better tooling. That tooling will take a while to develop after 1.11 is released.

Thus, making 1.10 the next LTS (without public) seems like the right call. Especially because @compat public is more than a viable solution for the current (next) LTS release cycle.

1 Like

Compat.jl is a rather large dependency for a no-op. Here an alternative solution:

@static if VERSION ≥ v"1.11"
    # therein declare public identifiers
    include("public.jl")
end

There is GitHub - JuliaLang/Public.jl if you want a smaller dependency.

Unless I missed some recent activity: there was considerable pushback against that package at the time, and it never ended up being registered

It’s probably installed anyway on your machine, since so many packages use it. And as a runtime dependency it should be quite small — most of it is precompiled away if you have a recent Julia version.

1 Like