uom icon indicating copy to clipboard operation
uom copied to clipboard

More examples and better doc

Open xoac opened this issue 6 years ago • 12 comments

It's would be nice to see more examples (and probably better documented).

For example: https://github.com/iliekturtles/uom/blob/master/examples/base.rs#L10-L16

could contain copy from doc or just link

mod cgs {
    // [ More info ]:  https://docs.rs/uom/0.19.0/uom/macro.ISQ.html
    ISQ!(
        uom::si, // Path to the module where the system! macro was run (e.g. ::uom::si).
        f32, // Underlying value storage type (e.g. f32).
        (centimeter, gram, second, ampere, kelvin, mole, candela) //Optional. Base units. Pass as a tuple with the desired units:
                                                                 // (meter, kilogram, second, ampere, kelvin, mole, candela). 
                                                                //The system's base units will be used if no value is provided.
    );
}

I would suggest add Fahrenheit or Celcius example. It would be also nice to see use of i32 instead of float precision numbers.

xoac avatar Jul 07 '18 18:07 xoac

Thanks for the suggestions. An i32 example would be really good and a documentation pass is definitely due. See #20 / #21 for a couple existing issues. Fahrenheit and Celsius aren't yet supported (see #3), but I've been working on temperature recently.

iliekturtles avatar Jul 09 '18 01:07 iliekturtles

Can you give me hint how to store a milivolt (as a base/store unit)?

xoac avatar Jul 09 '18 18:07 xoac

I haven't had a chance to test below, but changing from ampere to kiloampere will store electric potential as millivolts in the underlying storage type. If you are using i32 as your underlying type see #55 as integer storage types aren't very polished right now.

ISQ!(
    uom::si,
    i32,
    (meter, kilogram, second, kiloampere, kelvin, mole, candela)
);

iliekturtles avatar Jul 09 '18 18:07 iliekturtles

Just did a quick test and the above ISQ! invocation does work as expected. The following program prints the two electric potential's raw values. Note that because I used i32 as the underlying storage type the second can't store a millivolt (0.001 is too small for i32) while the first can. Another way to think about it is that everything is stored as some combination of the seven base units. e.g. volt is represented as m2 · kg · s-3 · A-1.

Let me know if you still have questions or additional suggestions for improving documentation. The design tries to answer questions like this.

#[macro_use]
extern crate uom;

use uom::si::electric_potential::millivolt;

ISQ!(
    uom::si,
    i32,
    (meter, kilogram, second, kiloampere, kelvin, mole, candela)
);

fn main() {
    let l1 = mv::ElectricPotential::new::<millivolt>(1);
    let l2 = uom::si::i32::ElectricPotential::new::<millivolt>(1);

    println!("{}", l1.value);
    println!("{}", l2.value);
}

and outputs

1
0

iliekturtles avatar Jul 09 '18 23:07 iliekturtles

My problem is that I want to store milivolt miliamper etc. and I would need to create own ISQ! for each type.

I was looking for solution that is similar to duration if you know C++11. There you can say that u want to store time in i64 as milliseconds or seconds or hours etc. It use ratio. What is more it allows you to add second + milliseconds and store value in milliseconds. But it's compile error when you try add second + milliseconds and store result in seconds.

xoac avatar Jul 20 '18 15:07 xoac

It's look like this will be possible in the future :) link

xoac avatar Jul 20 '18 15:07 xoac

As you mentioned multiple ISQ! invocations would be needed (see below), but this isn't very ergonomic with uom's current design. Eventually support along those lines would be nice, but it's not near the top of the list right now. Checkout out dimensioned which does work this way.

mod mV { ISQ!(uom::si, i32,(meter, kilogram, second, kiloampere, kelvin, mole, candela));
mod mA { ISQ!(uom::si, i32,(meter, kilogram, second, milliampere, kelvin, mole, candela));

iliekturtles avatar Jul 21 '18 19:07 iliekturtles

Not sure if this is the best place to add this, but since it's a documentation issue and I'm struggling to figure this out...

I have a meter/second velocity. How would I convert that to miles/kilometers per hour? I've tried a few things, but none seems to work. The docs include an example of converting velocity to acceleration, but if there's an example of converting the same quantity then I haven't had enough coffee yet. :)

Or can I only input a velocity and not convert one? Essentially I want to represent a M/S velocity as a string in KPH/MPH. Whether that means I do a conversion first or if I convert only the string representation is a bit unclear.

Thanks for a great library!

ndarilek avatar Jul 13 '19 13:07 ndarilek

Thanks for the kind words!

See #123, specifically the link to the Arguments struct, for more details about formatting a quantity into a string. It's a known issue that the documentation discoverability isn't good right now. We're working through documentation in preparation for v1.0.0 and haven't gotten to that one yet.

uom is currently designed so that within your program you work with quantities (length, time, velocity, ...) not units (meter, second, m/s, ...) since most* of the time you don't need to control how the actual value is stored. This isn't always very ergonomic however (see previous discussion in this thread) so eventually I hope to support explicit unit values (#107).

In your case when you enter a value as m/s you create a Velocity which erases the input type. From there you work with velocity and don't need to worry about units until displaying something to the user, saving to a DB, ... Let me know if this doesn't make sense and I'll write up something a bit more detailed.

  • By default uom stores velocity as m/s so if you're not working on a astronomical or atomic scale a f32/f64 can store your value with enough precision.

iliekturtles avatar Jul 15 '19 01:07 iliekturtles

Perfectly understandable. I wasn't clear whether the internal representation was always the same and conversions were only handled when formatting as a string, which your answer clarifies.

One additional question: is there a convenience/shortcut for truncating decimals when converting? Right now I'm doing:


let distance = format!("{}", distance.into_format_args(meter, Description));

This often gives me strings of distances with many decimal points, which is fine for accuracy but not so great for readouts. :) I'd like either 0 or 1 decimals if at all possible. Do I have to get the units and create an entirely new length, or is there an easier way?

Thanks again.

ndarilek avatar Jul 15 '19 14:07 ndarilek

All of the format specifiers from std::fmt pass right through. Just add .0!

let distance = format!("{:.0}", distance.into_format_args(meter, Description));

I'll add a note to the other issue to make sure this is explicitly noted.

iliekturtles avatar Jul 15 '19 14:07 iliekturtles

Oh, thanks. I'd found format specifiers a while back but had forgotten about them, and wasn't even sure what to google. Works great!

ndarilek avatar Jul 15 '19 14:07 ndarilek