Now that the where
syntax is used for typing the arguments of parametric functions, that leaves open the possibility for parameters on functions to be useful.
f{T}(t,u) = T
f{true}(1,2)
Parameters on functions are already a thing for inner constructors, but this would be a nice way to be able to type-stably set options without resorting to things like Val{true}
or requiring hyperpurity + Base.@pure
.
This would be equivalent to something like this?
julia> struct f{T}
function f{T}() where T
if T
return 1
else
return 1.0
end
end
end
julia> @code_warntype f{true}()
...
Body:
begin # line 4:
return 1 # line 6:
end::Int64
julia> @code_warntype f{false}()
....
Body:
begin
goto 3 # line 4:
3: # line 6:
return 1.0
end::Float64
Yes, it's exactly that. You can currently make this feature work by "abusing" inner functions, but I would like to see this get a nicer syntax since I find being able to easily throw compile-time constants into functions very useful.
Since f{T}(t,u) = T
will mean "add a method to f{T}
for the value of T
in this scope, that can't be the syntax. However, f{T}(t,u) where {T} = T
when f
is undefined doesn't mean anything, so it could potentially "auto-create" the f
struct for you with the given constructor. However, that seems a little error prone, and would be kind of bad unless we also require explicit qualification of imported function names for extension (which I feel we should do).
BTW, you don't need inner functions for this.
struct f{T} end
(::Type{f{T}})() where {T} = T ? 1 : 1.0
works just as well.
Or
julia> struct f{T} end
julia> f{T}() where {T} = T ? 1 : 1.0
On 0.7.
Is it correct that there is no way to specialize on f
when used as a higher order "function" since e.g. f{false}
is just a DataType
?
this would be a nice way to be able to type-stably set options
Type stability isn't a property of syntax. But note that f{true}
is also still one character longer than the current equivalent expression f_true
(the parameter needs to be a literal expression or it wouldn't have been type-stable) and is just as bad at conveying meaning.
Is it correct that there is no way to specialize on f when used as a higher order "function"
Unless I'm misunderstanding, no, you can still specialize on it. A method can be specialized on ::f{false}
or ::Type{f{false}}
.
It seems to me that we already have the capability requested in the OP. The syntax suggested by @yuyichao does it.
It seems to me that we already have the capability requested in the OP. The syntax suggested by @yuyichao does it.
Are you suggesting that should be taken as the canonical way to do it, documented, and closed? Or would a simplified syntax be on the table?
What I was thinking was this:
julia> struct f{T} end
julia> f{T}() where {T} = T ? 1 : 1.0
julia> struct F{T}
f::T
end
julia> func(F) = F.f()
func (generic function with 1 method)
julia> func(F(f{false}))
1.0
julia> @code_warntype func(F(f{false}))
Variables:
#self#::#func
F::F{DataType}
Body:
begin
return ((Core.getfield)(F::F{DataType}, :f)::DataType)()::Any
end::Any
but I think you need to wrap it in Type
like you say
Ah, I see. Yes, you can add a definition like this one: https://github.com/JuliaLang/julia/blob/68b0e40ba7ab9ce24dcaede21ce7e94873b4d7f7/base/generator.jl#L38 where needed.
Feel free to propose a syntax for this, but IIUC it would just be a matter of avoiding struct f{T} end
? Seems like it might be more complexity than it's worth.
Yeah, I guess it's not all that bad. Thanks for the input. At least now I can point to this if anyone asks where this syntax comes from 馃憤 .
but IIUC it would just be a matter of avoiding struct f{T} end?
It would also be a different way of representing Functions, since currently they are values, not types.
Changing that will mean apply_type
will be able to return non-type. That sounds like a pretty big breaking change...
Most helpful comment
Or
On 0.7.