Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

type inference does not work with closures #9248

Closed
mauro3 opened this issue Dec 4, 2014 · 7 comments
Closed

type inference does not work with closures #9248

mauro3 opened this issue Dec 4, 2014 · 7 comments

Comments

@mauro3
Copy link
Contributor

mauro3 commented Dec 4, 2014

In below example the return type is only inferred when T is passed into the function but not when it's passed in through a closure (both for 0.3.2 and 0.4):

T = Float64
g1(x) = convert(T, x)
g11() = x
let T=T # to see whether let helps...
    g11(x) = convert(T, x)
end
g2(x,T) = convert(T, x)

@code_typed g1(5)      # inferred return type Any
@code_typed g11(5)     # inferred return type Any
@code_typed g2(5,T)    # inferred return type Float64

Now that all objects can be callable it could be pretty natural to use these "extra functions" like normal function, i.e. as closures. A contrived example:

immutable U1{S} end
call{S}(u::U1{S}, x) = convert(S,x)

u1int = U1{Int}()
f(x) = u1int(x) + 5
@code_typed f(5) # cannot infer return type Int

# However:
g(T) = U1{T}()
@code_typed g(Int)  # this infers the type correctly though, why?

Issue #175 is the only one I found which references type inference and closures.

@ihnorton
Copy link
Member

ihnorton commented Dec 4, 2014

See #1864

@mbauman
Copy link
Member

mbauman commented Dec 4, 2014

In this case, const T = Float64 fixes it. It's because the global T might change, so there's no way for inference to be sure what the return type would be:

julia> T = Float64
Float64

julia> g1(x) = convert(T, x)
g1 (generic function with 1 method)

julia> g1(1)
1.0

julia> T = Float16
Float16

julia> g1(1)
float16(1.0)

@JeffBezanson
Copy link
Member

See also #4428

@JeffBezanson
Copy link
Member

Also #8870 #524

@mauro3
Copy link
Contributor Author

mauro3 commented Dec 4, 2014

Thanks for looking into this. One observations though following @mbauman comment. I thought that if I wrap the functions inside a function it should have the same effect as declaring const T:

function uu(T)
    g1(x) = convert(T, x)
    g11() = x
    g11(x) = convert(T, x)

    g2(x,T) = convert(T, x)
    return g1, g11, g2
end
T = Float64
g1, g11, g2 = uu(T)


@code_typed g1(5)      # inferred return type Any
@code_typed g11(5)     # inferred return type Any
@code_typed g2(5,T)    # inferred return type Float64

But Julia still can't infer the return types, shouldn't that work?

@JeffBezanson
Copy link
Member

I think that's due to a specialization heuristic. If you use function uu(T::Type) it infers more specific types.

@mauro3
Copy link
Contributor Author

mauro3 commented Dec 4, 2014

Yes that works. Before posting above I tried with function uu(T::DataType) which didn't do anything.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants