Previsibility on new releases to prepare teaching material (or ways to cope with the lack of...)?

Hello,

I am preparing tutorials for a course starting in September. We will be using Julia for relatively simple data analysis, and the students typically have not had much exposure to programming environments (neither language nor tooling). Because of that, I try to keep instructions as simple as possible, at the cost of hiding most of the Julia and package version “issues”. I have been bitten in the past by breaking changes in some packages (e.g. PrettyTables), where suddenly the prepared notebook did not work because the students installed Julia and the packages later than me and the “current” version was not the same. I know I could (should) have avoided that by using Project.toml files, but for the Julia version itself, I don’t know how to proceed, because - if my understanding is correct - the VS Code extension requires the “release” channel.

So currently, I am planning to say something like this:

  • install juliaup
  • add the release channel
  • if the release channel is not 1.12.7, add the 1.12.7 channel and make that the default

But that sounds a bit awkward. Is there a better solution?
More generally, I would be interested to know how others approach the “ever-changing version” problem when teaching courses for which lowering the entry barrier is key to student engagement.

Thanks!

The VS Code extension just needs the release channel to be installed, but it doesn’t have to be the default and you don’t have to use it for your stuff. We just run various things on it.

So you could for example tell all your students at the beginning of the class to do:

juliaup add release
juliaup add 1.12.7
juliaup default 1.12.7

And then you should be shielded from most surprises.

It sounds like that long-term-support release (LTS) might be appropriate for you and your class.Have you considered sticking to Julia 1.10 and using the lts channel?

Since you mention package versions – how do you provide the code to the students? Pluto for example would keep versions of packages in its notebook(s).

Alternatively give the students an environment – a folder with Project.tomland your resolved Manifest.toml and ask them to to Pky.activate(".")in that folder and then Pkg.instantiate() (not install or even update). That is basically what Pluto internally does.

I used Pluto a bit more but also made good experiences with the folder and a Project/Manifest combination.

(additionally to both previous tips of course)

Thank you all for answers. Yes, I have considered sticking to 1.10, especially after reading comments on compilation time increasing in later versions, but I am using 1.12 myself so I felt more comfortable “forcing” students to use it as well.

I think I will go with @davidanthoff’s suggestion, it’s not that bad after all to run juliaup 3 times.

For packages, I tend to use shared environments myself (by “theme”), so that’s what I was doing for students so far. I give them a script with Pkg.activate("MyCourse", shared=true)
a series of instructions like Pkg.add("SomePackage"), so their MyCourse shared environment has everything they need.

I realize that having “per directory” environments is probably better, but somehow I think it’s more cumbersome. I think it also come from a (wrong?) impression that activating and instantiating packages adds time, even if you have already instantiated the same package in some other directories. According to last year’s student feedback, the most frustrating apsect of Julia is installation / precompilation time. Of course I have no control on their hardware, network, etc., but installing Conda, IJulia, and Makie takes a fair bit of time on my (recent) machine on the university network, so I can imagine some students have a much worse experience if they do that at home on an aging laptop. My (naive?) assumption is that if they do that in a shared environment, it reduces the likeliness they will have to recompile something when they activate it for a new assignment (compared to “per directory” environments).

I think Pkg.add is generally “risky” in the kind of teaching environment you are doing, as you can never really know which versions of packages that will pull in, at the end of the day what exactly happens depends on when exactly the students run that command and which package author has published which version at that point.

One thing you could do is give them one Project.toml/Manifest.toml at the beginning of the semester that has all the packages that you will use throughout the semester in it.

And then you could just either tell them to put a copy of the two files (the originals) into the root whenever they start a new project/assignment/whatever, or tell them to put those files into a folder ~/.julia/environments/YOUR_CLASS_NAME (and then activate that shared env each time).

If you really stick to that env throughout the class, you should get absolutely minimal recompile etc

Thank you for your advice and for taking the time to answer. I guess I underestimated the possibility to get different environments by running Pkg.add at different points in time.

In most cases, I will distribute a directory structure with the files related to a project/assignment, so I could easily include a Project.toml/Manifest.toml in the root.Then, if I am correct, they will have to run Pkg.activate(".") each time, and Pkg.instantiate() once per project/assignment.

On the other hand, if I tell them to place the toml files in a shared environment, as you mention, they would have to activate it for each project/assignment, but instantiate the shared environment only once.

What I don’t understand is what the implications are in terms of recompilation - is there a risk that the first option (toml in the root of each project/assignment) would trigger more recompilation than the “shared environment” one? If not, my idea of a shared environment is probably not that good…

Small side question: if I distribute scripts that include activate and instantiate and they run them repeatedly, will the second, third, etc. instantiate trigger some process that could take a long time, or will Julia determine quickly that there is nothing to do?

Thanks again!