Moral of the story: Use less Python. Use declarative configuration and other langauges instead.
214 karma · joined March 11, 2021
Moral of the story: Use less Python. Use declarative configuration and other langauges instead.
Try JuliaC for compiling shared libraries if that is what you mean by a "module": https://github.com/JuliaLang/JuliaC.jl
That said Julia's original design focused on just-in-time compilation rather than ahead-of-time compilation, so the AOT process is still rough.
> I don't understand why there's so much friction between julia and python. You should be able to trivially throw a numpy array at julia and get a result back.
You can throw a numpy array at Julia and get a result back. See https://juliapy.github.io/PythonCall.jl/stable/juliacall/
Julia has OffsetArrays.jl implementing arbitrary-base indexing: https://juliaarrays.github.io/OffsetArrays.jl/stable/
The experience with this has been quite mixed, creating a new surface for bugs to appear. Used well, it can be very convenient for the reasons you state.
julia> A = collect(1:5)
5-element Vector{Int64}:
1
2
3
4
5
julia> B = OffsetArray(A, -1)
5-element OffsetArray(::Vector{Int64}, 0:4) with eltype Int64 with indices 0:4:
1
2
3
4
5
julia> A[1]
1
julia> B[0]
1 using TidierData, DataFrames
using PalmerPenguins: load
penguins = load()
@chain penguins begin
DataFrame
@drop_missing(body_mass_g)
@group_by(species, island)
@summarize(
body_weight_mean =
mean(body_mass_g),
body_weight_std =
std(body_mass_g)
)
show(_, allrows=true)
endHave you tried Polars? It really discourages the inefficient creation of intermediate boolean arrays such as in the code that you are showing.
> There's Julia -- it has serious drawbacks, like slow cold start if you launch a Julia script from the shell, which makes it unsuitable for CLI workflows.
Julia has gotten significantly better over time with regard to startup, especially with regard to plotting. There is definitely a preference for REPL or notebook based development to spread the costs of compilation over many executions. Compilation is increasingly modular with package based precompilation as well as ahead-of-time compilation modes. I do appreciate that typical compilation is an implicit step making the workflow much more similar to a scripting language than a traditionally compiled language.
I also do appreciate that traditional ahead-of-time static compilation to binary executable is also available now for deployment.
After a day of development in R or Python, I usually start regretting that I am not using Julia because I know yesterday's code could be executing much faster if I did. The question really becomes do I want to pay with time today or over the lifetime of the project.
While I understand that some have acclimated well to the prior situation and see no need to change their methods, is there really no objective self-awareness that perhaps having one fast tool over many tools may be objectively better?
Embrace. Extend. Extinguish.
It does take some asking around to discover the optimal Julia workflow with Revise.jl, PkgTemplates.jl, VSCode settings/debugger, Pluto.jl, but now it's probably my best development experience. Julia 1.10 improves much of this as well.
A large part of why I started using Julia is because calling into other languages through the C FFI is pretty easy and efficient. Most of the wrappers are a single line. If there is not existing driver support, I would pass the C headers through Clang.jl, which automatically wraps the C API in a C header.
https://github.com/JuliaInterop/Clang.jl
I most recently did this with libtiff. Here is the Clang.jl code to generate the bindings. It's less than 30 lines of sterotypical code.
https://github.com/mkitti/LibTIFF.jl/tree/main/gen
The generated bindings with a few tweaks is here:
https://github.com/mkitti/LibTIFF.jl/blob/main/src/LibTIFF.j...
I really do wish it were open source already though. I know they have laid out a roadmap for opening the source.
There are also some nice demonstrations showing Julia compiled to web assembly. https://tshort.github.io/WebAssemblyCompiler.jl/stable/examp...
julia> using StaticTools, StaticCompiler
julia> hello_world() = printf(c"Hello World\n")
hello_world (generic function with 1 method)
julia> compile_executable(hello_world, (), "./")
"~/hello_world"
shell> ./hello_world
Hello World
shell> du -h hello_world
16K hello_world
See https://github.com/brenhinkeller/StaticTools.jl for further details and limitations.For discovering methods you can do
julia> ?("hello", 1, 2.0)[TAB]
broadcast(f, x::Number...) @ Base.Broadcast broadcast.jl:844
readuntil(filename::AbstractString, args...; kw...) @ Base io.jl:520
...
See the Tab Completion section of the REPL documentation, https://docs.julialang.org/en/v1/stdlib/REPL/#Tab-completion .Julia has BigInt and Cint. Maybe there could be a more Pythonic implementation that scales between machine types and BigInt. That would not be hard to implement in Julia. I just have not found a good use case.
What I like about Julia is that I can do both the high level and low level in Julia. Abstract code becomes concrete due to late binding.
You can access Libc.malloc and Libc.free if needed. See GPUCompiler.jl
The effect system exists. If you can prove no side effects, eager finalization is also possible. That is the finalizer and deallocation will run deterministically. It's new though so effect analysis is a mostly manual affair at the moment.
I frankly would be concerned if the main contributors were not focused.
https://julialang.github.io/PackageCompiler.jl/stable/libs.h...
julia> versioninfo()
Julia Version 1.9.3
Commit bed2cd540a1 (2023-08-24 14:43 UTC)
Build Info:
Official https://julialang.org/ release
Platform Info:
OS: Linux (aarch64-linux-gnu)
CPU: 6 × Cortex-A55
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-14.0.6 (ORCJIT, cortex-a55)
Threads: 1 on 8 virtual cores