# Create custom units in Unitful

**URL:** <https://discourse.julialang.org/t/create-custom-units-in-unitful/102827>\
**Category:** General Usage\
**Tags:** question, unitful\
**Created:** [August 15, 2023, 1:03pm UTC](https://discourse.julialang.org/t/create-custom-units-in-unitful/102827 "2023-08-15T13:03:13Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tillmann\_Bosch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tillmann_bosch/32/52480_2.png) [@Tillmann\_Bosch](https://discourse.julialang.org/u/Tillmann_Bosch)\
**Post date:** [August 15, 2023, 1:03pm UTC](https://discourse.julialang.org/t/create-custom-units-in-unitful/102827/1 "2023-08-15T13:03:13Z")

</div>

Hey together!

Im creating custom units with Unitful and am stumbling across a difficulty for which I havent yet found a solution for. I created a little module in which I am able to define new unitful dimensions and create custom units:

```julia
module MyUnits

using Unitful
export @u_str

function create_unit(name::String)
	name = lowercase(name)

	Dimension = uppercasefirst(name) * "Dimension" |> Meta.parse
	DimensionQuote = uppercasefirst(name) * "Dimension"
	dimension = name * "Dimension" |> Meta.parse

	Unit = uppercasefirst(name) |> Meta.parse
	UnitQuote = uppercasefirst(name)
	unit = name |> Meta.parse
	UNIT = uppercase(name) |> Meta.parse

	return eval(
		quote
			@dimension $Dimension $DimensionQuote $dimension
			@refunit $Unit $UnitQuote $unit $Dimension true
			const $UNIT = Quantity{<:Real, $Dimension}
			export $UNIT, $Unit, $unit, $dimension, $Dimension
		end
	)
end

create_unit("tomate")
create_unit("salad")
create_unit("euro")

function __init__ ()
	Unitful.register(MyUnits)
end

end

```

This for now works fine. What I want to do with this is add units in form of vegetables like tomate, salad (later more), money like euro, and later many more very custom and unique dimesional units. In the create\_unit function I am defining multiple “namings”, which are fed into the @dimension and @refunit macros to name and define the new unitful dimensions and units. Then I export some of the names so I can use it lateron outside the package. There are some case conventions I use here for the namings which are not very relevant for my problem, like uppercase, firstuppercase, no uppercase and so on.

If I load this module, I can use my newly created units like:

```julia
price(e::EURO, t::TOMATE) = e/t
price(5u"Euro", 2u"Tomate") # 2.5 Euro Tomate^-1
5u"Euro/Tomate" * 7u"Tomate" # 35 Euro
isa(5u"Euro/Tomate" * 7u"Tomate", EURO) # true

```

So until here everything is fine. What I now would like to do is the following. I want to “typecheck” my calculations in the form of:

```julia
tom::TOMATE = 7u"Tomate"
cost::EURO = 3u"Euro"
tomatoprice::WHATTYPE = cost / tom

```

I want to define calculations and type check them by putting ::TYPE next to the resulting variable. This is just a basic example, lateron there will be many combined types flying around, which is actually my initial motivation to implement this kind of “typechecking” with Unitful.

So, what do I have to put into the missing space at WHATTYPE? Of course there shall be something like EURO/TOMATO, but how does it get created automatically, or how can I access it if already existing? I know that there is the Quantity type in Unitful, but I havent yet understood it very well and how to use it for this purpose.

Thanks very much for help here! I am enjoying Unitful, but am still at the beginning of my learning. If you have some critics on my module and code structures above, please let me know aswell. Im still somehow new to Julia too.

---

<div class="post-metadata">

**Author:** ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)\
**Post date:** [August 15, 2023, 1:10pm UTC](https://discourse.julialang.org/t/create-custom-units-in-unitful/102827/2 "2023-08-15T13:10:50Z")

</div>

I have not worked with Unitful.jl so I don’t know the answer but I can tell you how to check. Simply use `typeof` to ask Julia what the type is 🙂  
Like:

```julia
julia> typeof(cost/tom)

```

---

<div class="post-metadata">

**Author:** ![Tillmann\_Bosch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tillmann_bosch/32/52480_2.png) [@Tillmann\_Bosch](https://discourse.julialang.org/u/Tillmann_Bosch)\
**Post date:** [August 15, 2023, 1:20pm UTC](https://discourse.julialang.org/t/create-custom-units-in-unitful/102827/3 "2023-08-15T13:20:10Z")

</div>

Thanks for your quick answer! 🙂 I forgot to mention that I tried that but it doesnt seem to solve it for two reasons. First, if I do

```julia
typeof(1u"Euro/Tomate")

```

I get

```julia
Unitful.Quantity{Int64, EuroDimension TomateDimension^-1, Unitful.FreeUnits{(Euro, Tomate^-1), EuroDimension TomateDimension^-1, nothing}}

```

but

```julia
isa(1u"Euro/Tomate", Unitful.Quantity{Int64, EuroDimension TomateDimension^-1, Unitful.FreeUnits{(Euro, Tomate^-1), EuroDimension TomateDimension^-1, nothing}})

```

produces the error

```julia
syntax: missing comma or } in argument list

```

which I do not understand. I tried some similar things with the Quantity type thing, but it returned false.

But even if this would work, the Quantity… type is just too long to be used directly like that, so Im looking for a short and handy way of using quotient types in that sense.

---

<div class="post-metadata">

**Author:** ![sostock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sostock/32/5546_2.png) [@sostock](https://discourse.julialang.org/u/sostock)\
**Post date:** [August 15, 2023, 1:37pm UTC](https://discourse.julialang.org/t/create-custom-units-in-unitful/102827/4 "2023-08-15T13:37:52Z")

</div>

> [@Tillmann\_Bosch](#):
>
> So, what do I have to put into the missing space at WHATTYPE?

The `@derived_dimension` macro is useful for that:

```julia
@derived_dimension TomatoPrice EuroDimension/TomateDimension

```

This defines `TomatoPrice` (and `TomatoPriceUnits`, `TomatoPriceFreeUnits`) so that

```julia
tomatoprice::TomatoPrice = cost / tom

```

does what you want.

---

<div class="post-metadata">

**Author:** ![Tillmann\_Bosch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tillmann_bosch/32/52480_2.png) [@Tillmann\_Bosch](https://discourse.julialang.org/u/Tillmann_Bosch)\
**Post date:** [August 15, 2023, 1:44pm UTC](https://discourse.julialang.org/t/create-custom-units-in-unitful/102827/5 "2023-08-15T13:44:58Z")

</div>

Thanks much, that is a first step. Do you know if there is a automatic way of defining such derived dimensions for all dimensions I have created? Later I will for example have units like Container, Year, Shoes, etc and will want to “spontaneously” do

```julia
shoesPerContainerPerYear::SHOE/CONTAINER/YEAR = 100000u"Shoe" / (10u"Container"*1u"Year")

```

without having to explicitly define a derived dimension for that. Do you understand what I mean?

---

<div class="post-metadata">

**Author:** ![sostock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sostock/32/5546_2.png) [@sostock](https://discourse.julialang.org/u/sostock)\
**Post date:** [August 16, 2023, 8:03am UTC](https://discourse.julialang.org/t/create-custom-units-in-unitful/102827/6 "2023-08-16T08:03:38Z")

</div>

> [@Tillmann\_Bosch](#):
>
> First, if I do
> 
> ```julia
> typeof(1u"Euro/Tomate")
> 
> ```
> 
> I get
> 
> ```julia
> Unitful.Quantity{Int64, EuroDimension TomateDimension^-1, Unitful.FreeUnits{(Euro, Tomate^-1), EuroDimension TomateDimension^-1, nothing}}
> 
> ```
> 
> but
> 
> ```julia
> isa(1u"Euro/Tomate", Unitful.Quantity{Int64, EuroDimension TomateDimension^-1, Unitful.FreeUnits{(Euro, Tomate^-1), EuroDimension TomateDimension^-1, nothing}})
> 
> ```
> 
> produces the error
> 
> ```julia
> syntax: missing comma or } in argument list
> 
> ```

This is because the dimensions are printed as `EuroDimension TomateDimension^-1` (with a space instead of `*`, which isn’t valid Julia syntax) in the type parameters. You can instead write

```julia
Quantity{<:Real, EuroDimension/TomateDimension}

```

---

<div class="post-metadata">

**Author:** ![Tillmann\_Bosch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tillmann_bosch/32/52480_2.png) [@Tillmann\_Bosch](https://discourse.julialang.org/u/Tillmann_Bosch)\
**Post date:** [August 17, 2023, 9:44am UTC](https://discourse.julialang.org/t/create-custom-units-in-unitful/102827/7 "2023-08-17T09:44:35Z")

</div>

Oh ok, I wonder how I didnt try that out. That is now at least a worst case solution so to say, because it will still make my code kind of long if I always type `::Quantity{<:Real, ...}`, especially if many units are combined together, which will happen. But at least it gives a solution, thanks for that.

Ive been trying out right now to write some formating or macro to convert something like `EURO/TOMATE` into `Quantiy{<:Real, EuroDimension/TomateDimension`, such that it consistently extends to more combinations, like `EURO/TOMATE/CONTAINER`. Not yet successfull, also because of that `EuroDimension TomateDimension^-1` formating thing.

Do you see a simple way to do this?

---

<div class="post-metadata">

**Author:** ![Tillmann\_Bosch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tillmann_bosch/32/52480_2.png) [@Tillmann\_Bosch](https://discourse.julialang.org/u/Tillmann_Bosch)\
**Post date:** [August 17, 2023, 1:21pm UTC](https://discourse.julialang.org/t/create-custom-units-in-unitful/102827/8 "2023-08-17T13:21:32Z")

</div>

I found a workaround with which I may be able to do everyhing I want to do. Im doing the following:

```julia
module MyUnits

using Reexport
@reexport using Unitful
export @u_str, TT

TT(x) = Quantity{<:Real, x}

function create_unit(name::String)
	name = lowercase(name)

	DIMENSION = uppercase(name) |> Meta.parse
	DimensionQuote = uppercasefirst(name) * "Dimension"
	dimension = name * "Dimension" |> Meta.parse

	Unit = uppercasefirst(name) |> Meta.parse
	UnitQuote = uppercasefirst(name)
	unit = name |> Meta.parse

	return eval(
		quote
			@dimension $DIMENSION $DimensionQuote $dimension
			@refunit $Unit $UnitQuote $unit $DIMENSION true
			export $Unit, $DIMENSION
		end
	)
end

create_unit("tomato")
create_unit("euro")
create_unit("year")

function __init__ ()
	Unitful.register(MyUnits)
end

end

```

Then with the help of the `TT` function I can handyly do the following stuff:

```julia
using .MyUnits
isa(2.5u"Euro", TT(EURO)) # true
isa(4u"Euro/Tomato/Tomato", TT(EURO/TOMATO/TOMATO)) # true
price(e::TT(EURO), t::TT(TOMATO)) = e/t
price(2u"Euro", 8u"Tomato") # 0.25 Euro Tomato^-1
2u"Tomato"*5u"Euro/Tomato/Tomato"/3u"Euro" # 3.3333333333333335 Tomato^-1
tom::TT(TOMATO) = 7u"Tomato"
cost::TT(EURO) = 3u"Euro"
time::TT(YEAR) = 5u"Year"
tomatoprice::TT(EURO * YEAR / TOMATO / YEAR * TOMATO) = cost / 3.1*tom / time/tom*2*time # 1.935483870967742 Euro

```

And so on. So wrapping around this `TT` function is the very handy thing here. Final version would be to not need this function, but for now its working well for me.

If anyone has one idea how to build this without having to use such a helper function, I appreciate your comments! And also any further critics and how you find my approach here. Thanks!
