OK, so if Base.return_types is frowned upon, what is the recommended solution to the problem of
"here's a function and a list of types; give me a container that can hold the results of applying this function to arguments of the type in the list" ? For this specific case, I don't think it's so bad to use Base.return_types anyway, since what I want to get at is actually, literally, "what will type inference give me from this function call?". The main argument against using Base.return_types outside of the compiler was that if the type inference algorithm changes it might break your code; in my case, I want my code to change with the inference algorithm, and keep giving me whatever the algorithm gives me. However, I eventually solved the problem differently <https://github.com/tlycken/Interpolations.jl/commit/18ab2653bc4bf38712918dc0b4dc2e43be9acee5#diff-d9844e94478d4dd20a05dff646887c5cR22>, eliminating the need to call Base.return_types entirely. // T On Friday, September 18, 2015 at 5:38:40 PM UTC+2, Tom Breloff wrote: > > Hi Michael... have you had a chance to look at OnlineStats yet? > > https://github.com/joshday/OnlineStats.jl > > On Fri, Sep 18, 2015 at 11:31 AM, Michael Francis <mdcfr...@gmail.com > <javascript:>> wrote: > >> Hmm - looking at that thread I struggle to agree with the outcome. >> >> Using this function was how I stumbled on the 20% speed issue with cov in >> stats base (due to type instability of the named arg). cov as it currently >> stands will return 'Any' whereas for an input set of two vectors of >> Float64. The code emitted for cov is not optimal due to the type >> instability. >> >> To have any chance of performance in streaming time series operators I >> need to be able to figure out what the return type of an arbitrary function >> is ( say +( Float64, Float64 ) -> Float64, I use this is used to define the >> record type for each subsequent observation. >> >> >> On Friday, September 18, 2015 at 10:04:46 AM UTC-4, Tim Holy wrote: >>> >>> It's considered a no-no to call Base.return_types from code: >>> https://github.com/JuliaLang/julia/pull/12292#issuecomment-124322950 >>> >>> However, my PR expunging it ( >>> https://github.com/JuliaLang/julia/pull/12409) >>> has not gotten any interest from those who objected, so I'm certain how >>> serious they are ;-). >>> >>> --Tim >>> >>> >>> On Friday, September 18, 2015 05:58:03 AM Michael Francis wrote: >>> > I should probably submit a PR to add - the extra info >>> > >>> > On Friday, September 18, 2015 at 8:50:35 AM UTC-4, Tomas Lycken wrote: >>> > > In this specific use case I don't need to handle anonymous >>> functions, so >>> > > `Base.return_types` will probably do just fine. >>> > > >>> > > It's not documented, though, so searching in the docs didn't turn >>> anything >>> > > up (and even though I guess it must have been used on this list, my >>> search >>> > > terms apparently weren't good enough to find it. >>> > > >>> > > Thanks! >>> > > >>> > > // T >>> > > >>> > > On Friday, September 18, 2015 at 2:42:47 PM UTC+2, Michael Francis >>> wrote: >>> > >> Yes in the sense it hands anon functions >>> > >> >>> > >> On Friday, September 18, 2015 at 8:41:16 AM UTC-4, Mauro wrote: >>> > >>> Is that better than Base.return_types ? >>> > >>> >>> > >>> On Fri, 2015-09-18 at 14:36, Michael Francis <mdcfr...@gmail.com> >>> > >>> >>> > >>> wrote: >>> > >>> > function returns(f, types) >>> > >>> > >>> > >>> > rt = [] >>> > >>> > if( !isdefined(f, :code) ) >>> > >>> > >>> > >>> > for x in Base._methods(f,types,-1) >>> > >>> > >>> > >>> > linfo = x[3].func.code >>> > >>> > (tree, ty) = typeinf(linfo, x[1], x[2]) >>> > >>> > push!(rt, ty) >>> > >>> > >>> > >>> > end >>> > >>> > >>> > >>> > else >>> > >>> > >>> > >>> > # It is a lambda, not a function, we also need the types of >>> the >>> > >>> >>> > >>> bound >>> > >>> >>> > >>> > # variables to evaluate the lambda corectly >>> > >>> > println( types ) >>> > >>> > linfo = f.code >>> > >>> > env = f.env >>> > >>> > (tree, ty) = typeinf(linfo, types, () ) >>> > >>> > push!(rt, ty) >>> > >>> > >>> > >>> > end >>> > >>> > # If there is a set of return types we default to any for now >>> > >>> > # this could be converted to a union type >>> > >>> > if( length( rt ) == 0 ) >>> > >>> > >>> > >>> > println( "Failed to resolve return type for $f, $types") >>> > >>> > >>> > >>> > elseif( length(rt) > 1 ) >>> > >>> > >>> > >>> > return Any >>> > >>> > >>> > >>> > else >>> > >>> > >>> > >>> > return rt[1] >>> > >>> > >>> > >>> > end >>> > >>> > >>> > >>> > end >>> > >>> > >>> > >>> > >>> > >>> > >>> > >>> > The above is what I do - which also copes with anon-functions >>> > >>> > >>> > >>> > On Friday, September 18, 2015 at 8:32:45 AM UTC-4, Tomas Lycken >>> wrote: >>> > >>> >> Given a function `foo(x,y)` and two *types* `TX` and `TY`, is >>> there a >>> > >>> >>> > >>> way >>> > >>> >>> > >>> >> I can get the inferred return type from calling `foo(x::TX, >>> y::TY)`? >>> > >>> >>> > >>> I want >>> > >>> >>> > >>> >> to do this in the compile part of a generated function, so I >>> don't >>> > >>> >>> > >>> have >>> > >>> >>> > >>> >> access to any values to actually call the function with. >>> > >>> >> >>> > >>> >> I have already verified that the function `foo` is type stable, >>> so >>> > >>> >>> > >>> the >>> > >>> >>> > >>> >> inferred type should be good enough for my purposes. >>> > >>> >> >>> > >>> >> Thanks, >>> > >>> >> >>> > >>> >> // T >>> >>> >