# Automatically parameterizing a type

**URL:** <https://discourse.julialang.org/t/automatically-parameterizing-a-type/15945>\
**Category:** Performance\
**Created:** [October 5, 2018, 7:20pm UTC](https://discourse.julialang.org/t/automatically-parameterizing-a-type/15945 "2018-10-05T19:20:42Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![fabgrei](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fabgrei/32/4214_2.png) [@fabgrei](https://discourse.julialang.org/u/fabgrei)\
**Post date:** [October 5, 2018, 7:20pm UTC](https://discourse.julialang.org/t/automatically-parameterizing-a-type/15945/1 "2018-10-05T19:20:42Z")

</div>

In order to achieve good performance one is supposed to use parametric types. Is there a way to do this automatically?

I want this

```julia
@parameterize struct Foo
   field1::Real
   field2::AbstractVector
   field3::Number
end

```

become

```julia
 struct Foo{T1 <: Real, T2 <: AbstractVector, T3 <: Number}
   field1::T1
   field2::T2
   field3::T3
end

```

I use huge types with many fields for model simulations and it becomes very tedious to write this out by hand.

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [October 7, 2018, 4:25am UTC](https://discourse.julialang.org/t/automatically-parameterizing-a-type/15945/2 "2018-10-07T04:25:12Z")

</div>

This feature could also be added to Parameters.jl. But it would also be nice to have this separately.

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [October 7, 2018, 4:48am UTC](https://discourse.julialang.org/t/automatically-parameterizing-a-type/15945/3 "2018-10-07T04:48:37Z")

</div>

Was a fun exercise:

```julia
macro params(struct_expr)
	name = struct_expr.args[2]
	fields = @view struct_expr.args[3].args[2:2:end]
	params = []
	for i in 1:length(fields)
		x = fields[i]
		if x isa Symbol
			T = gensym()
			push!(params, T)
			fields[i] = :($x::$T)
		end
	end
	if name isa Symbol && length(params) > 0
		struct_expr.args[2] = :($name{$(params...)})
	elseif name.head == :curly
		append!(struct_expr.args[2].args, params)
	else
		error("Unidentified type definition.")
	end

	esc(struct_expr)
end

```

```julia
julia> @params struct MyType
           a
           b::Int
           c
       end

julia> MyType{Int, Float64}(1, 1, 1.0)
MyType{Int64,Float64}(1, 1, 1.0)

```

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [October 7, 2018, 7:25am UTC](https://discourse.julialang.org/t/automatically-parameterizing-a-type/15945/4 "2018-10-07T07:25:58Z")

</div>

I realize the above is not exactly the requested feature so…here you go:

```julia
macro params(struct_expr)
   name = struct_expr.args[2]
   fields = @view struct_expr.args[3].args[2:2:end]
   params = []
   for i in 1:length(fields)
           x = fields[i]
           T = gensym()
           if x isa Symbol
                   push!(params, T)
                   fields[i] = :($x::$T)
           elseif x.head == :(::)
                   abstr = x.args[2]
                   var = x.args[1]
                   push!(params, :($T <: $abstr))
                   fields[i] = :($var::$T)
           end
   end
   if name isa Symbol && length(params) > 0
           struct_expr.args[2] = :($name{$(params...)})
   elseif name.head == :curly
           append!(struct_expr.args[2].args, params)
   else
           error("Unidentified type definition.")
   end

   esc(struct_expr)
end

```

```julia
julia> @params struct MyType
           a::Integer
           b
       end

julia> MyType(1,2)
MyType{Int64,Int64}(1, 2)

julia> MyType(1.0,2)
ERROR: MethodError: no method matching MyType(::Float64, ::Int64)
Closest candidates are:
  MyType(::##360<:Integer, ::##361) where {##360<:Integer, ##361} at REPL[2]:2
Stacktrace:
 [1] top-level scope at none:0

```

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [October 7, 2018, 10:33am UTC](https://discourse.julialang.org/t/automatically-parameterizing-a-type/15945/5 "2018-10-07T10:33:10Z")

</div>

Do you need them at all? I usually end up deleting those qualifiers anyway once I realise I need to use a unit, not Real, or that a tuple would do instead of the Vector. Unless you _really_ need the type checks.

Writing packages, I initially I went with safety and explicit type checks everywhere. But now I keep `struct` field types as loose as possible and give the user a little more rope to hang themselves with.

I’ve had a lot of hassles with overly restricted types blocking the use of Dual numbers or units in other peoples packages. Having to write a pull request to remove types is way more of a pain than not getting an immediate warning that you are using the wrong type. But opinions on this may vary.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [October 7, 2018, 12:20pm UTC](https://discourse.julialang.org/t/automatically-parameterizing-a-type/15945/6 "2018-10-07T12:20:31Z")

</div>

Concrete struct field types are critical for performance (if the struct is used in inner loops). It’s not just about safety.

See also [this explanation](https://discourse.julialang.org/t/problem-with-complex-rationals/9474/7) for why concrete fields matter.

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [October 7, 2018, 1:32pm UTC](https://discourse.julialang.org/t/automatically-parameterizing-a-type/15945/7 "2018-10-07T13:32:35Z")

</div>

Absolutely. But you don’t need `<: Real` etc for that, and it can be more of a pain than its worth.

I mean to do this:

```julia
 struct Foo{T1, T2, T3}
   field1::T1
   field2::T2
   field3::T3
end

```

But use better type variable names if you need documentation. Then it’s really not much extra writing and you can drop the macro.

---

<div class="post-metadata">

**Author:** ![fabgrei](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fabgrei/32/4214_2.png) [@fabgrei](https://discourse.julialang.org/u/fabgrei)\
**Post date:** [October 8, 2018, 8:07pm UTC](https://discourse.julialang.org/t/automatically-parameterizing-a-type/15945/8 "2018-10-08T20:07:44Z")

</div>

```julia
@params struct Foo
   field1
   field2
   field3
end

```

is quite convenient, even without being more specific on the types, isn’t it?

I often have types with 10 or more fields. In these cases I’d really like to avoid writing out everything by hand.

---

<div class="post-metadata">

**Author:** ![fabgrei](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fabgrei/32/4214_2.png) [@fabgrei](https://discourse.julialang.org/u/fabgrei)\
**Post date:** [October 8, 2018, 8:07pm UTC](https://discourse.julialang.org/t/automatically-parameterizing-a-type/15945/9 "2018-10-08T20:07:45Z")

</div>

Thanks, @mohamed82008, you solved my problem!

I’ve never worked with macros, so it would take a while to figure out how that works, though 😅

I opened an [issue](https://github.com/mauro3/Parameters.jl/issues/85#issue-367923295) with `Parameters.jl` linking to your solution. Would be great if this feature could be added to that package.

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [October 8, 2018, 8:15pm UTC](https://discourse.julialang.org/t/automatically-parameterizing-a-type/15945/10 "2018-10-08T20:15:41Z")

</div>

`@qstruct_fp` already does this [https://github.com/cstjean/QuickTypes.jl](https://github.com/cstjean/QuickTypes.jl)
