<Measured> 0.4.1 has been released. This update ad...
# feed
n
Measured 0.4.1 has been released. This update adds support for other KMP targets like iOS and all Apple platforms, Android Native, Linux, etc. Measured makes units of measure simple by providing intuitive, strongly-typed units that combine using normal mathematical operations.
Copy code
val velocity     = 5 * meters / seconds
val acceleration = 9 * meters / (seconds * seconds)
val time         = 1 * minutes

//  d            = vt + ½at²
val distance     = velocity * time + 1.0 / 2 * acceleration * time * time

println(distance                ) // 16500 m
println(distance `as` kilometers) // 16.5 km
println(distance `as` miles     ) // 10.25262467191601 mi

println(5 * miles / hours `as` meters / seconds) // 2.2352 m/s
👍 9
❤️ 4
👍🏾 1
👍🏻 1
⚖️ 1
📐 1
⏱️ 1
p
@Nick OOC, is there any conceptual difference or a significant differentiator comparing to https://github.com/vsirotin/si-units?
n
i haven’t used this other library. but my understanding is that it does not provide compile-time safety as you do math on things with units. it seems like some invalid expressions won’t be caught until runtime. as a result, it seems like you have to define any unit you’d like to have a type for (i.e. Newton). Measured provides compile-time guarantees. each math computation returns a new type based on the rules of dimensional analysis. this means you can have guarantees about the outcome. it also means you don’t really need to define a type for something like acceleration at all. just take in a
Measure<UnitsRatio<Length, Square<Time>>>
. or create a typealias for the unit and take a Measure of that:
Copy code
typealias Acceleration = UnitsRatio<Length, Square<Time>>

fun foo(acceleration: Measure<Acceleration>)
Measured will just create these kinds of units automatically as you multiply and divide other units. it handles canceling numerators and denominators as well. of course there are still limits to how far this is taken in the library. but these gaps can easily be added via extensions. custom units are also fully supported. and they participate in the same dimensional logic as any other unit. you can also easily add new types to an existing unit. the docs show how to do both.
👍 1
p
got it, thanks! I'm definitely a fan of compile-time safety
👍 2
s
What would be a better name instead of
as
so that it must not be escaped? 🤔
n
open to suggestions 😅 .
👍 1
k
In addition to the above, there's an
in
that also has to be escaped. I'm not sure I can think of a better word for them. By the way, there's a section titled "Complex units" which might possibly be confusing as it does not involve complex numbers.
p
would
to
look weird? no need to escape
ah, I guess it creates a
Pair
(docs, usually used in the context of maps), it's auto-imported
s
Yes, so for
to
you would need the full qualified name. I'm thinking if something
presentedAs
(or another prefix) would help here. I don't like the escapes.
p
something to consider: I had a similar case in my lib, and we ended up providing 2 variants: one that has to be escaped but is shorter and resembles the GitHub's API (it's a Kotlin wrapper for GitHub Actions, ref), and another one that looks a bit worse but no escaping is needed. This way you let the users choose
👍 1
k
There's also the possibility of using an import alias, so you could name the functions whatever you like (at the expense of different teams using different names, which could cause confusion)
s
Right.
u
did you consider storing the units as a set of name,exponent, ordered by name. I.e. “m^2” = { “m” to 2 }, “m/s” being {“m” to 1, “s” to -1}? By normalizing this way you avoid the mentioned issue with order of operations. Certainly for real code you would not use “string to int” but a container class.
🧠 1
y
I wonder what happens if you use examples from

this

and

this

:D
😀 1
n
@uli, how would you get compile-time validation so the compiler knows that
Length/Time
is not the same as
Time/Length
etc.? the current approach produces 2 different Kotlin types for these and lets you write functions that require specific types like:
Measure<UnitsRatio<Length, Time>>
, aka velocity.
u
I see. If you keep that compile time type handling,
Length*Time
and
Time*Length
would still get different types, even when there suffixes and exponents could be matched at runtime. This sounds like an interesting challenge. And you are probably right, that the kotlin type system can not solve that. At least I have no idea how to force types to be fully ordered