Type parameters by default?

Hi everyone,

I’ve noticed a pattern in my Julia code and I wondered if it would make sense to have some compiler technology to automatically add type parameters for fields that have no explicit type.

For example, consider a view type on top of an array:

struct View
  arr
  ind
end

Base.getindex(v::View, i) = getindex(v.arr[ind[i]])

If we just add parametric types as in:

struct View{A,I}
  arr::A
  ind::I
end

The code using View becomes much faster as Julia is aware of the type of the fields as opposed to the default type Any. Would it make sense to change this behavior where the default Any type is actually replaced by a type parameter? Is there a major downside to this feature? I feel that it would make code much cleaner by default without compromising performance.

Perhaps my question is, what is the rationale for the default field type Any if it produces slow code?

1 Like

The downside is that compilation time would increase. Also, error messages would become much longer with all the type parameters (try DiffEq errors). And it is a breaking change. Thus I don’t think it would fly.

Note that you could achieve this with a macro. Alternatively, just use named tuples. Which are essentially this feature but without a name. Note that Parameters.jl has some features which are somewhat related: @deftype and @with_kw applied to NamedTuples.

2 Likes

This could have been a reasonable design choice (ask for Any if you want that, otherwise the field is parametrized implicitly), but given that the change would be breaking this is unlikely to happen.

I would follow @mauro3’s suggestion and have a macro

@implicittypes struct Foo
    a::T
    b
end

that expands to something like

struct Foo{T,S1}
    a::T
    b::S1
end

where S1 etc is generated not to conflict with other type parameters. It is a nice exercise with

https://github.com/FluxML/MacroTools.jl

3 Likes

There’s one such macro in QuickTypes.jl

# `_fp` (for Fully Parametric) automatically adds type parameters. For example:
@qstruct_fp Plane(nwheels, weight::Number; brand=:zoomba)
# is equivalent to `@qstruct Plane{T, U <: Number, V}(nwheels::T, weight::U; brand::V=:zoomba)`
# For even greater specialization, see `?@qstruct_np`.
5 Likes

Yeah, it would have been an interesting choice for performance I guess.