Generic functions
All functions in Julia are generic, we can add new methods as long as the argument types are different from existing methods. If a generic function in Rust takes an argument T
, we can export it multiple times with different types.
use jlrs::prelude::*;
fn return_first_arg<T>(a: T, _b: T) -> T {
a
}
julia_module! {
become julia_module_tutorial_init_fn;
for T in [isize, f64] {
fn return_first_arg<T>(a: T, b: T) -> T;
}
}
julia> module JuliaModuleTutorial ... end
Main.JuliaModuleTutorial
julia> JuliaModuleTutorial.return_first_arg(1, 2)
1
julia> JuliaModuleTutorial.return_first_arg(1.0, 2.0)
1.0
julia> JuliaModuleTutorial.return_first_arg(1.0, 2)
ERROR: MethodError: no method matching return_first_arg(::Float64, ::Int64)
Closest candidates are:
return_first_arg(::Float64, ::Float64)
@ Main.JuliaModuleTutorial none:0
return_first_arg(::Int64, ::Int64)
@ Main.JuliaModuleTutorial none:0
It's not necessary to use this for-loop construction, it's also valid to repeat the export with the generic types filled in.
use jlrs::prelude::*;
fn return_first_arg<T>(a: T, _b: T) -> T {
a
}
julia_module! {
become julia_module_tutorial_init_fn;
fn return_first_arg(a: isize, b: isize) -> isize;
fn return_first_arg(a: f64, b: f64) -> f64;
}
A type parameter may appear in arbitrary positions, the next example requires enabling the complex
feature.
use jlrs::{data::layout::complex::Complex, prelude::*};
fn real_part<T>(a: Complex<T>) -> T {
a.re
}
julia_module! {
become julia_module_tutorial_init_fn;
for T in [f32, f64] {
fn real_part<T>(a: Complex<T>) -> T;
}
}
julia> module JuliaModuleTutorial ... end
Main.JuliaModuleTutorial
julia> JuliaModuleTutorial.real_part(ComplexF32(1.0, 2.0))
1.0f0
julia> JuliaModuleTutorial.real_part(ComplexF64(1.0, 2.0))
1.0