xxxxxxxxxxusing Pkg; Pkg.activate(mktempdir()); Pkg.add("PlutoUI"); using PlutoUICode structuring and interaction with other languages
Julia workflows
When working with Julia, we can choose between a number of workflows.
Pluto notebook
This ist what you see in action here. After calling pluto, you can start with an empty notebook and add cells.
Jupyter notebook
With the help of the package IJulia.jl it is possible to work with Jupyter notebooks in the browser. The Jupyter system is very complex and Pluto hopefully will be able to replace it.
Classical workflow
Use a classical code editor (emacs, vi or whatever you prefer) in a separate window and edit files, when saved to disk run code in a console window. With Julia, this workflow has the disadvantage that everytime Julia is started, the JIT needs to recompile the packages involved. So the idea is to not leave Julia, but to start a permanent Julia session, and include the code after each change.
The Revise.jl package allows to keep track of changed files used in a Julia session if they have been included via includet (t for "tracked"). In orde to make this work, one should add
if isinteractive()
try
@eval using Revise
Revise.async_steal_repl_backend()
catch err
@warn "Could not load Revise."
end
end
to the startup file ~/.julia/config/startup.jl and to run Julia via julia -i.
Revise.jl also keeps track of packages loaded. It also can be used with Pluto.
Modern workflow
Use an IDE (integrated development environment). Currently the best one for Julia is Visual Studio Code with corresponding extensions.
Structuring code: modules, files and packages
Complex code is split up into several files which can be included
Need to avoid name clashes for code from different places
Modules
Modules allow to encapsulate implementation into different namespaces
Main.workspace3.TestModulexxxxxxxxxxmodule TestModule function mtest(x) return "mtest: x=$(x)" end export mtestend"mtest: x=2"xxxxxxxxxxTestModule.mtest(2)Packages
Packages are modules searched for in a number of standard places
Each package is a directory named
Packagewith a subdirectorysrcThe file
Package/src/Package.jldefines a module namedPackageMore structures in a package:
Documentation resources
Test code
Metadada: Dependency description, UUID (Universal unique identifier)...
Default packages (e.g. the package manager Pkg) are always found in the
.juliasubdirectory of your home directoryThe package manager allows to add packages by finding them via the registry and downloading them.
"AbstractTrees"
"Adapt"
"ArgCheck"
"ArgParse"
"ArnoldiMethod"
"ArrayInterface"
"Artifacts"
"AssetRegistry"
"AutoHashEquals"
"AxisAlgorithms"
"BenchmarkTools"
"BinaryBuilder"
"BinaryBuilderBase"
"BrowseTables"
"Bzip2_jll"
"CSV"
"Cairo_jll"
"Calculus"
"Cascadia"
"Cassette"
"Zlib_jll"
"Zstd_jll"
"ghr_jll"
"libass_jll"
"libfdk_aac_jll"
"libpng_jll"
"libvorbis_jll"
"x264_jll"
"x265_jll"
"xkbcommon_jll"
xxxxxxxxxxreaddir("/home/fuhrmann/.julia/packages/")".github"
".gitignore"
".travis.yml"
"LICENSE.md"
"NEWS.md"
"Project.toml"
"README.md"
"docs"
"examples"
"src"
"test"
xxxxxxxxxxreaddir("/home/fuhrmann/.julia/packages/AbstractTrees/vOsoQ/")After importing a package via the
importstatement, all functions from a package are available via their name prefixed with the name of the package.The
usingstatement makes these names available without prefix.
Calling code from other languages
C
C language code has a well defined binary interface
intInt32floatFloat32doubleFloat64C arrays as pointers
Create a C source file:
"double cadd(double x, double y) \n{ \n return x+y; \n}\n"xxxxxxxxxxcadd_source="""double cadd(double x, double y) { return x+y; }"""xxxxxxxxxxopen("cadd.c", "w") do io write(io,cadd_source)end;Compile to a shared object (aka "dll" on windows) using the gcc compiler:
Process(`gcc --shared cadd.c -o libcadd.so`, ProcessExited(0))xxxxxxxxxxrun(`gcc --shared cadd.c -o libcadd.so`)Define wrapper function
caddusing the Juliaccallmethod(:cadd, "libcadd"): call cadd fromlibcadd.soFirst
Float64: return typeTuple
(Float64,Float64,): parameter typesx,y: actual data passed
At its first call it will load
libcadd.sointo JuliaDirect call of compiled C function
cadd(), no intermediate wrapper code
cadd (generic function with 1 method)xxxxxxxxxxcadd(x,y)=ccall((:cadd, "libcadd"), Float64, (Float64,Float64,),x,y)4.0xxxxxxxxxxcadd(1.5,2.5)Julia and many of its packages use this method to access a number of highly optimized linear algebra and other libraries
Python
Both Julia and Python are homoiconic language, featuring reflection
They can parse the elements of their own data structures
possibility to automatically build proxies for python objects in Julia
The PyCall package provides the corresponding interface:
xxxxxxxxxxPkg.add("PyCall"); using PyCallCreate a python source file:
"def add(x,y):\n return x+y\n"xxxxxxxxxxpyadd_source="""def add(x,y): return x+y"""xxxxxxxxxxopen("pyadd.py", "w") do io write(io,pyadd_source)end;PyObject <module 'pyadd' from '/home/fuhrmann/Wias/teach/scicomp/scicomp/pluto/pyadd.py'>xxxxxxxxxxpyadd=pyimport("pyadd")9.7xxxxxxxxxxpyadd.add(3.5,6.2)Julia allows to call almost any python package
E.g. matplotlib graphics - this is the python package behind PyPlot (there are more graphics options in Julia)
There is also a pyjulia package allowing to call Julia from python
Other languages
There are ways to interact with C++, R and other langugas
Interaction with Fortran via
ccall