I have an idea for a package and am wondering if anyone feels like implementing it.
MinimalWorkingExamples.jl
A package for Minimal Working Examples (MWE), where by using MinimalWorkingExamples the current REPL session
activates a temporary environment
catches all the using SomePackage
adds them to the environment
and finally runs the example
The idea isn’t to cover all edge cases but to be pretty simple as MWEs are expected to be. This will simply save the extra steps of activating a temporary environment and adding all the dependencies before trying out people’s MWEs. This tool should make it a lot easier for people to try out other people’s MWEs: just copy-paste into the REPL.
Of course, this would mean that people would need to have MinimalWorkingExamples.jl as a dependency in their main environment, and that all MWE code should begin with using MinimalWorkingExamples.
What do you think? Wanna build the next big thing in Julia?
The “catches all the using SomePackage” part I don’t get.
Would MinimalWorkingExamples load a jl source file and generate a REPL + environment out of this?
Would this be an user story you think of?
1.) Person A: write your normal MWE
2.) Person A: send jl file to person B
3.) Person B: open repl
4.) Person B: load MinimalWorkingExamples
5.) Person B: load jl file using MinimalWorkingExamples
6.) MinimalWorkingExamples: generate environment
7.) MinimalWorkingExamples: parse jl file for using or import or include
8.) MinimalWorkingExamples: add packages to enivronment
9.) MinimalWorkingExamples: run jl file (+ benchmark, export package versions; julia version, etc)
10.) Person B: modify jl file
11.) Person B: goto 5 if not happy
12.) Person B: Send new jl file and generated statistics / meta info to person A
13.) Person A is now person B
14.) Goto 3
No. The main use case would be code you want people to copy (from Discourse, Slack, Zulip, Discord, or anywhere really) and paste in the (existing or fresh) REPL. No files involved, just simple code. For more complicated (and thus perhaps not so minimal MWE) examples, ideally a Project and Manifest files will be involved, but that’s not the intended use of MinimalWorkingExamples.jl.
And to clarify the "catches all the using SomePackage ", I was hoping that some meta-programming magic could do that…
julia --project=$(mktemp -d) # does not work on windows
julia --eval "using Pkg;Pkg.activate(mktempdir())" # does not enter the REPL
Basically the new package would need to introduce a new REPL mode where packages are auto-installed on entering a using/import command.
1.) Open REPL
2.) Switch to “experiment” mode
2.1) New environment is generated and activated
3.) Enter code
3.1) Code is scanned for using and intercepted to install the packages
Not that it matters too much how that specific step is achieved, but
julia> import Pkg
julia> Pkg.activate(temp = true)
Activating new environment at `/tmp/jl_Rqkofw/Project.toml`
Or
]
(@v1.6) pkg> activate --temp
Activating new environment at `/tmp/jl_Z2tBdP/Project.toml`
(jl_Z2tBdP) pkg>
Well, if that’s the only way. But in the interest of keeping things as simple as possible for the user, it would be great if there was no need to switch to a new REPL mode. To have that work, we would not only need people to have a MinimalWorkingExamples dependency in their main environment, but also import it in every Julia session (in case they want to use the new REPL mode), which seems a bit too much to hope for.
The problem I see with this is that it would be an extra step in the REPL.
To my knowledge there is no temp switch for the julia binary.
The REPL mode is a bit much maybe, but I don’t see a good way to scanning the code without manually adding macros in the REPL. Maybe a lower level intercept would work, but I don’t have experience with Cassette.jl or similar packages.
I stand corrected though: Couldn’t the activation of the REPL mode be elicited by the user using MinimalWorkingExamples? So that would work really well.
Or even something as simple as this:
module MinimalWorkingExamples
import Pkg
Pkg.activate(temp = true)
for command in readlines()
if startswith(command, ["using", "import"])
pkgs = split(command)[2:end]
Pkg.add(pkgs)
end
@eval command # I suspect this is wrong, my meta-foo is worthless
end
end
One way would be to read in the whole example code at once. I just don’t know how to terminate readlines. Maybe an end of file command, but this seems to require additional knowledge of the user.
The other option would be to check if an input is a valid command. For this parsing the input and checking for errors might work. And if it is OK run it.
Still the problem remains on how to exit the input loop automatically.
If we don’t exit the loop it is almost like a REPL mode
Maybe print a message like: Please press “CTRL+D” if you finished the example code input.
> julia --project=$(mktemp -d)
mktemp : The term 'mktemp' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the
spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:19
+ julia --project=$(mktemp -d)
+ ~~~~~~
+ CategoryInfo : ObjectNotFound: (mktemp:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
I mean, there is no real reason to exit that loop, it will just wait for more lines to “eat”. It’s not like the user is going to want to maintain that session open/functional beyond testing that MWE.
Regarding the possible methods I like the REPL hooks introduces by @ericphanson , but without documentation it seems quite troublesome to get it working.
Oh, I was just assuming the user would close the terminal. Like I said, it’s not like they need to use that specific session for anything. So once they’re done playing around they can just close the terminal. But yea, this is just an implementation detail relevant to the readlines loop, which might not be ideal.
Once Pluto’s package management PR lands it might be the easiest way to get a self-contained reproducible environment, although a reactive one which might be a bit different than what some users are accustomed to. I think I saw also some code somewhere for storing Project/Manifests in regular Julia scripts too, but I can’t find it now.
Yeah, as I understand it you just type using PkgX and it installs it into a local environment that gets copied into the Pluto notebook file itself (and it doesn’t use packages from the global environment), so then the notebook file itself holds all the information about packages and versions etc. (It literally stores the Project.toml and Manifest.toml as a string inside the notebook! But it handles making use of those automatically, so it looks pretty smooth). My info is based on the cool PlutoCon talk on it, Built-In Package Management | Fons van der Plas | PlutoCon 2021 - YouTube.
Ah nice.
TBH, I imagined something a lot simpler (and perhaps less robust) that just alleviates the need to
activate a temp env
add the mentioned packages
The whole point of MWE is that they are as minimal as they can be while still showcasing some point/issue/behavior. So there shouldn’t need to be any compt issues or needs.