kunalsheth / units-of-measure Goto Github PK
View Code? Open in Web Editor NEWType-safe dimensional analysis and unit conversion in Kotlin.
Home Page: http://units.kunalsheth.info
License: MIT License
Type-safe dimensional analysis and unit conversion in Kotlin.
Home Page: http://units.kunalsheth.info
License: MIT License
A minute can be 61 or 59 seconds. Just thought you should know. https://en.wikipedia.org/wiki/Minute
Since converting to a multiproject module, I am getting the following error when trying to build from a clean directory (./gradlew clean
):
Declaration annotated with '@OptionalExpectation' can only be used in common module sources
I believe this is caused by the @JsName
annotations.
It only happens on the first invocation of ./gradlew build
, if I re-run ./gradlew build
a second time everything compiles and runs fine.
This isn't a problem for development/testing on my workstation, but it is a problem for an automated build server. Have you seen this issue or have any ideas?
My module's build.gradle
is:
apply plugin: 'org.jetbrains.kotlin.multiplatform'
apply plugin: 'info.kunalsheth.units.gradle'
repositories.mavenCentral()
kotlin {
jvm()
sourceSets {
commonMain {
kotlin.srcDirs += generateUnitsOfMeasure.generatedSrcDir
dependencies { implementation kotlin('stdlib-common') }
}
jvmMain {
dependsOn commonMain
dependencies {
implementation kotlin('stdlib')
}
}
jvmTest {
dependencies {
implementation kotlin('test')
implementation kotlin('test-junit')
implementation "com.google.truth:truth:0.45"
}
}
all {
languageSettings.enableLanguageFeature('InlineClasses')
}
}
targets.all {
compilations.all { compileKotlinTask.dependsOn(generateUnitsOfMeasure) }
}
}
// workaround for https://youtrack.jetbrains.com/issue/KT-27170
configurations {
compileClasspath
}
apply from: 'units-of-measure.gradle'
This looks like a very fascinating project, and I would like to try it out in an android app that I have to do a lot of unit conversion in. The configuration on the wiki, unfortunately, does not work for android.
I get
Could not get unknown property 'sourceSets' for root project
Is it possible to adjust the config to work on android?
UPDATE: DO NOT DO THIS. units-of-measure is incompatible with Celsius and Fahrenheit. Attempting to define Celsius and Fahrenheit will cause weird and incorrect behavior.
Celsius and Fahrenheit would have to be manually programmed in on the user's end. Celsius and Fahrenheit aren't "units" in the theoretical sense because they have different zeros.
To add Celsius and Fahrenheit, your code would look like the following:
inline val Number.Celsius get() = `Θ`(toDouble() + 273.15)
inline val `Θ`.Celsius get() = siValue - 273.15
object `Celsius` : UomConverter<`Θ`>,
Quan<`Θ`> by box(1.Celsius) {
override val unitName = "Celsius"
override fun invoke(x: Double) = x.Celsius
override fun invoke(x: `Θ`) = x.Celsius
}
inline val Number.Fahrenheit get() = `Θ`((toDouble() - 32) * 5 / 9 + 273.15)
inline val `Θ`.Fahrenheit get() = (siValue - 273.15) * 9 / 5 + 32
object Fahrenheit : UomConverter<`Θ`>,
Quan<`Θ`> by box(1.Fahrenheit) {
override val unitName = "Fahrenheit"
override fun invoke(x: Double) = x.Fahrenheit
override fun invoke(x: `Θ`) = x.Fahrenheit
}
Make sure your Gradle project is properly imported into IntelliJ:
UnitsOfMeasure.kt
file in build/uoms
directory of your units-of-measure Gradle module.This library looks super cool and I wanted to try it out, but am coming across a problem in the generated code, where the compiler is complaining that '@JvmName' annotation is not applicable to this declaration
.
There are too many errors to list all of them, but they are all of a similar nature. An example line where the compiler is complaining is:
@JvmName("L0A0M0T0I0Theta0N0J0_Divide_L0A0M0T0I0Theta0N0J0_generic")
operator fun `Dimensionless`.div(that: Quan<`Dimensionless`>) = `Dimensionless`(this.siValue / that.siValue)
src/main/kotlin/Main.kt
import info.kunalsheth.units.generated.*
fun main() {
println(1.Metre)
}
build.gradle
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.4.21'
id 'info.kunalsheth.units' version '6.0.2'
}
repositories {
mavenCentral()
}
sourceSets {
main {
java {
srcDirs 'src/main/kotlin'
srcDirs 'build/uom'
}
}
}
In the demo there is code: val mass = 3.kilo(Gram)
, but When I try to do this, I get the following compile error:
Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
public val M /* = L0M1T0I0Theta0N0J0 /.Gram: Double defined in info.kunalsheth.units.generated
public val Number.Gram: M / = L0M1T0I0Theta0N0J0 */ defined in info.kunalsheth.units.generated
I'm not sure why it can't pick between those 2 extension methods.
same for:
val speed = 65.Mile / Hour
It cannot figure out Hour
This is in a unit test in a kotlin/jvm library
I believe the issue of converting between Kelvin and Celsius/Fahrenheit is a perfectly solvable one, and I offer the overall approach I used to handle this:
// Static Properties of a Quantity
// e.g.
// object Velocity : Quantifiable<Velocity> {
// override dimension = Dimension(L = 1, T = -1)
// override val baseUnit = Meter/Second
// }
interface Quantifiable<Q: Quantifiable<Q>> {
val dimension: Dimension
val baseUnit: BaseUnit<Q>
}
// An instance of a Quantifiable
// e.g. 11.Kelvin == Quantity(11, Kelvin)
// calculates amount in the base unit of the quantifiable for binary operations involving other quantities of the same quantifiable. e.g. 12.Kelvin + 25.Celsius == 12.Kelvin + (25.Celsius convertTo Kelvin)
class Quantity<Q : Quantifiable<Q>>(val amount: Double, val unit: MeasureUnit<Q> = baseUnit) : Quantifiable<Q> by unit.quantifiable {
val baseAmount: Double by lazy { unit.convertToBase(amount) }
operator fun compareTo(other: Quantity<Q>): Int = baseAmount.compareTo(other.baseAmount)
operator fun plus(other: Quantity<Q>): Quantity<Q> = unit.convertFromBase(other.baseAmount + baseAmount)
...
}
// The units themselves hold the functions for converting to/from base unit.
// In this way, Celsius is 'defined' as Kelvin - 273.15, as seen below.
interface MeasureUnit<Q : Quantifiable<Q>> { // e.g. Kelvin
val quantifiable: Q
fun convertToBase(amount: Double): Double
fun convertFromBase(baseAmount: Double): Double
}
// The base unit doesn't need to convert amounts to base. it's already base.
abstract class BaseUnit<Q : Quantifiable<Q>>(override val quantifiable: Q) : MeasureUnit<Q : Quantifiable<Q>> {
override fun convertToBase(amount: Double) = amount
override fun convertFromBase(baseAmount: Double) = baseAmount
}
// The following instances can be val instead of object. They were object for me because they were members of a sealed class
object Temperature : Quantifiable<Temperature> {
override val dimension = Dimension(Θ = 1)
override val baseUnit = Kelvin
}
object Kelvin : BaseUnit<Temperature> by BaseUnit(Temperature)
object Celsius : MeasureUnit<Temperature> {
override val quantifiable = Temperature
override fun convertToBase(amount: Double) = amount + 273.15
override fun convertFromBase(baseAmount: Double) = amount - 273.15
}
Hello there!
This is a cool library and I hope to see it developed more or at least have more community support on it!
I had a question about angles and radians within the library, and maybe I'm overthinking this. I have a function that accepts an angle, but internally the calculations are done in radians. I'm seeing if I could convert my code to use your library.
How would you write a function that does something like this into using your library? I've already got it compiled and working otherwise.
fun doMath(degrees: Double) {
val radians = degrees * (Math.PI / 180.0)
// Math that uses radians later
}
I was having a hard time figuring out what types I'd need to use from the library to replace the Double
for the angle. It's assumed to be degrees currently.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.