Deprecation => error?

I am really trying to say as politely as I can! :slight_smile:

I am sorry but I don’t think it is proper way how we do deprecation!

From julia/base/deprecated.jl:

macro deprecate_moved(old, new, export_old=true, default_package=false)
    eold = esc(old)
    return Expr(:toplevel,
         default_package ? :(function $eold(args...; kwargs...)
                                 error($eold, " has been moved to the standard library package ", $new, ".\n",                                                              
                                       "Restart Julia and then run `using ", $new, "` to load it.")
                             end) :
                           :(function $eold(args...; kwargs...)
                                 error($eold, " has been moved to the package ", $new, ".jl.\n",
                                       "Run `Pkg.add(\"", $new, "\")` to install it, restart Julia,\n",
                                       "and then run `using ", $new, "` to load it.")
                             end),
         export_old ? Expr(:export, eold) : nothing,
         Expr(:call, :deprecate, __module__, Expr(:quote, old), 2))
end

It is bad enough to return error during deprecation phase, but also if we try something from:

# Special functions have been moved to a package
for f in (:airyai, :airyaiprime, :airybi, :airybiprime, :airyaix, :airyaiprimex, :airybix, :airybiprimex,
          :besselh, :besselhx, :besseli, :besselix, :besselj, :besselj0, :besselj1, :besseljx, :besselk,
          :besselkx, :bessely, :bessely0, :bessely1, :besselyx,
          :dawson, :erf, :erfc, :erfcinv, :erfcx, :erfi, :erfinv,
          :eta, :zeta, :digamma, :invdigamma, :polygamma, :trigamma,
          :hankelh1, :hankelh1x, :hankelh2, :hankelh2x,
          :airy, :airyx, :airyprime)
    @eval @deprecate_moved $f "SpecialFunctions"                                                                                                                            
end

for example:

julia> zeta(0)
ERROR: Base.zeta has been moved to the package SpecialFunctions.jl.
Run `Pkg.add("SpecialFunctions")` to install it, restart Julia,
and then run `using SpecialFunctions` to load it.

it tell us to run Pkg.add also in case we have SpecialFunctions installed.

And why we need to restart Julia? Couldn’t using Unicode redefine Base.uppercase during deprecation period as we can see below?

julia> uppercase("abc")
ERROR: Base.uppercase has been moved to the standard library package Unicode.
Restart Julia and then run `using Unicode` to load it.
Stacktrace:
 [1] error(::Function, ::String, ::String, ::String, ::String, ::String, ::String) at ./error.jl:42
 [2] #uppercase#978(::NamedTuple{(),Tuple{}}, ::Function, ::String, ::Vararg{String,N} where N) at ./deprecated.jl:138
 [3] uppercase(::String, ::Vararg{String,N} where N) at ./deprecated.jl:138
 [4] top-level scope

julia> using Unicode

julia> using Base.uppercase
julia> Base.uppercase(args...; kwargs...) = Unicode.uppercase(args...; kwargs...)

julia> uppercase("abc")
"ABC"

And don’t we need all this newly deprecated functions put in NEWS.md?

Am I missing something?

You are looking at the active development of an unreleased version. If you find things to improve, participate in the development.

3 Likes

Are you using 0.7? That version breaks a lot of things with respect to 0.6. If you want a “production” version, use 0.6.

1 Like

Normally there would be a “soft” deprecation period for name/feature changes, where the message is only a warning, but for code removal that would make maintenance significantly more difficult because we would need to keep two copies of the code in sync for an entire release cycle (or use tricky tools like git submodules). So these are “hard” deprecations in the sense that there is still a (hopefully)-informative message, instead of only a “not found” error.

GitHub - timholy/Revise.jl: Automatically update function definitions in a running Julia session might help.

In the case of the special functions, they were mentioned in the release notes for 0.6:

3 Likes
  1. This could not be excuse for mature well established language.
  2. deprecated.jl could import SpecialFunctions and Base.zeta could call SpecialFunctions.zeta (I see nor significant difficulty nor two copies of code)

But when I asked in first post: “Am I missing something?” I really expect that there could be some deeper problem which prevent us to use “import solution”.

I don’t understand. What I am talking about is stevengj’s post, Jeff’s answer and ararslan’s reaction.

But I think that I wrote example above where I was able to use uppercase without restarting Julia and without using Revise.jl (I am still newbie and I could be wrong and it is unusable):

Sorry! My mistake! My memory mixed up News.md and History.md.

PS. It could be probably good if I try to write some proof of concept test with my idea of fixed deprecate_moved macro.

But if majority core could not see problem with hard break (and call it deprecation) why to waste energy?

Same behavior you could see in “production” version 0.6 if you try to use for example zeta function.

I think you’ve identified two potential improvements:

  • check whether SpecialFunctions is already installed
  • check the Julia version and if applicable do an @eval to update the Base definition

Sounds like you’re 95% of the way towards a pull request :wink:.

4 Likes

I agree that it is not ideal. If you look in the pull request where I introduced the @deprecated_moved macro, we specifically discussed this as an annoyance, and discussed several different ways to try to address it:

Improving the deprecation machinery for code that is moved to elsewhere has been an incremental process, and lots of technical improvements are still possible, but take some work to implement.

Yeah, well, that’s why we’re doing it now :slight_smile:

This assumes that the package is installed. It’s still an error the first time otherwise. My point is that avoiding first-time-error hard deprecation requires including the code from SpecialFunctions.jl, in the main download bundle for a release cycle. The situation when you do have the package installed already could be improved, but as the links you posted show, clearly people do and did take that seriously.

1 Like

As a general observation, implementing perfect deprecations for this sort of thing is often very time consuming and difficult – often much harder than implementing a new feature. Given that deprecations are inherently ephemeral, and especially so in the 0.7 release where you should be fixing them and immediately switching to 1.0, there’s very little reason at this point to spending a huge amount of our limited development time and energy making the deprecation experience perfect. So, please help do your part to get us closer to 1.0: if your code has a deprecation warning or error, just fix it and move on.

3 Likes

Yes. It’s right. But it’s code was in Base, so it is not too big to bundle during deprecation phase.

And I don’t think that we need to keep these copies in sync (as you wrote above).

Bundled copy Deprecated.SpecialFunctions (or probably better to name it _SpecialFunctions) could be frozen while “wild” copy SpecialFunctions could be developed independently.