Reputation: 531
I'm writing a function that searches through a collection and collects the outputs of some user-supplied functions f
and g
applied to things it finds.
function search_map_collect(f::Function, g::Function)
output = []
# searching through the collection
# oh look we found an x and a y
push!(output, f(x, y))
# whoa, we even found a z
push!(output, g(x, y, z))
# end loopy stuff
return output
end
As the function is written, the output will always have type Array{Any,1}
, because that's the type of the empty array. However, it will often be the case that f
and g
always return values of the same type T
. In this case, a built-in function like map
would return an output of type Array{T,1}
, and I'd like my function to behave the same. Is there a nice way to do this?
If Julia supported function types with signatures, this would be easy. Unfortunately, it doesn't.
If I could easily predict when f
or g
would first be applied, I could initialize the output array as
output = [f(x_first, y_first)]
to set the type. Unfortunately, I can't predict the first application.
I realize I could do something horrific like
function complicated_collect(f::Function, g::Function)
output = Union{}[]
# searching through the collection
# oh look we found an x and a y
if isempty(output)
output = [f(x, y)]
else
push!(output, f(x, y))
end
# whoa, we even found a z
if isempty(output)
output = [g(x, y, z)]
else
push!(output, g(x, y, z))
end
# end loopy stuff
return output
end
but this makes the code much less readable, and it doesn't feel very efficient either.
Upvotes: 2
Views: 452
Reputation: 32351
If you know the return type when you call the function, you can add it as an argument.
function test1(t::Type, f::Function)
output = t[]
for x in 1:5
push!( output, f(x) )
end
output
end
test1( Float64, exp )
@code_warntype test1(exp)
Since it is type-stable, it should be more efficient than using the type of the first element found.
Upvotes: 5