#FunctionalInterface
interface Interf {
fun m1(num: Int)
}
fun main() {
val a: Interf = { 34 -> println("Hello world !!") }
}
Upon compilation getting this error
Unexpected tokens (use ';' to separate expressions on the same line)
Is Kotlin lambda function syntax is bit different from Java Lambda Expression?
First of all, this will not compile in java as well:
#FunctionalInterface
interface Interf {
void m1(int num);
}
class Main {
public static void main(String[] args) {
Interf f = 34 -> System.out.println("Hello world !!"); //compilation error here
}
}
With pretty the same error:
error: ';' expected
Interf f = 34 -> System.out.println("Hello world !!");
^
To make it correct, name of the lambda parameter should be changed, so that it become a valid java identifier.
For instance, this will compile:
Interf f = x -> System.out.println("Hello world !!");
Now, returning back to Kotlin. Version 1.4 introduces syntax for SAM conversions:
fun interface Interf {
fun m1(num: Int)
}
It could be instantiated with:
val a = Interf { println("Hello world !!") }
Convention of implicitly declared it parameter referring to lambda only parameter is preserved here.
Related
I am new to kotlin.
I was working on some design patterns used in kotlin. I came across abstract factory design and I keep getting this error while creating an object for the class. I tried the other solutions on stack overflow such as curly braces missing, but in vain. I've attached the entire code to resolve. Can someone help me how to resolve this? Thanks in advance.
The error in console:
Unexpected tokens (use ';' to separate expressions on the same line)
The main.kt code:
object AAbstractFactoryDesignPattern{
internal interface IAndroid{
fun GetModelDetails(): String
}
internal interface IiOS{
fun GetModelDetails(): String
}
internal interface IMobile{
fun GetAndroidPhone() : IAndroid
fun GetiOsPhone() : IiOS
}
internal class SamsungGalaxy : IAndroid{
override fun GetModelDetails(): String {
return "Model: Samsung Galaxy - RAM: 2GB - Camera: 13MP"
}
}
internal class IphoneFour: IiOS{
override fun GetModelDetails(): String {
return "Model: Iphone 4 - RAM: 1GB - Camera: 12MP"
}
}
internal class Samsung : IMobile{
override fun GetAndroidPhone(): IAndroid {
return SamsungGalaxy()
}
override fun GetiOsPhone(): IiOS {
return IphoneFour()
}
}
internal class MobileClient(factory: IMobile){
var androidPhone: IAndroid
var iOSPhone: IiOS
fun GetAndroidPhoneDetails(): String{
return androidPhone.GetModelDetails()
}
fun GetIOSPhoneDetails(): String{
return iOSPhone.GetModelDetails()
}
init {
androidPhone = factory.GetAndroidPhone()
iOSPhone = factory.GetiOsPhone()
}
}
#JvmStatic
fun main(args : Array<String>){
val samsungMobilePhone: Samsung() //error line
val samsungClient: MobileClient(samsungMobilePhone) //error line
println(samsungClient.GetAndroidPhoneDetails())
println(samsungClient.GetIOSPhoneDetails())
}
}
When declaring a variable, a colon (:) is for explicitly specify the variable's type. It looks like the colons on the error line should be equals (=) instead.
Try changing your "error lines" to this:
val samsungMobilePhone = Samsung() //error line
val samsungClient = MobileClient(samsungMobilePhone) //error line
Alternatively, if you want to be explicit about the type:
val samsungMobilePhone: IMobile = Samsung() //error line
val samsungClient: MobileClient = MobileClient(samsungMobilePhone) //error lines
I'm trying to introduce the following (simplified) DSL:
fun <T> myDsl(specFn: DslSpec<T>.() -> Unit) {
val value = DslSpec<T>().apply(specFn).fn!!()
println("value is: $value")
}
class DslSpec<T> {
internal var fn: (() -> T)? = null
fun getValue(fn: () -> T) {
this.fn = fn
}
}
fun testCase() {
myDsl {
getValue {
"abc"
}
}
}
But it fails to infer T based just on the returned type of getValue ("Not enough information to infer type variable T"). I kind of see how it could be a very hard task to do for a compiler, but thought maybe there are already some tricks to make constructs like this work?
If you're using a version of Kotlin < 1.6.0, you should add #BuilderInference to the specFn argument:
fun <T> myDsl(#BuilderInference specFn: DslSpec<T>.() -> Unit) {
...
}
https://pl.kotl.in/__xy04j88
If you're using a version >= 1.6.0, you should either use the annotation as well, or both your declarations and their usages must be compiled with the compiler argument -Xenable-builder-inference.
I am trying to convert one of the java function which takes java.util.function.Function<T, R> to Kotlin using IDEA 2019.3 Kotlin multiplatform library.
But t I could not find a way to do an equivalent function in kotlin. I can see here that there is Function1 to do a java interoperability but I am not able to do any import from import kotlin.jvm.functions.*
I am trying Kotlin for the first time. Could someone please tell what am I doing wrong.
Update- Please see my java code
import java.util.function.Function;
public class A {
Function<String, String> function;
public A(Function<String, String> function) {
super();
this.function = function;
}
public String convert(String input) {
return function.apply(input);
}
}
Not clear about your question, but assuming you are trying to duplicate functionality from Java:
In Kotlin, you do not use Function interfaces directly because functions are first-class. The Function1, Function2, etc. classes are only used to make functions available to Java code and the JVM.
If you want to create the equivalent of a Java Function<T, R>, you would define a function using either Kotlin's fun or lambda syntax.
fun getStringLength(x: String): Int {
return x.length
}
//...
val functionReference = ::getStringLength
// Java code will treat this as a Function1<String, Int>
or
val function = fun (x: String): Int {
return x.length
}
// Java code will treat this as a Function1<String, Int>
or
val functionReference = { x: String -> x.length }
// Java code will treat this as a Function1<String, Int>
To declare that a function takes a function as a parameter, you use (input) -> output syntax as the variable type:
fun <T, R> doSomething(functionalReference: (T) -> R) {
//
}
You can call a function using its referenced name:
fun <T, R> doSomething(input: T, functionalReference: (T) -> R): R {
return functionalReference(input)
}
Sounds like you want to convert a Java function that accepts a Function to an equivalent Kotlin function.
Example:
Java
public class JavaFunctions {
public static <T,R> void runAFunction(Function<T, R> userFunction){
userFunction.apply(null);
}
}
Kotlin (These two functions are equivalent)
class KotlinFunctions{
companion object{
#JvmStatic
fun <T,R> runAFunction(userFunction:(T?) -> R?){
userFunction.invoke(null);
}
#JvmStatic
fun <T,R> runAFunction2(userFunction: Function1<T?, R?> ){
userFunction.invoke(null);
}
}
}
TL;DR
In Kotlin 1.3.61 (or newer), is there any way to make a non-local return from a lambda that is passed as the argument for a function parameter whose type is an interface that extends kotlin.jvm.functions.Function0<Unit>?
Details
In the following Kotlin 1.3.61 code, I get compilation errors on the code lines after the comments that specify the errors.
It looks like I cannot make a non-local return from an enclosing function if the return is in a lambda passed to an inline function that accepts an interface that extends Function0<Unit>.
It works, however, if the receiving function accepts a Function0<Unit> (or a () -> Unit) instead of the sub-interface.
Is there any way to make a non-local return work from an interface that extends Function0<Unit>?
If not, is this either a bug in the Kotlin compiler, or is this a feature that is not yet supported by Kotlin?
If the latter, is there any existing request for enhancement?
If no request exists, is this a feature that could / should be supported by Kotlin?
inline fun a(x: () -> Unit) {
x()
}
fun b(): Int {
a {return 1}
return 2
}
inline fun c(x: Function0<Unit>) {
x()
}
fun d(): Int {
c {return 3}
return 4
}
interface F: Function0<Unit>
inline fun e(x: F) {
x()
}
fun f(): Int {
// ERROR
// 'return' is not allowed here
// Type mismatch: inferred type is () -> [ERROR : Return not allowed] but F was expected
e {return 5}
return 6
}
fun g(): Int {
// ERRORS
// Interface F does not have constructors
// 'return' is not allowed here
e(F {return 7})
return 8
}
fun h(): Int {
// ERROR
// 'return' is not allowed here
e({return 9} as F)
return 0
}
println(b()) // properly prints 1 if code with errors is commented out
println(d()) // properly prints 3 if code with errors is commented out
println(f()) // should print 5
println(g()) // should print 7
println(h()) // should print 9
Why does kotlin report Property must be initialized or be abstract. The object construction is never finished, so it should not matter whether a is initialized or not. Could a case be demonstrated where this would be a problem?
class Foo {
private val a: Int
init {
a = 42
throw Exception()
}
}
fun main() {
Foo()
}
kotlin playground
However these work just fine
fun bar() {
throw Exception()
}
class Foo {
private val a: Int
init {
a = 42
bar()
}
}
fun main() {
Foo()
}
kotlin playground
class Foo {
private val a: Int = throw Exception()
}
fun main() {
Foo()
}
kotlin playground
Similar java code works as expected:
public class Test {
private static class Foo {
private final int a;
public Foo() throws Exception {
a = 42;
throw new Exception();
}
}
public static void main(String []args) throws Exception {
new Foo();
}
}
The question is very well answered in the below link.
Kotlin: why do I need to initialize a var with custom getter?
Essentially it boils down to having a backing field for every "val" (property) . If you can provide a backing field, you need not initialize the field. Below is a small example of it.
class Foo {
private val a: Int
get() = getValue()
}
fun getValue():Int {
throw Exception()
}
fun main() {
Foo()
}
Similar java code works as expected:
Java initializes fields to 0 (or null/false depending on type) by default. You can see it e.g. by printing a's value before the a = 42 line.
Kotlin doesn't, because this implicit initialization makes it too easy to forget to initialize a property and doesn't provide much benefit. So it requires you to initialize all properties which have backing fields.
It seems to be a compiler bug as Alexey suggested
There is similar issue posted on Kotlin bug tracer.