Julia: Parameters on functions

Created on 2 Aug 2017  路  15Comments  路  Source: JuliaLang/julia

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.

Most helpful comment

Or

julia> struct f{T} end

julia> f{T}() where {T} = T ? 1 : 1.0

On 0.7.

All 15 comments

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

Was this page helpful?
0 / 5 - 0 ratings

Related issues

yurivish picture yurivish  路  3Comments

m-j-w picture m-j-w  路  3Comments

ararslan picture ararslan  路  3Comments

arshpreetsingh picture arshpreetsingh  路  3Comments

wilburtownsend picture wilburtownsend  路  3Comments