I am from a background of Javascript trying to learn some Kotlin.
I know i can define my function by
fun add(a: Int , b: Int): Int{
return a+b
}
I am trying this
val add = {
a:Int,b:Int->
println("I am calculating the sale => no body you guy [$x+$y]");
//works
}
val add = { a:Int ,b : Int ->
//How do i return from this function
}
Also Is this a right way to define Kotlin functions? and Whats the difference with the first way ?
Also Is this a right way to define Kotlin functions? and Whats the difference with the first way ?
This is not even "a way to define Kotlin functions".
In JavaScript, all functions are reified: they are first-class values you can refer to from variables and pass around. Not so in Kotlin, just as in many other languages like Java, C++, Objective C and so on.
A function is just a declaration, you can call it but you can't otherwise directly refer to it. Separate language features allow you to create functional objects that delegate to these functions, and you can pass these objects around.
Therefore,
fun add(a: Int , b: Int): Int {
return a + b
}
is a function declaration and
val add = {a: Int, b: Int ->
a + b
}
is four things:
declaration of a variable add
declaration of an anonymous implementation of the functional type (Int, Int) -> Int
instantiation of this anonymous type, resulting in a functional object
assignment of the object to the variable add.
The object has a method invoke(a: Int, b: Int): Int whose implementation you have given in the block:
fun invoke(a: Int, b: Int): Int {
return a + b
}
You can call it explicitly:
val result = add.invoke(a, b)
and on top of that Kotlin defines syntax sugar that allows you to omit the explicit .invoke.
You don't need the explicit return there
val add = { a: Int, b: Int ->
a + b
}
add(2, 3) // => 5
Hopefully this will work.
val onChange = {
a:Int,b:Int->
println("I am calculating the sale => no body you guy [$x+$y]");
//works
}
val add = { a:Int ,b : Int ->
println("Sunm ${a+b}")
//How do i return from this function
}
Log.v("Response", add(4,3))
Output
V/Response: Sum 7
You can't return values in kotlin like this, it will give error of type mismatch as you havn't declared any return type :
fun add(a: Int , b: Int){
return a+b
} //wrong
we declare return type in kotlin as :
fun add(a: Int , b: Int) : Int{
return a+b
}
Secondly,
val add = { a:Int ,b : Int ->
}
this is not a function, its a declaration of value assignment
In kotlin we declare function by adding "fun" before your function name as
//you can add access modifiers(private,public,protected) if needed just before "fun"(by default its public)
fun add (){ //if it returns any value then add ": {datatype}" just right of "()"
//your code here
}
Hope it helped you :)
Related
package algorithms
import algorithms.util.IOUtils
object Calculator {
/* static abstract class Operation {
* private Function logic; //functional interface
* Operation(Function f) { this.logic = f );
* }
*/
sealed class Operation(val logic : (Int, Int)-> Int)
/* define singleton types 'ADD', 'SUB', 'MUL', 'DIV' - equivalent to inner class definitions in Java */
/* static class ADD extends Operation {
* ADD(){
* super((int x, int y)-> x+y);
* }
* }
*/
object ADD: Operation({ x: Int , y: Int -> x+y } )
object SUB: Operation({ x: Int , y: Int -> x-y })
object MUL: Operation({ x: Int , y: Int -> x*y })
object DIV: Operation({ x: Int , y: Int -> x/y })
private fun getOperationFromChar(ch : Char): Operation? {
return when(ch){
'+' -> ADD
'-' -> SUB
'*' -> MUL
'/' -> DIV
else -> null
}
}
fun eval(ch: Char, x: Int, y: Int): Int? {
val op : Operation? = getOperationFromChar(ch)
return op?.logic?.invoke(x,y)
}
}
fun main(){
println("Result : ${Calculator.eval(
IOUtils.readChar("Enter desired operation (+,-,*,/) "),
IOUtils.readInteger("Enter first number"),
IOUtils.readInteger("Enter second number"))}")
}
The above code works fine, however, IntelliJ forces me to make logic in
return op?.logic?.invoke(x,y) nullable
Although the definition of Operation sealed class Operation(val logic : (Int, Int)-> Int) has nowhere mentioned that it can be null.
I would image if the definition of the Operation object was sealed class Operation(val logic : ((Int, Int)-> Int)?) then it would make sense, but it is not so.
What is going on here?
It's because the return value of getOperationFromChar() is nullable.
It's not your operation function that returns a nullable value. op itself is already nullable. You defined it yourself with val operation: Operation?. When you use ?. calls, the results are always nullable because null will be the result if there was no object to call the function on.
The input of your getOperationFromChar() function is a Char. A Char can be any of many thousands of possible values, not just the four that you have in your when statement. That's why the compiler is enforcing an else branch. If you want to avoid returning a nullable, you could choose to throw an error if an invalid input is given:
private fun getOperationFromChar(ch : Char): Operation {
return when(ch){
'+' -> ADD
'-' -> SUB
'*' -> MUL
'/' -> DIV
else -> error("Invalid input $ch")
}
}
Then you could define val op: Operation and it would be able to accept the result of this function as non-nullable.
Sealed classes help avoid the need for an else branch when the sealed class is the type of the when's subject. Then the compiler can be sure you have a branch for every possible input. Your function is the opposite case, where your sealed class type is the output, not the input.
By the way, it is more sensible for you to use an enum instead of a sealed class for this case, because none of the children of your sealed class have unique properties or functions.
If you take the chained evaluation apart, it becomes clear:
fun eval(ch: Char, x: Int, y: Int): Int? {
val op: Operation? = getOperationFromChar(ch)
val logic: ((Int, Int) -> Int)? = op?.logic
val retval: Int? = logic?.invoke(x, y)
return retval
}
logic is not typed ((Int, Int) -> Int) but ((Int, Int) -> Int)?, because if op is null, the result of op?.logic will also be null.
It is because op is nullable; if you set type of op as Operation you don't need to check the nullability of logic.
In fact, it checks the nullability of whole op?.logic to call invoke() method; that can throw NullPointerException due to op nullability.
The safe call operator(?.) returns null if the value to the left is null, otherwise continues to evaluate the expression to the right.
for example
val x:Int? = 4
x?.dec()?.inc()?.dec()
x?.let {
it.dec().inc().dec()
}
I have made an extension functions for BigIntegers, allowing me to add Ints to them.
operator fun BigInteger.plus(other: Int): BigInteger = this + other.toBigInteger()
// Allowing me to do
val c = myBigInt + 3
I have also made a Counter class, holding bigintegers for various keys, for easy counting. Since doing counter["1"] += myBigInt isn't allowed on standard maps (it's nullable), I have added a custom getter that returns a default value, making this possible.
class Counter<K>(val map: MutableMap<K, BigInteger>) : MutableMap<K, BigInteger> by map {
constructor() : this(mutableMapOf())
override operator fun get(key: K): BigInteger {
return map.getOrDefault(key, BigInteger.ZERO)
}
I can then use it like this
val counter = Counter<String>()
c["ones"] += 5.toBigInteger()
Problem is that I cannot use it like this:
c["ones"] += 5 // doesn't work, "Kotlin: No set method providing array access"
but this should be equivalent to this, which works, since it should use my extension operator on the bigint:
c["ones"] = c["ones"] + 5 // works
Why doesn't this work?
I've tried adding a set method for Ints, but then I see a very weird behavior. Kotlin will do the calculation correct, but then convert the BigInteger to an Int before passing it to my class! Example:
inline operator fun BigInteger.plus(other: Int): BigInteger {
val bigInteger = this + other.toBigInteger()
println("calculated bigint to $bigInteger")
return bigInteger
}
class Counter<K>(val map: MutableMap<K, BigInteger>) : MutableMap<K, BigInteger> by map {
constructor() : this(mutableMapOf())
override operator fun get(key: K): BigInteger {
return map.getOrDefault(key, BigInteger.ZERO)
}
operator fun set(key: K, value: Int) {
println("setting int $value")
map[key] = value.toBigInteger()
}
}
val c = Counter<String>()
c["1"] = "2192039569601".toBigInteger()
c["1"] += 5
println("result: ${c["1"]}")
c["1"] = "2192039569601".toBigInteger()
c["1"] = c["1"] + 5
println("result: ${c["1"]}")
Which prints
calculated bigint to 2192039569606
setting int 1606248646 <--- why does it call the int setter here?
result: 1606248646
calculated bigint to 2192039569606
result: 2192039569606
Why does Kotlin do the BigInt summation, but converts it back to an Int before sending to my setter?
Update
Since a comment suggest this is a compiler issue, any other ideas?
My ultimate goal here, was to have a counter of big integers, but to be able to easily add ints to it.
Adding this as a set function, makes it being called for both ints and bigints, so I can do the proper assignment myself. However, it will also then allow someone to add floats that will crash at runtime.
operator fun set(key: K, value: Number) {
map[key] = when (value) {
is BigInteger -> value
is Int -> value.toBigInteger()
else -> throw RuntimeException("only ints")
}
}
Any tips?
Notice that c["ones"] += 5 can be translated into calls in two ways:
c.set("ones", c.get("ones").plus(5))
c.get("ones").plusAssign(5)
The first way is what your code currently translates to, because you don't have a plusAssign operator defined. As I said in the comments, there is a bug in the compiler that prevents the operators from resolved correctly. When resolving c["ones"] += 5, It seems to be trying to find a set operator that takes an Int instead (possibly because 5 is an Int), which is unexpected. If you modify the code in the bug report a little, you can even make it throw an exception when executed!
class Foo {
operator fun get(i: Int) : A = A()
operator fun set(i: Int, a: A) {}
operator fun set(i: Int, a: Int) {}
}
class A {
operator fun plus(b: Int) = A()
}
class B
fun main(args: Array<String>) {
val foo = Foo()
foo[0] = foo[0] + 1
foo[0] += 1 // this compiles now, since there is a set(Int, Int) method
// but A can't be casted to Int, so ClassCastException!
}
It is rather coincidental (and lucky) in your case, that the compiler knows how to convert from BigInteger (or any other Number type actually) to Int, using Number#intValue. Otherwise the program would have crashed too.
A natural alternative way is to define the plusAssign operator, so that the assignment gets translated the second way. However, we can't do it on BigInteger, because plusAssign would need to mutate this, but BigInteger is immutable. This means that we need to create our own mutable wrapper. This does mean that you lose the nice immutability, but this is all I can think of.
fun main() {
val c = Counter<String>()
c.set("1", "2192039569601".toMutableBigInteger())
c.get("1").plusAssign(5)
println("result: ${c["1"]}")
}
data class MutableBigInteger(var bigInt: BigInteger) {
operator fun plusAssign(other: Int) {
bigInt += other.toBigInteger()
}
}
fun String.toMutableBigInteger() = MutableBigInteger(toBigInteger())
class Counter<K>(val map: MutableMap<K, MutableBigInteger>) : MutableMap<K, MutableBigInteger> by map{
constructor() : this(mutableMapOf())
override operator fun get(key: K): MutableBigInteger {
return map.getOrPut(key) { MutableBigInteger(BigInteger.ZERO) }
}
operator fun set(key: K, value: Int) {
println("setting int $value")
map[key] = MutableBigInteger(value.toBigInteger())
}
}
Notably, getOrDefault is changed to getOrPut - when a value is not found, we want to put the zero we return into the map, rather than just returning a zero that is not in the map. Our changes to that instance wouldn't be visible through the map otherwise.
I made a function which returns all factors of an integer. But the problem is that it gives an error that the return type is Unit instead of mutableListOf. my code:
fun get_factors(num: Int) {
var factors = mutableListOf<Int>()
for (x in 1..num) {
if (x % num == 0) {
factors.add(x)
}
}
return factors
}
fun main() {
print(get_factors(18))
}
I tried doing:
fun get_factors(num: Int): mustableListOf {
var factors = mutableListOf<Int>()
for (x in 1..num) {
if (x % num == 0) {
factors.add(x)
}
}
return factors
}
fun main() {
print(get_factors(18))
}
but it says mutableListOf not defined.
I just started learning Kotlin today so I am a total beginner with Kotlin. Please help me out with this.
You seem to have confused the type MutableList<Int>, with the function mutableListOf.
Since the type name is MutableList<Int>, you should do:
fun get_factors(num: Int) : MutableList<Int> {
...
}
Or, if the caller doesn't need to modify the list, you can just return List<Int> too:
fun get_factors(num: Int) : List<Int> {
...
}
I can see why this is confusing - to create an instance of a type, you normally just add () to the end of the type name, so if mutableListOf() creates a list, you'd think that mutableListOf is the type name. However, this is actually calling the global function called mutableListOf, which returns an instance of MutableList<T>.
One way to distinguish between these is to look at the first letter. Type names usually begin with a capital letter, whereas function names begin with a small letter.
The Idioms section of the official Kotlin docs contains this example:
Builder-style usage of methods that return Unit
fun arrayOfMinusOnes(size: Int): IntArray {
return IntArray(size).apply { fill(-1) }
}
As the function apply returns the generic type, and I thought Unit is as same as void in Java, this section is suggesting we can use a void method in builder-style? That doesn't make sense to me - what's it trying to say?
The point it's trying to make is that if you just did traditional Java builder style, like this:
return IntArray(size)
.fill(-1)
then it wouldn't compile, because it's of type Unit, not IntArray.
So traditionally, you'd have to do something like this:
val ret = IntArray(size)
ret.fill(-1)
return ret
apply enables you to avoid this, because the return type is still of type IntArray (or T, in general).
Take this one:
class X {
var a: Int? = null
var b: Int? = null
fun first(a: Int) = apply { this.a = a }
fun second(b: Int) = apply { this.b = b }
}
X().first(2).second(3)
The apply functions are used to return the instance of X after setting the property. This enables builder-style call of both methods. If apply were removed, the function would return Unit.
I have the following function in Kotlin:
fun max(a: Int, b: Int): Int {
return if (a > b) a else b
}
which could be simplified to:
fun max(a: Int, b: Int) = if (a > b) a else b
In the previous definition, the returned type of the function has been omitted, and this is known as expression body. I am wondering if there exists other cases in which it is possible to omit the return type of a function in Kotlin.
Functions with block body must always specify return types explicitly, unless it's intended for them to return Unit.
If a function does not return any useful value, its return type is Unit. Unit is a type with only one value - Unit. This value does not have to be returned explicitly
fun printHello(name: String?): Unit {
if (name != null)
println("Hello ${name}")
else
println("Hi there!")
// `return Unit` or `return` is optional
}
The Unit return type declaration is also optional. The above code is equivalent to
fun printHello(name: String?) {
...
}
when the return type is Unit
fun printHello(): Unit {
print("hello")
}
is the same as
fun printHello() {
print("hello")
}
also, is the same as
fun printHello() = print("hello")
Usually, a function must declare it's return type. But if some functions consist of a single expression then we can omit the curly braces and the return type and uses the = symbol before the expression rather than the return keyword. This type of functions are called Single Expression Functions.
Example:
fun add(a: Int, b: Int): Int {
return a + b
}
This code can be simplified to:
fun add(a: Int, b: Int) = a + b
The compiler will enforce you to do this.