After adding Flux package, why is it necessary to also add Zygote

This is a beginner/tooling question about packages, but if I post it there people will not know the particular packages.

The question: I want to use Zygote.@nograd, so I put
using Zygote
however this says that it is required to Pkg.add(“Zygote”) first.

I find this surprising, since Flux already depends on Zygote, so it must in some sense be added already - why does it need to be added “again”?

What version of Flux are you using? If it’s <0.10, it doesn’t use zygote.

This was on 0.10.3/Julia1.3.1

I’m not exactly sure about the nomenclature here, so I hope what I’m saying isn’t too confusing (or inaccurate), but adding Flux downloads Zygote, but it doesn’t put it into your Project.toml.
If you look at ] status, you’ll see all of the packages that you immediately added. You don’t see all of the packages that were also downloaded as their dependencies, only the ones that you added yourself. Those are the ones available with using. If you do add Zygote, the package gets registered in your Project.toml, but if you already have it as a dependency for Flux, it doesn’t get downloaded again.

2 Likes

that is helpful, Thank you

To add to @jstrube’s explanation: the idea is that your code doesn’t get to depend on transitive dependencies (i.e. dependencies of dependencies) without explicitly declaring it. After all, your dependencies’ dependencies are allowed to change without letting you know!

Therefore, if you also have a direct dependency on, in this case, Zygote, then you have to ]add it. But that’s purely administrative; it doesn’t get downloaded or pre-compiled again, and it will be the same version as what Flux is using.

Edit/Afterthought: in this case, you can actually also do using Flux.Zygote: @nograd without adding Zygote as your own dependency. That’s a nice way of showing that you are using Zygote only because it is Flux’s dependency.

I would treat this as an implementation detail, and add and use Zygote explicitly.

Technically, I disagree: If I’m using Zygote because Flux uses it, then I should allow Flux to change to another AD backend as long as it keeps on making the same API available to me under Flux.Zygote. edit: because I’m already not treating it as an implementation detail if I’m relying on it!

But in practice I agree: it’s rather impractical to be backwards compatible with the full implementation of one of your dependencies while switching dependencies, so Flux would just do a breaking release anyway (just like they did when introducing Zygote). So being technically correct probably has zero benefit in practice.

this makes sense (that it forces you to explicitly use transitive dependencies)