Does the kotlin REPL have code completion? - kotlin

I just opened kotlinc (which apparently defaults to kotlin-jvm ?) and dropped in some hello-world type code:
data class Person(val name: String, val age: Int) {
val isAdult get() = age >= 20
}
Let's create an instance :
val p = Person("ab", 10)
Hopefully the repl will offer us the properties via tab key .. ?
p.<tab>
The repl beeps on each tab instead of offering the properties of that Person instance. "Just in case" I :quit and opened kotlinc-jvm explicitly - and got the same behavior. Is it to be believed that there were no code completion available? Am I missing some option to starting kotlinc ?

Update: JetBrains has now released ki, which supports auto completion (and more).
The kotlin repl currently does not support tab completion. See the official bug tracker for more details:
https://youtrack.jetbrains.com/issue/KT-14177,
https://youtrack.jetbrains.com/issue/KT-23036
If you use IntelliJ, you may want to try out scratch files. They work well for small bits of code and support code completion.

Intellij Kotlin-REPL does have code completion. It makes a ton of sense to use the IDE coming from the creators of the language JetBrains.

Related

Kotlin script: main function does not get called locally, unlike in online judge

I am trying to participate in online Codeforces contests using Kotlin.
My understanding is I should use Kotlin script if my code is contained within a single file.
If I run the following file locally (version 1.6.10):
kotlin just_main.main.kts
// just_main.main.kts
fun main() {
println("Hello World")
}
Nothing happens. I need to add an explicit call for it to actually execute main:
// top_level_call.main.kts
fun main() {
println("Hello World")
}
main()
So far, so normal. The problem occurs when I try to submit my solution to the Codeforces online judge. The judge expects no top-level code and runs the main function instead. So just_main runs fine, but top_level_call produces a compilation error:
Can't compile file:
program.kt:43:1: error: expecting a top level declaration
main()
^
This leads to the awkward situation of me having to add the main() call when I want to try my solution locally, but having to remove it every time I upload an attempt.
Is there a way to have my local Kotlin behave the same as the online judge, meaning implicitly running any main functions (meaning just_main would produce output)?
I haven't found a way to do this with Kotlin script files, but you can also use normal .kt files without having any classes in the file (my understanding is that Kotlin magically turns them into Java class bytecode/files):
kotlinc a.kt && kotlin AKt < a.in
This "runs" a.kt with standard input from a.in.
(And yes I only found this after I already wrote the question)

Is there a Kotlin "eval"

I have a bunch of strings like these in my already existing and quit big template file:
Hello $World I say hello to $User, too
I was thinking I could somehow let kotlin parse/search&replace this file as a kotlin string, and I'd just have to set the variables World and User to get an evaluated string... How is this possible?
This is not a kotlin source file, but a file that's beeing read by my kotlin program.
Why I want to do this? I used bash's envsubst before, and had to move away from this, since things were getting too complicated. But now I have no easy way to replace strings in a file anymore...
Thanks
What you want is called a template engine.
You don't really need an eval (which would allow running a full Kotlin application from a String) in this case.
For example, FreeMarker templates use a syntax that's similar to Kotlin template Strings, so a template may look like this:
<h1>Welcome ${user}!</h1>
Then, from Kotlin, you can evaluate the template with a Map holding the template bindings (variables the template can use) like this:
val user = "joe"
val bindings = mapOf("user" to user)
val cfg = new Configuration(Configuration.VERSION_2_3_29)
cfg.directoryForTemplateLoading = File("/where/you/store/templates")
val template = cfg.getTemplate("test.ftlh")
// write the resolved template to stdout
val out = OutputStreamWriter(System.out)
template.process(bindings, out)
See a Java example here: https://freemarker.apache.org/docs/pgui_quickstart_all.html
There are many other template engines, and the KTor site lists a few:
https://ktor.io/docs/working-with-views.html
If you're using KTor, BTW, it makes it much easier to use template engines... your framework may even have similar.
Warning: Please see my other answer first: you probably don't want to run a full Kotlin script just to parse some text file with variables... use a template engine for that.
It's possible to execute Kotlin scripts, i.e. eval Kotlin code, but it requires that you basically ship the Kotlin compiler with your application.
This GitHub project, KtsRunner, for example, does that, so you can do this:
val scriptContent = "5 + 10"
val fromScript: Int = KtsObjectLoader().load<Int>(scriptContent))
println(fromScript)
// >> 15
It requires some hacking though, is very slow and it uses a bunch of Kotlin "internal" APIs to work.
See the full list of libraries this project uses here:
https://github.com/s1monw1/KtsRunner/blob/master/lib/build.gradle.kts#L21
A "proper" KEEP proposal (discussion here) exists to add first-class support for this in Kotlin, but it's not finalized yet.
Currently, it looks something like this:
fun evalFile(scriptFile: File): ResultWithDiagnostics<EvaluationResult> {
val compilationConfiguration = createJvmCompilationConfigurationFromTemplate<MainKtsScript>()
val evaluationConfiguration = createJvmEvaluationConfigurationFromTemplate<MainKtsScript>()
return BasicJvmScriptingHost().eval(scriptFile.toScriptSource(), compilationConfiguration, evaluationConfiguration)
}
But it'll probably change before being released.

Functional Programming in Kotlin, Manning book: Arrow code needs update

Though this book was just finalized in August, they appear to be using some deprecated Arrow library code in their code examples.
Here's an example from Chapter 6:
Listing 6.18. State propagation using a for-comprehension.
val ns2: State<RNG, List<Int>> =
State.fx(Id.monad()) {
val x: Int = int.bind()
val y: Int = int.bind()
val xs: List<Int> = ints(x).bind()
xs.map { it % y }
}
Using latest Arrow libs, the above snippet fails syntax checker in Idea. 'Id' is not recognized, and Arrow docs say it was slated for deprecation.
Wondering if anyone can help refactor this to current Arrow version, or recommend previous version this will work with?
I was able to contact the authors on this issue.
Currently, there are no updated code examples for the latest Arrow libs, but they may release that in the future.
In the meantime, there is a git repository of the code (Idea project) that works with the older libs. It can be found here: Functional Programming in Kotlin
I've been recreating the exercise files within the project to avoid seeing the answers before I complete the exercises, and it works.

Annotation class does not validate input as enum in Kotlin

I'd like to create annotation instead of enum use it for when statement
#Retention(AnnotationRetention.SOURCE)
#IntDef(SELECT.toLong(), WEAR.toLong(), BAND.toLong())
annotation class CurrentState
companion object {
const val SELECT = 0
const val WEAR = 1
const val BAND = 2
}
private fun handleFragment(#CurrentState state:Int) {
val fragment:Fragment =
when(state){
SELECT -> SelectDeviceFragment.newInstance()
WEAR -> ConnectWatchFragment.newInstance()
BAND -> SelectDeviceFragment.newInstance()
}
From my understanding, this code should prevent me from performing following code:
handleFragment(5)
and when statement should not ask me to add else statement, as expected from enum
What I'm doing wrong or misunderstand?
From https://discuss.kotlinlang.org/t/intdef-and-stringdef-not-being-checked-at-compile-time/7029:
This checking doesn’t come from the compiler, but from Android lint. Work to make android lint language independent is being done, but if I’m not mistaken you’ll need a newer version of Android Studio for it.
And Android Studio 3.1 blog post mentions lint checks for Kotlin as a feature (though it doesn't say whether this check specifically is supported).
The #IntDef annotation is part of the Android framework. The compiler is not aware of any specific semantics of this annotation, and is not able to use it for checking the exhaustiveness of when statements.
Moreover, even with the annotation, you can call handleFragment(5). Such code will not be a compiler error, it will only be reported as a lint warning.

What does `$iv` appended to a symbol mean in the IntelliJ debugger?

In the IntelliJ debug window, some variables have $iv appended to their name:
What is the information that IntelliJ is trying to convey? A quick look at the documentation did not bring the answer.
It seems generated by Kotlin compiler for inline functions:
const val INLINE_FUN_VAR_SUFFIX = "\$iv"
That const is defined here and used here.