An implementation of some python features for kotlin.
Add pytlin to your <dependency> tag in your POM file:
(pom.xml):
<dependency>
<groupId>io.github.psunset</groupId>
<artifactId>pytlin</artifactId>
<version>${pytlin.version}</version>
</dependency>Then set pytlin.version in your <properties> tag in the same file:
(pom.xml):
<properties>
<pytlin.version>x.y.z</pytlin.version>
</properties>Please replace x.y.z with an available version by checking
out the releases.
Finally, install the library:
mvn install
Add pytlin to your dependencies in the build file:
Groovy (build.gradle):
dependencies {
implementation "io.github.psunset:pytlin:$pytlin_version"
}Kotlin (build.gradle.kts):
dependencies {
implementation("io.github.psunset:pytlin:$pytlin_version")
}Then set pytlin_version in your properties file:
(gradle.properties):
pytlin_version=x.y.zPlease replace x.y.z with an available version by checking
out the releases.
Finally, build your project:
./gradlew build
Directly download the pytlin-x.y.z.jar file
from the releases page.
Then import it into your module.
All kotlin examples below are tested in a kotlin script (.kts) file.
Therefore, there's no main function in the code.
If you want to directly use the example code in a kotlin (.kt) file,
please remember to create a main function as an entry point.
When you define a function in python, you may use *args and **kwargs as parameters.
For example:
from functools import reduce
import operator
def f(*args, **kwargs) -> int:
method = kwargs.pop('method', 'add')
match(method):
case 'add': result = sum(args)
case 'mul': result = reduce(operator.mul, args, 1)
case _: result = 2147483647 # Invalid method
return result
sum_result = f(*range(1, 10), 15, 20, method='add')
print(sum_result) # Result: 80
prod_result = f(*range(1, 5), method='mul')
print(prod_result) # Result: 24Now, you can achieve the same purpose in kotlin with the following code.
import net.psunset.pytlin.collections.Kwargs
import net.psunset.pytlin.collections.kwargsOf
import net.psunset.pytlin.collections.prod
fun f(vararg args: Int, kwargs: Kwargs): Int {
val method = kwargs["method", "add"]
// "method" is key, "add" is defaultValue
// Only getting the value here, not popping the element.
// Because the key-value pairs in Kwargs are immutable.
return when (method) {
"add" -> args.sum()
"mul" -> args.prod() // A feature in this library
else -> Int.MAX_VALUE // Invalid method
}
}
val sum_result = f(
*(1..<10).toList().toIntArray(), 15, 20,
kwargs = kwargsOf(
"method" to "add"
)
)
println(sum_result) // Result: 80
val prod_result = f(
*(1..<5).toList().toIntArray(),
kwargs = kwargsOf(
"method" to "mul"
)
)
println(prod_result) // Result: 24Sometimes, we would like to use a kwargs-like map or dict
which is a more convenient map or dict with string keys and values.
Since the elements in Kwargs are all immutable,
we need MutableKwargs instead.
For example:
import net.psunset.pytlin.collections.mutableKwargsOf
val goodToPrice = mutableKwargsOf("apple" to 3, "orange" to 2, "banana" to 3)
val priceOfApple = goodToPrice / ("apple" to 0)
// "apple" is key, `0` is defaultValue
// using `/` operator to pop an element
val priceOfOrange = goodToPrice / ("orange" to 0)
println("Total price is ${priceOfApple + priceOfOrange}") // Result: Total price is 5
println(goodToPrice) // Result: {banana=3}
// This shows that apple and orange have already been removed.When we want to create a list by repeating another list, we simply make a list multiplied by an integer.
For example:
l = [1] * 10
print(l) # Result: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
ll = [1, 2] * 5
print(ll) # Result: [1, 2, 1, 2, 1, 2, 1, 2, 1, 2]Now, we can simply implement that in kotlin with the following code.
import net.psunset.pytlin.collections.times
val l = listOf(1) * 10
println(l) // Result: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
val ll = listOf(1, 2) * 5
println(ll) // Result: [1, 2, 1, 2, 1, 2, 1, 2, 1, 2]In python, you can directly put a non-boolean variable after if.
Often, it implies if itself isn't empty, non-zero, etc.
For example:
a = []
b = ''
c = 0
if a: print('a is True!')
if b: print('b is True!')
if c: print('c is True!')
# There is no output because a, b and c all stands for false.Now, let's convert it into kotlin.
import net.psunset.pytlin.lang.not
import net.psunset.pytlin.lang.toBool
val a = listOf<Any>()
val b = ""
val c = 0
if (a.toBool()) println("a is true!")
if (b.toBool()) println("b is true!")
if (!!c) println("c is true!") // Also, `obj.toBool()` can be replaced to `!!obj`
// There's no output, either.By the same token, if not obj: ... in python is equivalent to if (!obj) { ... }.
== operator in python only checks the value of two numbers, regardless of their type.
For example:
print(1.0 == 1) # Result: TrueBut after converting the preceding code into kotlin.
println(1.0 == 1) // Error: Operator '==' cannot be applied to 'Double' and 'Int'Uh..., there is an error with the preceding code.
Let's transform that into a BigDecimal.
import java.math.BigDecimal
println(BigDecimal.valueOf(1.0) == BigDecimal.valueOf(1)) // Result: falseAs you see, the result is false because the == operator in kotlin
not only compares the value of the numbers but also checks whether they are of the same type.
But the function named valEq can address two problems we encounter.
Let's replace the == operators with valEq infix functions.
import net.psunset.pytlin.lang.valEq
import java.math.BigDecimal
println(1.0 valEq 1) // Result: true
println(BigDecimal.valueOf(1.0) valEq BigDecimal.valueOf(1)) // Result: trueIt seems that the problems are solved.
This feature is unavailable in raw python. It is enabled only when you install numpy, pytorch or other libraries like them.
A tensor can store a multi-dimensional array. Its features include matrix multiplication, dot product and cross product of vectors, operation for all elements, etc.
But, in fact, the tensors in this library are incomplete and deprecated. For a more useful library with more features and better performance. Please check out mulkit, which is a kotlin official library.
For more details, please check out the document in Tensors source.
In python, slices of a list can be simply implemented by the following code.
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(a[:5]) # Result: [1, 2, 3, 4, 5]
print(a[:]) # Result: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(a[::-1]) # Result: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]Now, with this library,
you can achieve the same effect in kotlin by wrapping the slice symbol with " to make it a string.
For example:
import net.psunset.pytlin.collections.get
val a = arrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
println(a[":5"]) // Result: [1, 2, 3, 4, 5]
println(a[":"]) // Result: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
println(a["::-1"]) // Result: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]Also, setting elements with python-like slice is also available.
In python, the most common for loop is the following code.
for i in range(10):
print(i, end='')
# Result: 0123456789This library implements that range function in kotlin. The following code can be run correctly.
import net.psunset.pytlin.Py
for (i in Py.range(10)) {
print(i)
}
// Result: 0123456789But, to be honest, the recommended way is to use raw kotlin function. Just like the following code.
for (i in 0..9) {
print(i)
}
// Result: 0123456789
// '0..9' and '0..<10' are similar to each other. deprecated