The UFCS stuff that lets you write 100.kpa for kpa(100) is wild, I haven’t really seen it before in other languages, and it seems like it’d be great for exactly this use case.
Different, but F# has units of measure. Seems wonderful to be honest.
Those are clean as heck. The thoroughness and how they combine with the type system is really appealing.
Seems like something similar is possible in Ada too. (That web page takes a while to get to examples; search for Examples: to see a few.)
You can do a lot of it with C++ too (see std::chrono::duration for an example, including the ability to write things like 10ms in C++14). It’s a little bit clunky though. Derived units (e.g. m/s once you’ve defined m and s) are much harder: you can do it, but not automatically and you end up needing to define explicit conversion templates.
Yeah, it takes a bit of user code to make that happen in D, but it more-or-less can be done. see https://code.dlang.org/packages/quantities for an example
Basically it creates a new subtype for each unit then the operator overloads do various combinations. So like 1.km / 1.sec will return a new km_per_sec unit which can be aliased to nicer names and compared etc. The .km there is a UFCS constructor call.
Since you can do compile time evaluation of normal functions and pass string literals to them, you can do a bunch of the internal stuff with string processing to make it part of the type and whatnot.
tbh though I never use these things in practice. Maybe I should it just never seems worth the hassle.
The Nim language also has UFCS, and I was not sure if I can write 100.foobar so I just tried, and yes I can:
$ cat exp_units.nim
proc km(i: int): int = 1000*i
$ nim c -r --verbosity:0 exp_units.nim
Rails has 12.hours and so forth.
Doesn’t it do that by adding methods to the integer class (or however Ruby phrases it)? That’s similar, but not quite the same thing.
Yep. They aren’t quite units of measure, either; they just convert to a Duration (or whatever). You can of course combine 12.hours and 12.days because they’re of the same measure.