I have a question about workflows in Julia, or alternatively, some aspects of how the REPL can be used.
Allow me to start by describing how I am currently constrained.
I recognized that what I am about to describe will be considered by many here as a sub-optimal situation.
Here is my situation:
There is a server in the cloud somewhere which I have to connect to in order to do my work. It uses a strange version of ssh
, so while I can connect a single terminal session to this machine, what I cannot do is scp
files to and from it. (This will become important later.)
This server does not have git
installed, and it cannot be installed.
I am using a Windows machine to connect to this server. The Windows machine does have git installed. This is how I modify the repository, from the Windows PC.
There is a problem here. While I can make changes to the code in the repository, and push them from my Windows PC, how can I test the changes on the production server?
Here’s how we do it:
We copy the files one by one and paste them into an instance of vim
running on the production server.
This creates a very slow development loop. To test a change:
- Copy the file from VS Code on Windows.
- Exit the
julia
REPL in terminal session connected to remote prod server rm <target.jl>
vim <target.jl>
- Press
i
to enter insert mode - Press
CTRL+V
to paste buffer contents - Press
ESC
,:wq
to save the file and quitvim
- Reload the
julia
REPL julia> include("entryPoint.jl:)
julia> Main.EntryPointModule.main()
- Get feedback from the stack trace if it errors etc
- Modify file on Windows machine using VS Code
- Repeat
If I could cut out some of these steps, there is potentially a significant time saving to be obtained.
Since Julia is dynamic, and modules can be replaced dynamically, my thoughts are that there might be a way to copy and paste some code into the REPL, and replace the existing function or module definitions.
It would be simpler to do this for individual functions, rather than whole modules.
I tried something, but wasn’t able to get it to work.
Here’s a simple example to test:
Create this file
# MyModule.jl
module MyModule
export exampleFunction
function exampleFunction()
println("hello world")
end
end
Create a second file which uses the first
# MainModule.jl
module MainModule
include("MyModule.jl")
using Main.MainModule.MyModule
function main()
exampleFunction()
end
end
Use MainModule.jl
from the REPL
julia> include("MainModule.jl")
julia> Main.MainModule.main()
hello world
Example change
Imagine that we want to make the following change to exampleFunction
function exampleFunction()
println("goodbye world")
end
I would not expect copying and pasting just these lines into the REPL to work, because it will create a name exampleFunction
inside the Main
module, not the namespace Main.MainModule.MyModule
.
I tried to create it using this code, but this did not work.
module Main.MainModule.MyModule
function exampleFunction()
println("goodbye world")
end
end
The error is:
ERROR: ParseError:
# Error @ REPL[7]:1:12
module Main.MainModule.MyModule
# ╙ ── invalid identifier
So I tried something else
julia> module MainModule
module MyModule
function exampleFunction()
println("goodbye world")
end
end
end
WARNING: replacing module MainModule.
Main.MainModule
This also didn’t work, because it breaks this, which previously did work…
julia> Main.MainModule.main()
ERROR: UndefVarError: `main` not defined
It makes sense that this no longer works, because I have replaced the existing module named MainModule
with something which now does not contain the main()
function. (At least this is what seems to be happening.)
Is what I am trying to do possible?