-
Notifications
You must be signed in to change notification settings - Fork 122
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Frequency Enhancements #213
Conversation
It may be that the Frequency.*(TimeIntegral) method is too abstract and I'll need to define a method for each TimeIntegral in the libary .... class Frequency(...) {
...
def *(that: Length): Velocity = that * this
def *(that: Velocity): Acceleration = that * this
def *(that: Information): DataRate = that * this
// etc ...
} It would be nice if the TimeIntegral/Derivative abstraction could handle that, but maybe not. Thoughts? |
I replaced the Frequency * TimeIntegral code, which was limited, with explicit methods for each defined TimeIntegral. This achieves the API requirement, but with a bit more code. This could be improved in the future, but this PR should be mergeable as is - pending review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a few small issues, but this look good.
@@ -26,6 +30,36 @@ final class Frequency private (val value: Double, val unit: FrequencyUnit) | |||
protected[squants] def timeIntegrated = Each(toHertz) | |||
protected[squants] def time = Seconds(1) | |||
|
|||
// Below are two failed attempts to invert the TimeIntegral * Frequency method to support Frequency * TimeIntegral |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should remove the comments from lines 33 - 44 into the PR. I'd like to preserve them, but I don't think they need to be in the source.
@@ -10,7 +10,7 @@ package squants | |||
|
|||
import org.scalatest.{ FlatSpec, Matchers } | |||
import squants.thermal.{ Celsius, Fahrenheit } | |||
import squants.time.Hours | |||
import squants.time.{ Hours, Hertz } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit - Hertz should be before Hours to keep imports alphabetized.
I agree spelling out the specific types is sub-optimal, but at least we're type safe. We might be able to implement it more generically in the future at the cost of binary compatibility. With this new syntax, we should update the README. I had removed this syntax in #202 a few months ago. Can you update val freq = 60 / second example in the "Implicit conversion support for using Double on the left side of multiplication" section (which we probably should rename now). (this was the original line https://github.com/typelevel/squants/pull/202/files#diff-04c6e90faac2675aa89e2176d2eec7d8L487) |
Hertz(100) * Webers(100) should be(Volts(10000)) | ||
Hertz(100) * Kilograms(100) should be(KilogramsPerSecond(10000)) | ||
Hertz(100) * NewtonSeconds(100) should be(Newtons(10000)) | ||
Hertz(100) * Watts(100) should be(WattsPerHour(10000)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this in WattsPerHour
? Shouldn't the unit be watts per second?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. Most time derivative relationships are based on the second. Energy/Power/PowerRamp prefer the WattHour, Watt and WattsPerHour units, so the base time is one hour. The new conversion assumed 1 second, which coupled with my blind paste and copy test setup, led to a passing test on a bad conversion. It's fixed up now.
Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although WattsPerSecond, which is effectively a joule / sec^2, would be a good addition to library.
README.md
Outdated
@@ -788,14 +789,21 @@ scala> val low = 40.dollars / megawattHour | |||
low: squants.market.Price[squants.energy.Energy] = 40.00 USD/1.0 MWh | |||
``` | |||
|
|||
Implicit conversion support for using Double on the left side of multiplication: | |||
Implicit conversion support for using Doubles, Longs and BigDecimals on the left side of multiply and divide operations: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like you edited README.md
directly. The readme is built via tut now, so these changes will be overwritten on the next build. Can you also update shared/src/main/tut/README.md
so they're preserved?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, yes. Thanks. Fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One thing I noticed is
BigDecimal(1) / hour
works in the tut, but
BigDecimal(1) per hour
does not: method not defined.
However, both of these are defined in the same implicit class and both work in the console. For the README, I just went back to using the / operator. Any thoughts on that?
cc388f5
to
b0c14c5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me, thanks for the PR
def *(that: LuminousEnergy): LuminousFlux = that * this | ||
def *(that: LuminousExposure): Illuminance = that * this | ||
def *(that: MagneticFlux): ElectricPotential = that * this | ||
def *(that: Mass): MassFlow = that * this |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will this produce e.g. [kgs/sec]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it will.
[T^-1] * [M] = [M/T]
383dbe8
to
954eb6a
Compare
Added /(Time) and per(Time) to Squantified numbers to support expression like: val f: Frequency = 1000 / second Added *(Frequency) to TimeIntegral to support conversions like: val dr: DataRate = 1000.bytes * 10/second Added *(TimeIntegral) to Frequency to support the same conversion in with reversed operands: val dr: DataRate = 10/second * 1000.bytes However, this returns type Any and needs to be reviewed for ideas on how to fix that. Added *(TimeIntegral) to Frequency for all currently defined TimeIntegrals Review updates * removed extraneous comments * alphabetized imports * updated README * Fixed Power / Energy / Frequency conversions and tests Review updates * Update tut/README * resolved merge conflicts
954eb6a
to
78bf5a2
Compare
LGTM. |
Added /(Time) and per(Time) to Squantified numbers to support expression like:
Added *(Frequency) to TimeIntegral to support conversions like:
Added *(TimeIntegral) to Frequency to support the same conversion with reversed operands:
However, this last expression returns type Any and needs to be reviewed for ideas on how to fix that before this is merged.
This is intended to close #134