# Deprecation =\> error?

**URL:** https://discourse.julialang.org/t/deprecation-error/8062
**Category:** Internals & Design
**Created:** [December 29, 2017, 5:57pm UTC](https://discourse.julialang.org/t/deprecation-error/8062 "2017-12-29T17:57:01Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![Liso](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@Liso](https://discourse.julialang.org/u/Liso)
#### Post date: [December 29, 2017, 5:57pm UTC](https://discourse.julialang.org/t/deprecation-error/8062/1 "2017-12-29T17:57:02Z")

</div>

I am really trying to say as politely as I can! 🙂

I am sorry but I don’t think it is proper way how we do [deprecation](https://en.wikipedia.org/wiki/Deprecation)!

From `julia/base/deprecated.jl`:

```julia
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:

```julia
# 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
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
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](https://github.com/JuliaLang/julia/blob/master/NEWS.md)?

Am I missing something?

---

<div class="post-metadata">

### Author: ![lobingera](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lobingera/32/211_2.png) [@lobingera](https://discourse.julialang.org/u/lobingera)
#### Post date: [December 29, 2017, 6:35pm UTC](https://discourse.julialang.org/t/deprecation-error/8062/2 "2017-12-29T18:35:05Z")

</div>

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

---

<div class="post-metadata">

### Author: ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)
#### Post date: [December 29, 2017, 7:05pm UTC](https://discourse.julialang.org/t/deprecation-error/8062/3 "2017-12-29T19:05:10Z")

</div>

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.

---

<div class="post-metadata">

### Author: ![ihnorton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ihnorton/32/26_2.png) [@ihnorton](https://discourse.julialang.org/u/ihnorton)
#### Post date: [December 29, 2017, 8:57pm UTC](https://discourse.julialang.org/t/deprecation-error/8062/4 "2017-12-29T20:57:53Z")

</div>

> [@Liso](#):
>
> It is bad enough to return error during deprecation phase

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.

> [@Liso](#):
>
> And why we need to restart Julia?

[GitHub - timholy/Revise.jl: Automatically update function definitions in a running Julia session](https://github.com/timholy/Revise.jl) might help.

> [@Liso](#):
>
> And don’t we need all this newly deprecated functions put in NEWS.md?

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

> <https://github.com/JuliaLang/julia/blob/master/HISTORY.md>

---

<div class="post-metadata">

### Author: ![Liso](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@Liso](https://discourse.julialang.org/u/Liso)
#### Post date: [December 30, 2017, 8:09am UTC](https://discourse.julialang.org/t/deprecation-error/8062/5 "2017-12-30T08:09:37Z")

</div>

> [@ihnorton](#):
>
> […] 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). […]

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”.

> [@ihnorton](#):
>
> [GitHub - timholy/Revise.jl: Automatically update function definitions in a running Julia session](https://github.com/timholy/Revise.jl) might help.

I don’t understand. What I am talking about is [stevengj’s post](https://github.com/JuliaLang/julia/pull/22763#issuecomment-314593417), [Jeff’s answer](https://github.com/JuliaLang/julia/pull/22763#issuecomment-314595010) and [ararslan’s reaction](https://github.com/JuliaLang/julia/pull/22763#issuecomment-314616901).

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):

> [@Liso](#):
>
> julia\> using Unicode
> 
> julia\> using Base.uppercase  
> julia\> Base.uppercase(args…; kwargs…) = Unicode.uppercase(args…; kwargs…)

> [@ihnorton](#):
>
> In the case of the special functions, they were mentioned in the release notes for 0.6:

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?

---

<div class="post-metadata">

### Author: ![Liso](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@Liso](https://discourse.julialang.org/u/Liso)
#### Post date: [December 30, 2017, 8:15am UTC](https://discourse.julialang.org/t/deprecation-error/8062/6 "2017-12-30T08:15:24Z")

</div>

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

---

<div class="post-metadata">

### Author: ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)
#### Post date: [December 30, 2017, 10:21am UTC](https://discourse.julialang.org/t/deprecation-error/8062/7 "2017-12-30T10:21:51Z")

</div>

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 😉.

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [December 30, 2017, 2:31pm UTC](https://discourse.julialang.org/t/deprecation-error/8062/8 "2017-12-30T14:31:31Z")

</div>

> [@Liso](#):
>
> But if majority core could not see problem with hard break (and call it deprecation) why to waste energy?

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:

> <https://github.com/JuliaLang/julia/pull/22763>
>
> This adds a new \`@deprecate\_moved name "newmodule"\` macro for functions moved ou…t of Base to external modules. More importantly, it makes it possible to import deprecated symbols from external modules without warnings/errors.
> 
> For example, you can now do:
> \`\`\`jl
> using QuadGK
> quadgk(sin, 0,1)
> \`\`\`
> and it will work without warnings, whereas in 0.6 you get \`WARNING: both QuadGK and Base export "quadgk"; uses of it in module Main must be qualified\` followed by \`ERROR: UndefVarError: quadgk not defined\`.
> 
> This actually extends an earlier version of the same idea implemented in fe3b08121d4ab3d929a1921e3beb0e360d2d329e, which only worked for \`@deprecate\_binding\` deprecations that involved renames of things in Base. See also the discussion in JuliaMath/FFTW.jl#21

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.

---

<div class="post-metadata">

### Author: ![ihnorton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ihnorton/32/26_2.png) [@ihnorton](https://discourse.julialang.org/u/ihnorton)
#### Post date: [December 30, 2017, 4:34pm UTC](https://discourse.julialang.org/t/deprecation-error/8062/9 "2017-12-30T16:34:24Z")

</div>

> [@Liso](#):
>
> This could not be excuse for mature well established language.

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

> [@Liso](#):
>
> deprecated.jl could import SpecialFunctions and Base.zeta could call SpecialFunctions.zeta (I see nor significant difficulty nor two copies of code)

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.

---

<div class="post-metadata">

### Author: ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)
#### Post date: [December 30, 2017, 7:01pm UTC](https://discourse.julialang.org/t/deprecation-error/8062/10 "2017-12-30T19:01:54Z")

</div>

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.

---

<div class="post-metadata">

### Author: ![Liso](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@Liso](https://discourse.julialang.org/u/Liso)
#### Post date: [December 30, 2017, 11:54pm UTC](https://discourse.julialang.org/t/deprecation-error/8062/11 "2017-12-30T23:54:55Z")

</div>

> [@ihnorton](#):
>
> 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.

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.
