Usage of Array of abstract types in Julia
Asked Answered
L

3

6

I'm exploring Julia so I'm a newbie. Now I'm exploring its strongly typed features. What I'm realizing is that I can't see the usage of abstract types for arrays. Let me explain with an example:

Let's suppose that I would like to create a function which accepts arrays of reals, no matter its concrete type. I would use:

function f(x::Array{Real})
  # do something
end

This function can be never called without raising a f has no method matching f(::Array{Float64,1})

I would like to call f([1,2,3]) or f([1.,2.,3.]) as long as the type of the element is Real.

I've read that you could promote or convert the array (p.eg f(convert(Array{Real}, [1, 2, 3])) or so) but I see that way really non-dynamic and tedious.

Is there any other alternative rather than getting rid of the strongly typed behaviour?

Thanks.

Lobell answered 1/3, 2016 at 8:26 Comment(4)
You can define a parametric function: function f{T<:Real}(x::Array{T}). This would capture both f([1,2,3]) and f([1.,2.,3.]).Westbound
Just adding to @user3580870 comment: there is no performance penalty associated with parametric functions. It is an absolutely integral feature of Julia.Samoyedic
Yes, thanks for your comment, you are right. I was about to add this alternative as a "tedious alternative" as well but I finally regretted it. This solution doesn't satisfy me either because it can't be used for anonymous functions.Lobell
If speed is not an issue, you can define f(x::Array) and check @assert eltype(x)<:Real, first thing in the function.Westbound
D
8

To expand upon the solution by @user3580870, you can also use a typealias to make the function definition a little more succinct:

typealias RealArray{T<:Real} Array{T}
f(x::RealArray) = "do something with $x"

And then you can use the typealias in anonymous functions, too:

g = (x::RealArray) -> "something else with $x"
Delois answered 1/3, 2016 at 14:19 Comment(1)
Definitely for me it's the best solution. Thanks :)Lobell
B
4

Since there's been an updated since the orginal answer, the keyword typealias is gone so that the solution of @Matt B. would now be

const RealArray{T<:Real} = Array{T}
f(x::RealArray) = "do something with $x"

I'll just put this here for the sake of completeness ;)

Bloater answered 8/10, 2020 at 7:0 Comment(0)
T
0

You can do this explicitly using the <: subtype operator:

function f(x::Array)
    return zero.(x)
end

function f(x::Array{<:Real})
    return one.(x)
end

@show f([1, 2])
@show f([1.0, 2.0])
@show f([1im, 2im])

prints

f([1, 2]) = [1, 1]
f([1.0, 2.0]) = [1.0, 1.0]
f([1im, 2im]) = Complex{Int64}[0+0im, 0+0im]
Tasset answered 3/4, 2019 at 9:4 Comment(1)
Add some explanation on your answer.Yodle

© 2022 - 2024 — McMap. All rights reserved.