# Dimensionless Units and Quantities¶

Every dimension has a variety of units available to measure its quantities. This is no less true for the “null” dimension! Example units include “dozen”, “score”, “percent”, and others. We call these units (and their quantities) “dimensionless”.

One big difference (compared to units of other dimensions) is that the magnitudes of *dimensionless*
units are *objectively meaningful*. Recall that for, say, length-dimensioned units, there is no
such thing as “the” magnitude of `Feet`

. We can choose any number we like, as long as it’s 12 times
the magnitude of `Inches`

. By contrast, `Percent`

has a definite magnitude: it’s 1/100.

`Unos`

: the “unit 1”¶

Dimensionless units are special, but one is more special still. Literally, *one* — the
dimensionless *unit* whose *magnitude* is 1. It is the only unit equal to its own square, and the
only unit whose quantities are completely and unambiguously interchangeable with raw numbers.

In our library, we named this unit “unos”, after an SI proposal from the 1990s. Although
the proposal failed, the concept turns out to suit software libraries much better than scientific
prose. It is short, greppable, and reasonably intuitive. It also lets us enter and exit the library
boundaries in just the same way as for other units: `q = unos(x)`

turns a numeric value `x`

into
a Quantity `q`

, and `q.in(unos)`

retrieves the raw number.

This is particularly useful when working with *non- unos* dimensionless units. For example: say we
wanted to “express

`0.75`

as a quantity of `percent`

”. Instead of trying to remember whether to
multiply or divide by 100, we can simply write `x = unos(0.75).as(percent)`

. And if we have
something that’s already a `percent`

, but we want its “true” value, we can simply write
`x.in(unos)`

.## Exact cancellation and types¶

Sometimes a computation exactly cancels all units (like the ratio of two lengths, each measured in
`Feet`

). As a units library, we have two options: return a Quantity of `Unos`

, or a raw number.
Presently, we opt for the latter; here is why.

Users generally tend to expect the result of a perfectly unit-cancelling expression to behave
exactly like a raw number, in *every* respect. Although a `Quantity<Unos, T>`

implicitly converts
to `T`

, this conversion turns out to get triggered in only a subset of use cases; many edge cases
remain. The only way to *perfectly* mimic a raw number is to return one.

The downside is that this incurs some complexity. This mainly impacts *generic* code, where we
can’t know whether a product or quotient of Quantities is a Quantity, or a raw number. People
writing generic code are generally more advanced users, and thus better able to work around this
inconsistency. For example, one could write an `ensure_quantity(T x)`

function template, which
returns `unos(x)`

in the generic case, but has an overload for when `T`

matches `Quantity<U, R>`

that simply returns `x`

.

We may someday be able to improve the ergonomics of `Quantity<Unos, T>`

to the point that we’d feel
comfortable returning it, thus making the library more consistent. However, returning a raw number
feels like the right compromise solution for us to start with.

Note

For results that are dimensionless but *not* “unitless”, we **always** return a Quantity.

For example, `milli(seconds)(50) * hertz(10)`

produces a numeric value of `50 * 10 -> 500`

, in
a dimensionless unit whose magnitude is 1 / 1000. This is equivalent to a raw numeric value
of 1 / 2 — but it’s not the library’s place to decide how or when to perform the lossy
conversion of this integral Quantity. Rather, the library’s job is to safely hold the obtained
numeric value of `500`

. The Magnitude attached to the Quantity is what lets us do so.

## Other dimensionless units and implicit conversions¶

A common choice among units libraries is to support implicit conversions with dimensionless units.
This is intuitively appealing: after all, a Quantity like `percent(75.0)`

represents the value
`0.75`

. Shouldn’t we handle that conversion automatically, just as happily as we turn `feet(3)`

into `inches(36)`

?

While the appeal is obvious, we believe this does more harm than good. The reason is that
a Quantity has *two different* notions of value, and for dimensionless units specifically, these
become ambiguous. Consider something like `inches(24)`

. By “value”, we might mean:

- the numeric variable
`24`

, stored safely within the Quantity object, as if in a container. - the
*quantity value itself*— in this case, the extent of the physical length, which is identical with`feet(2)`

.

With dimensioned quantities, the library prevents confusion: we can’t use either in contexts where
the other belongs. But dimensionless quantities lack this safeguard. This opens the door to
decisions which are individually reasonable, but which interact badly together. For instance,
a `Quantity<Percent, T>`

may be implicitly constructible *and* convertible with `T`

, but could pick
up stray factors of 100 in the round trip!

It is safer (and not *much* less convenient!) to use separate, unambiguous idioms for these two
notions of “value”.