How to write `$("user")` in kotlin with flink - kotlin

from flink 1.14, it suggest using $() for retrieving elements like below:
Table table = tableEnv.fromDataStream(ds, $("user"), $("product"), $("amount"));
so is there a way to convert it to kotlin, for it causing compiler error in kotlin:
var table = tableEnv.fromDataStream(ds, $("user"), $("product"), $("amount"));

I am not familiar with Apache Flink, but you're not allowed to use the dollar sign on it's own.
For function names with special characters, e.g. whitespace, you have to put the function name into backticks (`), e.g.:
fun `white space`() = Unit
fun `$`() = Unit
fun main() {
`white space`()
`$`()
}
Thus, your code example above works on my machine with the following adjustments.
import org.apache.flink.table.api.Expressions.*
...
val table = tableEnv.fromDataStream(ds, `$`("user"), `$`("product"), `$`("amount"))

This problem will be fixed in one of the next Flink releases:
https://issues.apache.org/jira/browse/FLINK-26278

Related

Kotlin readLine gives error in a basic program where input is taken from user and the same is shown as output

The following code :
fun main(args: Array<String>) {
print("Write anything here: ")
val enteredString = readLine()
println("You have entered this: $enteredString")
}
gives the following error in KotlinPlayground :
Write anything here: You have entered this: null
Here, the user doesn't get an opportunity to enter input. After the initial print statement gets executed, the compiler is not waiting for the user to give input and skips to the next print statement. Why is it happening? I have tried the same in several other online Kotlin compilers but I am getting the same error.
There's no error. readLine just returns null (because Kotlin Playground doesn't have a console to read from), and it's printed as expected.
E.g. on https://ideone.com/ you can say what to use for input and it'll print that line (though its Kotlin version is pretty old).
Because Kotlin playground have no user input console and this is not an error. For user input you can either use https://ideone.com/ or
https://www.jdoodle.com/compile-kotlin-online/
I will recommend you to use the second on which is jdoodle. It is pretty much faster to run and read user input and almost use the latest version of Kotlin and JRE.
And if you like to play (run) with command line argument then it will good for you with jdoodle.
This can be done in Kotlin Playground by using JS as the destination platform - click on the JVM dropdown (top left, to the right of the kotlin version) and change to JS.
Now you can call JavaScript - only using constant strings, e.g.
fun main() {
val name = js("prompt('Please enter your name', 'Bob')")
println("Hello $name")
}
For another example, using a common function, see https://pl.kotl.in/MkhfYNS47
Note: if you try this:
fun promptName(default: String = "") {
return js("prompt('Please enter your name', '$default')")
}
You will get a compilation error - Argument must be string constant.
Note that JS IR as an option ran much slower and had an issue with default type needing to be stated for the linked code

Kafka Streams Materialized View with Kotlin

To create a kafka streams state store in Java I can do this:
final KGroupedStream<String, String> wordCounts = textLines
.flatMapValues(value -> Arrays.asList(pattern.split(value.toLowerCase())))
.groupBy((key, word) -> word);
wordCounts.count(Materialized.<String, Long, KeyValueStore<Bytes, byte[]>>as(WORD_COUNT_STORE));
I am attempting to convert this to Kotlin, like this:
val wordCounts: KGroupedStream<String, String> = textLines
.flatMapValues({value -> value.split("\\W+") })
.groupBy({ _, word -> word})
wordCounts.count(Materialized.<String, Long, KeyValueStore<Bytes, Array<Byte>>>as(WORD_COUNT_STORE))
However, I get the following compiler error:
Interface KeyValueStore does not have constructors
What do I need to do?
In case it's of use to anyone else, as well as the backticks suggested by Raman, I had to make couple of other changes:
First, the generic types need to be specified after the as method, not straight after the Materialized class.
Secondly, rather than using Array<Byte> I had to use ByteArray.
So the full line of code that worked for me was:
wordCounts.count(Materialized.`as`<String, Long, KeyValueStore<Bytes, ByteArray>>(WORD_COUNT_STORE))
Since as is a reserved word in Kotlin, try surrounding the as with backticks i.e.
`as`

Kotlin-js: Define number of decimals

Let's imagine something like this:
var num: Float = 0.0f
num = 2.4 * 3.5 / 3.8
num has several decimals, but I want only 2.
In JS I would use num.toFixed(2).
Other answers here suggest to use "%.2f".format(num) or num.format(2). The latter needs a custom extension fun:
fun Double.format(digits: Int) = java.lang.String.format("%.${digits}f", this)
However, any of these options leads to a compiler error of "unresolved reference". I don't think is a question of imports cause the compiler would suggest it.
Is there an easy way to do this?
Kotlin standard library for JS doesn't have anything like Double.format yet, but you can implement it easily with aforementioned toFixed function available in javascript:
fun Double.format(digits: Int): String = this.asDynamic().toFixed(digits)
fun Float.format(digits: Int): String = this.asDynamic().toFixed(digits)
This works because Double and Float in Kotlin are represented with Number data type in JS, so you can call toFixed() function on instances of those types.

Escape reserved words in an import

When using Java classes in Kotlin, sometimes they use identifiers that are reserved word in kotlin. The java interop documentation says you can use backtick (`) character but this doesn't work in imports. So how to escaped reserved words on import.
e.g. The tinkerpop library has a class called '__' but thats a Kotlin reserved so if I import it like below it gives an error.
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__
I can import it using the wild card like this:
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.*
but because I only use the one class then Intellij's code formatter replaces it with the previous version of the import that gives an error. (Which I guess is a bug in the intellij formatter as well)
For the answers that suggest using backtick ` works. It does not. This does not compile even on try.kotlinlang.org.
Assuming a class exists defined as
package blah
class `__` {
}
This is what happens when you import it with backticks.
Disclaimer: I am not a Kotlin user.
The Kotlin Grammar page ( https://kotlinlang.org/docs/reference/grammar.html#SimpleName ) states that the import keyword is followed by a SimpleName ("." SimpleName) where SimpleName is defined as either <java identifier> or "``" <java identifier> "``"
According to the above rules, each component that needs escaping should be surrounded in single backtick characters. As only the last name is reserved your code should look like this:
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.`__`
I tried using this in an online Kotlin tool ( http://try.kotlinlang.org/ ) and the syntax was accepted.
Update
I created a 2-file program in try.kotlinlang.org and I can reproduce the problem, and fix it.
So the issue isn't just that keywords and other reserved words need to be escaped with backticks (though in this case, the name __ (two underscores) is not a keyword in Kotlin, but that Kotlin does not seem to allow reserved names to even exist in-scope!
Here's my test-case:
File1.kt
package blah
class `__` {
fun foo(): Int {
return 5
}
}
File2.kt
import blah.__
fun test2() {
val us = __()
us.foo
}
This gives me this compile-time error:
File2.kt - Error:(1,) Names _, , _, ..., are reserved in Kotlin
If I change File2.kt to this, then it works fine:
import blah.__ as underscore
fun test2() {
val us = underscore()
us.foo
}
Using backticks doesn't seem to help at all, but it does give me unexpected errors:
import blah.`__` as `__`
fun test2() {
val us = `__`() <-- error is here
us.foo()
}
File2.kt - Error: (4, 13) Unresolved reference: __
Variations of the names with backticks and unescaped double-underscores yields no effect.
So it seems the solution is to alias the name to something else during import.
One method I've found that works is to import it with an alias which is ok but it does change the name used in code.
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__ as underscore
As specified in the docs, your import must look like:
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.`__`
Then to use the underscore symbol in the code you'll have to escape it every time, so an alias is the best solution:
`__`.foo()
Docs: https://kotlinlang.org/docs/reference/java-interop.html#escaping-for-java-identifiers-that-are-keywords-in-kotlin

Kotlin: Why can't I use one of my functions?

I am trying to use one of my defined functions that accepts a string yet the software won't compile.
fun passes(address: String) = Collections.frequency(addresses, address) <= CONNECTIONS_PER_IP
fun passes(remoteAddress: InetSocketAddress) = passes(remoteAddress.hostName)
I can't even call the string function using a custom string, for example passes("127.0.0.1").
None of the following functions can eb called with the arguments supplied.
passes(String) defined in abendigo.Firewall
passes(InetSocketAddress) defined in abendigo.Firewall
I presume you're using java.lang.String instead of kotlin.String in the Kotlin source code. Please use only kotlin.String instead, this is the type that string literals in Kotlin have (but in the bytecode it's still transformed to java.lang.String).
The issue was an import of java.lang.String. For some reason IntelliJ imported it.