Is it possible to implement an interface on a simple custom type so that many common functions will work on it? I’m trying to improve my knowledge of Julia. Let’s say we have the following simple custom type.
mutable struct interfaceTest
value::Int
x::Bool
theAnswer::Bool
function interfaceTest(val::Float64)
interfaceTest(Int(val))
end
function interfaceTest(val::Int)
value = val
x = val > 10
theAnswer = val == 42
new(value,x,theAnswer)
end
end
x = [3,5,48,30,2,2,2,42,21,15,12]
y = interfaceTest.(x)
y.value is the important factor, the rest are derived values. I would like to use simple functions like mean, unique, minimum, and maximum. It’s simple enough to extend each function but it would be very practical to have one way of doing it all at once.
Using the interfaces section of the manual I tried this:
function Base.iterate(test::interfaceTest, state=1)
state > 1 ? nothing : (test.value, state+1)
end
Testing unique resulted in the same result, even though there are duplicate values in the original data set, it returned every of the interfaceTest values as unique.
That is because these “duplicate values” are actually unique, i.e., they are not equal to each other:
julia> a = interfaceTest(2)
interfaceTest(2, false, false)
julia> b = interfaceTest(2)
interfaceTest(2, false, false)
julia> a == b
false
This is because == falls back to === which returns false because they have different addresses in memory. You need to either implement a custom == method or turn interfaceTest into a non-mutable struct to fix this.
In order to get the other functions (like maximum) to work, you would need to implement max, +, etc. Iteration does not help here.
julia> struct A
x::Float64
end
julia> using Statistics
julia> Statistics.mean(avec::AbstractVector{A}) = mean(a.x for a in avec)
julia> avec = A.(x)
3-element Vector{A}:
A(1.0)
A(2.0)
A(3.0)
julia> mean(avec)
2.0
To get mean to work without defining it explicitly, you would need to define the operations:
julia> import Base:+,-,/
julia> +(x::A,y::A) = x.x + y.x
+ (generic function with 191 methods)
julia> /(x::A,y) = x.x/y
/ (generic function with 108 methods)
julia> +(x,y::A) = x + y.x
+ (generic function with 192 methods)
julia> mean(avec)
2.0