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 
>>>
>>>
>

Reply via email to