r-quantities / units

Measurement units for R
https://r-quantities.github.io/units
172 stars 27 forks source link

Allow logical math? #352

Open ilikegitlab opened 11 months ago

ilikegitlab commented 11 months ago

I can see why its odd, but I cannot see a good reason to block math with logicals (but have special cases for NA).

TRUE set_units(1, km) Error in units<-.logical(`tmp*`, value = as_units(value, ...)) : x must be numeric, non-NA logical not supported

Of course, I can actually trick you anyway:

TT<-set_units(1,1); mode(TT)<-"logical"; TT * set_units(1, km) 1 [km]

Apart from allowing simpler TRUE/FALSE conditionals, it also makes use with ifelse (issue #350) more sane.

But if it is too strange to allow all units, I think a logical values should at least behave as if it had dimensionless units instead of causing an error. FWIW it would clean up some code I have (I switched to my logical vars being integers now...).

Enchufa2 commented 6 months ago

Sorry, I missed this issue.

I can see why its odd, but I cannot see a good reason to block math with logicals (but have special cases for NA).

Yes, it's odd. But I'm in the other side: I'd like to have a good reason to allow logicals with units. :) What's your use case?

Apart from allowing simpler TRUE/FALSE conditionals, it also makes use with ifelse (issue #350) more sane.

Not really. The same issue happens with or without math with logicals. It's about how ifelse works.

ilikegitlab commented 3 months ago

use case: I simply commonly multiply something with TRUE or FALSE rather than writing ifelse if its cleaner. I've large data.frames with instrument data and I feel it makes sense to set set some columns to logical (as its clear to the user). But once i am using the columns to calculate derived parameters i regret that choice as i can't simply do col1* but need to write an ifelse that requires further syntactic sugar....

I maintain it does make ifelse more sane. In 350 you wrote: ifelse(set_units(c(1, 0, 1, 0, 1), m), set_units(8, km), set_units(3, mm))

that c(1,0,1,0,1) is likely actually a logical vector. So you want us to do: ifelse(set_units(as.numeric(logical_vector), m), set_units(8, km), set_units(3, mm))

i would like to: ifelse(set_units(logical_vector, m), set_units(8, km), set_units(3, mm))

or even just: logical_vector*set_units(8, km) (in case i need either 8 or 0)

[tangent: I've used units in a larger project but feel continuously that it makes large equations explode in complexity because of the extra syntax. This, and the sometimes strict checks result in people just dropping units, calculating stuff, and reapplying. Instead, i've implemented my own layer on top of units that overloads @ to allow things like 1@m/10@s and also accepts logical vectors. Lots of people would object I guess, but it works surprising well for me within package namespace.). ]