Am using IntelliJ IDEA 2019.1.2 (Ultimate Edition) with Kotlin (kotlinc-jvm 1.3.31) on macOS Mojave 10.14.5.
When I created a Kotlin JVM project and added a Kotlin file entitled "Nullability.kt" with the following code (extension function with a main() method):
fun List<Int>.allNonZero() = all { it > 0 }
fun main() {
val list1 = listOf(1, 2, 3)
list1.allNonZero() eq true
}
IntelliJ IDEA highlights "eq" in red and it states:
Kotlin: Unresolved reference: eq
How to resolve this from within IntelliJ IDEA?
Found it, inside the Coursera course, Kotlin has a Playground where the code is hidden but you can expand it and view it by clicking on the + sign.
infix fun <T> T.eq(other: T) {
if (this == other) println("OK")
else println("Error: $this != $other")
}
Related
I have the following code in Kodein module
bind<Manager>() with factory { strategy: OrderStrategyType ->
val manager: Manager = when (strategy) {
OrderStrategyType.VOLATILITY -> VolatilityManager()
else -> SimpleManager()
}
return#factory manager
}
where Manager is interface and VolatilityManager() and SimpleManager() are implementing it.
IntelliJ suggests to inline variable manager, if I apply suggestion I receive the code:
bind<Manager>() with factory { strategy: OrderStrategyType ->
return#factory when (strategy) {
OrderStrategyType.VOLATILITY -> VolatilityManager()
else -> SimpleManager()
}
}
However, while IDE detects no problems with this code, it doesn't compile with
Type inference failed: infix fun <C, A> with(binding: KodeinBinding<in C, in A, out Manager>): Unit
cannot be applied to
(Factory<Any?, OrderStrategyType, Any>)
Honestly, I don't understand compiler error. Inference looks obvious for me. Should I rewrite my code, if yes, how?
Regarding this code, with Kotlin 1.3.72 their is no issue.
interface A
class B: A
class C: A
bind<A>() with factory { b: Boolean ->
when(b) {
true -> B()
false -> C()
}
}
If your classes implements/extends more than one interfaces/classes type inference may not now what type you want to return.
Force cast seems to do the trick
interface A
interface X
class B: A, X
class C: A, X
bind<A>() with factory { b: Boolean ->
when(b) {
true -> B()
false -> C()
} as A
}
PS: you don't need the return#factory as when is an expression.
Is there a way to get the Kotlin compiler to tell me exactly what type it thinks an expression is? So e.g. given (1 + 2) it would print Int.
Better example: (if (args.isEmpty()) 1 else 2.0) should print Any, because that's what the compiler thinks is the type of that term, because the best it can do at compile time is infer the most specific supertype of Int and Double.
fun main() {
println(typeName { if (true) 1 else 2.5 }) // Any
println(typeName { 1 + 2 }) // Int
println(typeName { f() }) // String
}
fun f(): String = TODO() // throws NotImplementedError
inline fun <reified T> typeName(block: () -> T): String? = T::class.simpleName
If you need this functionality while you're editing your code, IntelliJ based IDEs support this. The action is called Type Info, and you can access it with Ctrl + Shift + P (⌃⇧P on macOS) by default.
I'm trying to create an IntelliJ Plugin to automatically create a project type. I've gotten as far as making a custom ModuleBuilder with an area for inserting a Group ID and Artifact ID.
When the project is created, I want it to immediately come with gradle support, as well as a filled out build.gradle file and other stuff.
Does anyone know how to do this?
Thanks!
class SpigotKtWizard : ModuleBuilder() {
override fun setupRootModel(modifiableRootModel: ModifiableRootModel?) {}
override fun getModuleType(): ModuleType<*> {
return SpigotKtModuleType.instance
}
override fun createWizardSteps(wizardContext: WizardContext, modulesProvider: ModulesProvider): Array<ModuleWizardStep> {
return arrayOf(BuildOptionsStep())
}
override fun createProject(name: String?, path: String?): Project? {
val project = super.createProject(name, path) ?: return null
setupModule()
val d = project.baseDir.createChildData(this, "Test")
File(d.path).writeText("Testing boyyyy")
return project
}}
What I have so far.
If you're creating a Gradle project, it's much better to use a different API - GradleFrameworkSupportProvider. Then the user will choose Gradle in the new project wizard, and your framework in the list of frameworks to add. As an example, you can refer to the implementation in the Kotlin plugin.
I was trying to learn higher order functions from the first example of this video. Here's my code and output.
Code
fun lowercase(value: String) = value.toLowerCase()
fun higherOrder(value:String, op: (String) -> String) : String {
println("Executing higher order fun $op")
return op(value)
}
fun main(args: Array<String>) {
println(higherOrder("HELLO", ::lowercase))
println(higherOrder("hello", {it -> lowercase(it)}))
println(higherOrder("HeLlo", { x -> lowercase(x) }))
println(higherOrder("Hello", { lowercase(it) }))
}
Output
Executing higher order fun function lowercase (Kotlin reflection is not available)
hello
Executing higher order fun Function1<java.lang.String, java.lang.String>
hello
Executing higher order fun Function1<java.lang.String, java.lang.String>
hello
Executing higher order fun Function1<java.lang.String, java.lang.String>
hello
Process finished with exit code 0
So my question is, why does it print Kotlin reflection is not available?
Full reflection requires the kotlin-reflect library in addition to kotlin-stdlib.
If full reflection is available it will probably have a more comprehensive toString(), hence the message.
add kotlin-reflect library
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.0'
I try it, it works.
The last time I used Kotlin was Dec 2015 when I used it to solve a couple of Project Euler problems.
This time I want to try its interoperability with Javascript. Now my question is, how do we import/use existing Javascript libraries in Kotlin?
I've seen some people using the native keyword, and I just want a brief explanation of it.
There's no native keyword anymore, there's #native annotation. Currently, it's working solution and you can use it with 1.0.x branch of Kotlin compiler. However, we are going do deprecate this annotation in favour of extern annotations, so be prepared to rewrite your code eventually for 1.1.x branch.
When you put #native annotation on a class or on a top-level function, two things happen:
Its body is not compiled to JavaScript.
Compiler references this class or function directly, without package name and mangling.
I think it's easier to explain by providing example of a JavaScript library:
function A(x) {
this.x = x;
this.y = 0;
}
A.prototype.foo = function(z) {
return this.x + this.y + z;
}
function min(a, b) {
return a < b ? a : b;
}
and a corresponding Kotlin declaration
#native class A(val x: Int) {
var y: Int = noImpl
fun foo(z: Int): Int = noImpl
}
#native fun min(a: Int, b: Int): Int = noImpl
Note that noImpl is a special placeholder that's required because of non-abstract functions required bodies and non-abstract properties require initializers. BTW, when we replace #native with extern, we'll get rid of this noImpl.
Another aspect of interoperation with JS libraries is including libraries via module system. Sorry, we don't have any solution right now (but are going to release it soon). See proposal. You can use the following workaround for node.js/CommonJS:
#native interface ExternalModule {
fun foo(x: Int)
}
#native fun require(name: String): dynamic = noImpl
fun main(args: Array<String>) {
val module: ExternalModule = require("externalModule")
module.foo(123)
}
where external module is declared like this
function foo(x) {
return x + 1;
}
module.exports = { foo : foo };
I added a simple barebone project as an example of how to do Kotlin2Js.
https://bitbucket.org/mantis78/gradle4kotlin2js/src
Here is the gradle file that is the main recipe.
group 'org.boonhighendtech'
version '1.0-SNAPSHOT'
buildscript {
ext.kotlin_version = '1.1.2-5'
repositories {
maven { url 'http://dl.bintray.com/kotlin/kotlin-dev/' }
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin2js'
repositories {
maven { url 'http://dl.bintray.com/kotlin/kotlin-dev/' }
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version"
}
build {
outputs.dir("web/")
}
build.doLast {
copy {
from 'src/main/webapp'
into 'web/'
include '**/*.html'
include '**/*.js'
include '**/*.jpg'
include '**/*.png'
}
configurations.compile.each { File file ->
copy {
includeEmptyDirs = false
from zipTree(file.absolutePath)
into "${projectDir}/web"
include { fileTreeElement ->
def path = fileTreeElement.path
path.endsWith(".js") && (path.startsWith("META-INF/resources/") || !path.startsWith("META-INF/"))
}
}
}
}
clean.doLast {
file(new File(projectDir, "/web")).deleteDir()
}
compileKotlin2Js {
kotlinOptions.outputFile = "${projectDir}/web/output.js"
kotlinOptions.moduleKind = "amd"
kotlinOptions.sourceMap = true
}
Firstly, you can assign a dynamic variable then essentially code it like you code JavaScript, dynamically.
e.g.
val jQuery: dynamic = passedInJQueryRef
jQuery.whateverFunc()
But if your intention is to have it typed, then you need to introduce types to the external library. One way is to make use of the relatively extensive libraries of typedefs by https://github.com/DefinitelyTyped/DefinitelyTyped
Find the ts.d there, then run ts2kt (https://github.com/Kotlin/ts2kt) to get your Kotlin files. That typically gets you there. Occasionally, certain conversions are not well done. You will have to hand fix the conversion. E.g. snapsvg's snapsvg.attr() call takes in "{}" but it got converted to some strange interface.
It was
fun attr(params: `ts$2`): Snap.Element
And I replaced it with
fun attr(params: Json): Snap.Element
and it works like a charm.
Kotlin 1.1 introduces the externalmodifier that can be used to declare functions and classes written directly in JS, see http://kotlinlang.org/docs/reference/js-interop.html