# String macro to simplify type declarations with units

**URL:** <https://discourse.julialang.org/t/string-macro-to-simplify-type-declarations-with-units/47292>\
**Category:** General Usage\
**Tags:** unitful\
**Created:** [September 25, 2020, 10:34pm UTC](https://discourse.julialang.org/t/string-macro-to-simplify-type-declarations-with-units/47292 "2020-09-25T22:34:42Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![MartinOtter](https://avatars.discourse-cdn.com/v4/letter/m/87869e/32.png) [@MartinOtter](https://discourse.julialang.org/u/MartinOtter)\
**Post date:** [September 25, 2020, 10:34pm UTC](https://discourse.julialang.org/t/string-macro-to-simplify-type-declarations-with-units/47292/1 "2020-09-25T22:34:43Z")

</div>

I am trying to simplify the declaration of struct variables that have units with a string macro. This works:

```julia
using Unitful

macro Float64_str(str)
    return :( typeof(Float64(1.0)*@u_str($str)) )
end

mutable struct Data1
    length::Float64"m"
end

d1 = Data1(2.0u"mm")
@show d1.length

```

I do not manage to get a similar approach for a parameterized type.

The goal is to implement this code fragement:

```julia
using Unitful

mutable struct Data2{Float}
    length::Quantity{Float, dimension(u"m"), typeof(u"m")} 
end

d2 = Data2{Float64}(2.0u"mm")
@show d2.length

```

The above code fragement works. I would like to get it in a more readable form by using again a string macro:

```julia
using Unitful

macro Float_str(str)
    return :( Quantity{Float, dimension(@u_str($str)), typeof(@u_str($str))} )
end

mutable struct Data3{Float}
    length::Float"m" 
end

d3 = Data3{Float64}(2.0u"mm")
@show d3.length

```

However, this code fragement gives an error:

```julia
UndefVarError: Float not defined

```

Help is appreciated.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [September 25, 2020, 10:50pm UTC](https://discourse.julialang.org/t/string-macro-to-simplify-type-declarations-with-units/47292/2 "2020-09-25T22:50:21Z")

</div>

String macro is likely the wrong approach. You should simply use a function like `f(a, b) = Quantity{a, dimension(b), typeof(b)}`.

As for why the macro is not working, you are assuming the name of the type parameter (which is REALLY bad for readability) and if you really want to do that, you have to pretend it is user input by escaping the `Float` symbol.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [September 25, 2020, 10:55pm UTC](https://discourse.julialang.org/t/string-macro-to-simplify-type-declarations-with-units/47292/3 "2020-09-25T22:55:29Z")

</div>

Besides @yuyichao’s points, there’s a typo in your second string macro.

```julia
macro Float_str(str)
    return :( Quantity{Float, dimension(@u_str($str)), typeof(@u_str($str))} )
end

```

should be

```julia
macro Float_str(str)
    return :( Quantity{Float64, dimension(@u_str($str)), typeof(@u_str($str))} )
end

```

---

<div class="post-metadata">

**Author:** ![MartinOtter](https://avatars.discourse-cdn.com/v4/letter/m/87869e/32.png) [@MartinOtter](https://discourse.julialang.org/u/MartinOtter)\
**Post date:** [September 25, 2020, 11:15pm UTC](https://discourse.julialang.org/t/string-macro-to-simplify-type-declarations-with-units/47292/4 "2020-09-25T23:15:56Z")

</div>

> String macro is likely the wrong approach. You should simply use a function like `f(a, b) = Quantity{a, dimension(b), typeof(b)}` .

Thanks. This proposal works and is a more compact representation:

```julia
using Unitful

quantity(a,b) = Quantity{a, dimension(b), typeof(b)} 

mutable struct Data4{Float}
    length::quantity(Float,u"m")
end

d4 = Data4{Float64}(2.0u"mm")
@show d4.length

```

> As for why the macro is not working, you are assuming the name of the type parameter (which is REALLY bad for readability) and if you really want to do that, you have to pretend it is user input by escaping the `Float` symbol.

I did not get this suggestion to work. Maybe I misunderstood you (I used `esc(Float)` instead of `Float`):

```julia
using Unitful

macro Float_str(str)
    return :( Quantity{esc(Float), dimension(@u_str($str)), typeof(@u_str($str))} )
end

mutable struct Data3{Float}
    length::Float"m" 
end

d3 = Data3{Float64}(2.0u"mm")
@show d3.length

```

The above code fragement gives the same error.

(Your first proposal is clearer from a computer science point of view. If there are many declarations with units, the form `length::Float"m"` is nicer to read as `length::quantity(Float,u"m")`)

---

<div class="post-metadata">

**Author:** ![MartinOtter](https://avatars.discourse-cdn.com/v4/letter/m/87869e/32.png) [@MartinOtter](https://discourse.julialang.org/u/MartinOtter)\
**Post date:** [September 25, 2020, 11:19pm UTC](https://discourse.julialang.org/t/string-macro-to-simplify-type-declarations-with-units/47292/5 "2020-09-25T23:19:21Z")

</div>

> Besides @yuyichao’s points, there’s a typo in your second string macro. […]

No, this is not a typo: The goal is to use the type defined as parameter in the struct `struct Data3{Float}`, so using `Float` in the macro and not a concrete type, such as `Float64`.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [September 25, 2020, 11:36pm UTC](https://discourse.julialang.org/t/string-macro-to-simplify-type-declarations-with-units/47292/6 "2020-09-25T23:36:36Z")

</div>

> [@MartinOtter](#):
>
> No, this is not a typo: The goal is to use the type defined as parameter in the struct `struct Data3{Float}` , so using `Float` in the macro and not a concrete type, such as `Float64` .

Apologies, yes I had a silly moment there.

> [@MartinOtter](#):
>
> I did not get this suggestion to work. Maybe I misunderstood you (I used `esc(Float)` instead of `Float` ):

He means you should interpolate `esc(:Float)` into the expression. e.g.

```julia
julia> using Unitful

julia> macro Float_str(str)
           :(Quantity{$(esc(:Float)), dimension(@u_str($str)), typeof(@u_str($str))})
       end
@Float_str (macro with 1 method)

julia> mutable struct Data3{Float}
           length::Float"m"
       end

julia> d3 = Data3{Float64}(2.0u"mm")
Data3{Float64}(0.002 m)

```

But yeah, prt of why I got confused is that this macro is very specialized, it’s written _assuming_ that the user has defined a variable `Float` outside of the macro, which is usually a bad idea.

---

<div class="post-metadata">

**Author:** ![tomerarnon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomerarnon/32/3170_2.png) [@tomerarnon](https://discourse.julialang.org/u/tomerarnon)\
**Post date:** [September 26, 2020, 12:08am UTC](https://discourse.julialang.org/t/string-macro-to-simplify-type-declarations-with-units/47292/7 "2020-09-26T00:08:02Z")

</div>

> [@MartinOtter](#):
>
> ```julia
> mutable struct Data4{Float}
> length::quantity(Float,u"m")
> end
> 
> ```

It’s nicer for readability (and more idiomatic) to write this as

```julia
mutable struct Data4{T <: AbstractFloat}
    length::quantity(T, u"m")
end

```

if you intend to limit the type to floats. And if you don’t intend to have that limitation, to simply leave `T` as untyped.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [September 26, 2020, 12:58am UTC](https://discourse.julialang.org/t/string-macro-to-simplify-type-declarations-with-units/47292/8 "2020-09-26T00:58:04Z")

</div>

> [@MartinOtter](#):
>
> (I used `esc(Float)` instead of `Float` ):

I said escaping the `Float` **symbol**

The symbol is represented as a literal `Float` currently and you need to replace it with the `esc` of the symbol (i.e. `esc(:Float)`). To get it in the expression, use `$(...)` to splice that in, i.e. replace `Float` with `$(esc(:Float))`.

* * *

edit: i.e.

> [@Mason](#):
>
> He means you should interpolate `esc(:Float)` into the expression. e.g.

---

<div class="post-metadata">

**Author:** ![MartinOtter](https://avatars.discourse-cdn.com/v4/letter/m/87869e/32.png) [@MartinOtter](https://discourse.julialang.org/u/MartinOtter)\
**Post date:** [September 26, 2020, 10:05am UTC](https://discourse.julialang.org/t/string-macro-to-simplify-type-declarations-with-units/47292/9 "2020-09-26T10:05:46Z")

</div>

**Thanks very, very much for all your suggestions**. My questions are resolved. Let me summarize:

The Julia idiomatic way is

```julia
using Unitful

Quantity(a,b) = Quantity{a, dimension(b), typeof(b)} 

mutable struct Data4{Float <: AbstractFloat}
    length::Quantity(Float,u"m")
end

d4 = Data4{Float64}(2.0u"mm")
@show d4.length

```

Nicer to read, but hard to understand the implementation behind it with the (bad) assumption that a type `Float` is defined outside of the macro (so the macro only works under this assumption):

```julia
using Unitful 

macro Float_str(str)
    return :( Quantity{$(esc(:Float)), dimension(@u_str($str)), typeof(@u_str($str))} )
end

mutable struct Data3{Float <: AbstractFloat}
    length::Float"m"  
end

d3 = Data3{Float64}(2.0u"mm")
@show d3.length

```

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [September 26, 2020, 1:18pm UTC](https://discourse.julialang.org/t/string-macro-to-simplify-type-declarations-with-units/47292/10 "2020-09-26T13:18:37Z")

</div>

Yes that’s correct. The second approach is also only bead because you want to make the macro name match the type parameter name. Making it `@quantity(Float, "m")` or `quantity"Float,m"` would not have this issue. (though for the second version you’d have to do some parsing with the string macro, which is basically true for all string macros…)

---

<div class="post-metadata">

**Author:** ![MartinOtter](https://avatars.discourse-cdn.com/v4/letter/m/87869e/32.png) [@MartinOtter](https://discourse.julialang.org/u/MartinOtter)\
**Post date:** [October 23, 2020, 1:41pm UTC](https://discourse.julialang.org/t/string-macro-to-simplify-type-declarations-with-units/47292/11 "2020-10-23T13:41:05Z")

</div>

For your information: I opened an [issue in Unitful.jl](https://github.com/PainterQubits/Unitful.jl/issues/385) and asked to introduce the function `quantity(FloatType, unit)` into Unitful.
