how to create and call extension function in Kotlin - kotlin

fun main(args: Array<String>) {
val comingvalue = "\"6340040278031835\"".replace("[^0-9]".toRegex(), "");
print(getAuthDigits(comingvalue))
}
fun getAuthDigits( number :String?): String? {
return if (number?.length ?: 0 < 14) {
null
} else {
number?.substring(10, 14)
}
}
This is the function I am calling in the main method. Can anyone please suggest how to create an extension function and how to call it main method with a comingvalue input parameter?

fun String.getAuthDigits(): String? {
return if (this.length ?: 0 < 14) {
null
} else {
this.substring(10, 14)
}
}
and call this like below
fun main(args: Array<String>) {
val comingvalue = "\"6340040278031835\"".replace("[^0-9]".toRegex(), "");
print(comingvalue.getAuthDigits())
}

If this is the only place you call that function, you may as well write it inline.
You can use takeIf() to return null if the condition is not satisfied:
fun main() {
val authDigits: String? = """"6340040278031835""""
.takeIf { it.length >= 14 }?.substring(10, 14)
println(authDigits)
}
Output:
8031

Related

How to convert a function to listOf without lamdas?

There example of works code:
package cryptography
typealias taskFun = () -> Unit
var i: Int = 0
object tasks {
val supportTaskTextList = listOf("hide", "show", "exit")
val supportTaskFunList = listOf<taskFun>(fun() { println("hide $i");i++ }, fun() { println("show $i"); i++ } , fun() { println("Bye $i"); i++ })
fun hide() {
println("Hiding message in image.")
}
fun show() {
println("Obtaining message from image.")
}
fun exit() {
println("Bye!")
kotlin.system.exitProcess(0)
}
fun getTask() {
println("Task (${supportTaskTextList.joinToString(", ")}):")
val i = readln()
for (idx in supportTaskFunList.indices)
{
if (supportTaskTextList[idx] == i) return supportTaskFunList[idx]()
}
println("Wrong task: $i")
}
}
fun main() {
while(true) {
tasks.getTask()
}
}
Is code is works. But i want to call my methods without lamda. When i tried to just use them by name i got "main.kt:4:43: error: function invocation 'hide()' expected"
in: val supportTaskFunList = listOf<taskFun> = listOf(hide, show, exit)
Yet, i can to use it like:
package cryptography
typealias taskFun = () -> Unit
// var i: Int = 0
object tasks {
val hide = fun() {
println("Hiding message in image.")
}
val show = fun() {
println("Obtaining message from image.")
}
val exit = fun() {
println("Bye!")
kotlin.system.exitProcess(0)
}
val supportTaskTextList = listOf("hide", "show", "exit")
val supportTaskFunList = listOf<taskFun>(hide, show, exit)
fun getTask() {
println("Task (${supportTaskTextList.joinToString(", ")}):")
val i = readln()
for (idx in supportTaskFunList.indices)
{
if (supportTaskTextList[idx] == i) return supportTaskFunList[idx]()
}
println("Wrong task: $i")
}
}
fun main() {
while(true) {
tasks.getTask()
}
}
May i use it without lamdas? Just, like as in C++ though pointers on methods? And why i can't use functions without lamdas here?
The correct syntax to reference a function by name is not using a plain name, but the :: syntax, for which you still need the name of hte object task I think. You could try just writing ::hide, ::show... but I am not sure it resolves here.,
val supportTaskFunList = listOf(tasks::hide, tasks::show, tasks::exit)
Short mention: This is a function type. According to the documentation this is not a lambda (in Kotlin terminology) as it does not define a new function or use the lambda syntax, just references an existing function.

Returning a class in Kotlin

class Wolf {
var hunger = 10
val food = "meat"
fun eat() {
println("The Wolf is eating $food")
}
}
class MyWolf {
var wolf: Wolf? = Wolf()
fun myFunction() {
wolf?.eat()
}
}
fun getAlphaWolf(): Wolf? {
return Wolf()
}
fun main(args: Array<String>) {
var w: Wolf? = Wolf()
if (w != null) {
w.eat()
}
var x = w?.hunger
println("The value of x is $x")
var y = w?.hunger ?: -1
println("The value of y is $y")
var myWolf = MyWolf()
myWolf?.wolf?.hunger = 8
println("The value of myWolf?.wolf?.hunger is ${myWolf?.wolf?.hunger}")
var myArray = arrayOf("Hi", "Hello", null)
for (item in myArray) {
item?.let { println(it) }
}
getAlphaWolf()?.let { it.eat() }
w = null
var z = w!!.hunger
}
This above code is extracted from a Kotlin textbook.
I have problem with the following:
fun getAlphaWolf(): Wolf? {
return Wolf()
}
As there is only a class called Wolf but no variable called Wolf in the code.
I wonder if it is possible to return a class inside a function?
What is the output if a class is returned inside a function?
If you are familiar with Java, then this Kotlin is equivalent to:
public class Application {
public Wolf getAlphaWolf() {
return new Wolf();
}
}
So, in Kotlin you are calling the no-arguments constructor. If you want to return the class Wolf, then that is also possible:
fun getWolfClass(): KClass<Wolf> {
return Wolf::class
}
In the following code, the primary constructor of class Wolf is called:
fun getAlphaWolf(): Wolf? {
return Wolf()
}
So, getAlphaWolf returns a completely new instance of Wolf with default values: Wolf(hunger=10,food=meat).
Update: by the way, making the return type of this function nullable is redundant, because a new instance cannot be null.

Is possible to change dynamically method for an instance?

I wrote down this code:
open class Test(){
override fun toString(): String {
return "This is test!"
}
}
fun createTestX(): Test {
return object : Test() {
override fun toString(): String {
return super.toString() + "XXX"
}
}
}
fun main(args: Array<String>) {
val x = createTestX()
println(x)
}
It works as expected but I am curious whether is it possible to change method of instance using for example lambda like this:
val x = Test()
x.toString = () -> x.toString() + "XXX"
What you can do
class C {
var example:()->String = this::toString
}
fun main(args: Array<String>) {
val c = C()
println(c.example())
c.example = {"ABCDEF"}
println(c.example())
}
Limitations
Although this works for swapping fields, you cannot use it to override methods. This can be worked around by defining the method to invoke the field.
class C {
var example:()->String = {"ABC"}
override fun toString() = example()
}
fun main(args: Array<String>) {
val c = C()
println(c)
c.example = {"DEF"}
println(c)
}
Output:
ABC
DEF

Invoking Action by reference in Kotlin

I've a Map of (key, value) where the value is a predefined function.
I want to iterate the input param in the Mp and check where the key is matching with the input parameter, then invoke the equivalent function, something like this
My code required to be something like below:
fun fn1: Unit { // using Unit is optional
println("Hi there!")
}
fun fn2 {
println("Hi again!")
}
fun MainFun(x: int){
val map: HashMap<Int, String> = hashMapOf(1 to fn1, 2 to fn2)
for ((key, value) in map) {
// if key = x then run/invoke the function mapped with x, for example if x = 1 then invoke fn1
}
}
Notes: I read something like below, but could not know how to us them:
inline fun <K, V> Map<out K, V>.filter(
predicate: (Entry<K, V>) -> Boolean
): Map<K, V> (source)
val russianNames = arrayOf("Maksim", "Artem", "Sophia", "Maria", "Maksim")
val selectedName = russianNames
.filter { it.startsWith("m", ignoreCase = true) }
.sortedBy { it.length }
.firstOrNull()
Hi I hope this would help you.
fun fn1() {
println("Hi there!")
}
fun fn2() {
println("Hi again!")
}
fun main(args: IntArray){
val map = hashMapOf(
1 to ::fn1,
2 to ::fn2)
map.filterKeys { it == args[0] } // filters the map by comparing the first int arg passed and the key
.map { it.value.invoke() } // invoke the function that passed the filter.
}
If the keyis RegEx then map.filterKeys { Regex(it).matches(x) } can be used, below full example of it Try Kotlin:
data class Person(val name: String,
val age: Int? = null)
val persons = listOf(Person("Alice"),
Person("Bob", age = 23))
fun old() {
val oldest = persons.maxBy { it.age ?: 0 }
println("The oldest is: $oldest")
}
fun young() {
val youngest = persons.minBy { it.age ?: 0 }
println("The youngest is: $youngest")
}
fun selection(x: String) {
val map = mapOf(
"old|big" to ::old,
"new|young" to ::young)
map.filterKeys { Regex(it).matches(x) }
.map { it.value.invoke() }
}
fun main(args: Array<String>) {
selection("new")
}
fun fn1() {
println("Hi there!")
}
fun fn2() {
println("Hi again!")
}
fun main(args: Array<Int>){
val map = hashMapOf(1 to ::fn1, 2 to ::fn2)
map.forEach { key, function -> function.invoke() }
}
This will do the work but your code does not even have the correct syntax. You should learn the basic first.

How to get names and values of method's parameters?

Is there possibility to get names of method's parameters inside method code? Can anyone show example of it?
I found only this solution at this time, but dislike it..:
class Greeter() {
fun greet(name: String) {
val c = Greeter::class;
for (m in c.memberFunctions) {
if (m.name == "greet") {
val p = m.parameters
println(p.toString())
}
}
println("Hello, ${name}");
}
}
fun main(args: Array<String>) {
Greeter().greet("UserName")
}
update: i found another solution, but now i have one more question:
How to get pairs of ParamName, ParamValue at function greet?
class Greeter() {
fun greet(name: String) {
val p = Greeter::greet.parameters
println(p.toString())
println("Hello, ${name}");
}
}
fun main(args: Array<String>) {
Greeter().greet("UserName")
}
Parameter names are available through the KParameter.name property:
class Greeter() {
fun greet(name: String) {
val p = Greeter::greet.parameters
println("Hello, ${p[0].name}")
}
}
Parameter values, on the other hand, cannot be obtained reflectively easily on JVM.