Skip to content

Instantly share code, notes, and snippets.

@senamit2708
Created June 30, 2023 10:31
Show Gist options
  • Select an option

  • Save senamit2708/3ed496f970d770f8a113f18c5cb862b3 to your computer and use it in GitHub Desktop.

Select an option

Save senamit2708/3ed496f970d770f8a113f18c5cb862b3 to your computer and use it in GitHub Desktop.
scope function learning
/*
there are five types of scope functions: makes your code clear, concise and more readable
with
let
run
apply
also
two main difference between them
1. the way to refer the context object -> either this or it
2. the return value either contextObject or the lambda result
with:
context-> this
return -> lambda
*/
//start[learning with]
class Person() {
var name: String = "amit"
var age: Int = 23
}
/*fun main(){
val person = Person()
// println("name is ${person.name}")
// println("age is${person.age}")
//simple example
with(person){
println(this.name)//this keyword is also not required because bydefault its taking this
println(this.age)
}
//here return is lambda and context is this
val ageAfterfiveYear: Int = with(person){
println(this.name)
println(this.age)
age+5
}
println("age after 5 years is $ageAfterfiveYear")
}*/
//End [learning with]
//Start[apply]
/*class Person(){
var name: String = ""
var age: Int = 23
}
fun main(){
//used to assign the value to the variables of the class
val person = Person().apply {
this.name = "amit sen"
this.age = 30
}
with(person){
println(name)
println(age)
}
}*/
//End[apply]
//Start[also]
/*fun main(){
val numberList = mutableListOf<Int>(1,3,4)
val duplicateNumber = numberList.also {
it.add(5)
it.remove(3)
println("the list elements are $it")
}
println("origianl numberlist $numberList")
println("duplicate numberlist $duplicateNumber")
}
the list elements are [1, 4, 5]
origianl numberlist [1, 4, 5]
duplicate numberlist [1, 4, 5]*/
//second example
/*class Person(){
var name: String = ""
var age: Int = 23
}
fun main(){
//used to assign the value to the variables of the class
val person = Person().apply {
this.name = "amit sen"
this.age = 30
}
with(person){
println(name)
println(age)
}
//so here it is used if u want to do some varaible data changes use also function
person.also {
it.name = "amit new name"
println("name is ${it.name}")
}
println("name is ${person.name}")//amit new name
}*/
//End[also]
//Start[let]
//used for avoiding nullpoint exceptions
/*fun main(){
val name:String? = "amit"
val nameLength = name?.let {
println("name reversed ${it.reversed()}")
println("captalized ${it.capitalize()}")
it.length
}
println("length of name $nameLength")
}*/
//End[let]
//Start[Run]
//this function is a combination of with and let scope function
/*class Person(){
var name: String = "amit"
var age: Int = 23
}
fun main(){
val person = Person()
//so here with is used alsong with let
person?.run {
println(name)
println(age)
age+5
}
}*/
//with -> lambda,this
//let-> lambda, it
//run-> lambda, this
//apply-> context obj, this
//also-> context Obj, it
//SCOPE Function
/*The Kotlin standard library contains several functions whose sole purpose is to execute a block of code
within the context of an object. When you call such a function on an object with a lambda expression provided,
it forms a temporary scope. In this scope, you can access the object without its name. Such functions are called scope functions.
Basically, these functions all perform the same action: execute a block of code on an object.
What's different is how this object becomes available inside the block and what is the result of the whole expression.
*/
/*
two main difference between them
1. the way to refer the context object -> either this or it
2. the return value either contextObject or the lambda result
//with -> lambda,this
//let-> lambda, it
//run-> lambda, this
//apply-> context obj, this
//also-> context Obj, it
-------where to execute which scope function -------
Executing a lambda on non-null objects: let
Introducing an expression as a variable in local scope: let
Object configuration: apply
Object configuration and computing the result: run
Running statements where an expression is required: non-extension run
Additional effects: also
Grouping function calls on an object: with
-------------------------------------------------
this -> lambda receiver
it -> lambda argument
----------
let, run, and with return the lambda result. So you can use them when assigning the result to a variable, chaining operations on the result, and so on.
val numbers = mutableListOf("one", "two", "three")
val countEndsWithE = numbers.run {
add("four")
add("five")
count { it.endsWith("e") }
}
println("There are $countEndsWithE elements that end with e.")
-------------
The return value of apply and also is the context object itself. Hence,
they can be included into call chains as side steps: you can continue chaining function calls on the same object, one after another.
val numberList = mutableListOf<Double>()
numberList.also { println("Populating the list") }
.apply {
add(2.71)
add(3.14)
add(1.0)
}
.also { println("Sorting the list") }
.sort()
*/
data class Employee(var name: String = "Amit", var age: Int = 32, var address: String = "Bihar")
fun main() {
// letFun()
// runFun()
// withFun()
// withOrRunFun()
// applyFun()
alsoFun()
}
fun letFun() {
val employeeOne = Employee().let {
return@let "Employee name is ${it.name}"
}
println(employeeOne) //Employee name is Amit
//note -> It is not necessary to write “return@let”. This is only done to enhance code readability. In Kotlin,
val employeeTwo = Employee().let {
it.name = "sohan kumar"
it.name
}
println(employeeTwo) //sohan kumar
//note -> if the last statement in a “ let ” block is a non-assignment statement, it is by default a return statement.
val employeeThree = Employee().let {
it.name = "saurav"
}
println(employeeThree) //kotlin.Unit
//note -> if we don’t return anything in the “ let ” block? and also last statement is assignment.
// It is similar to calling a function that has no return value
val name = Employee().name?.let {
"name of employee is $it"
}
println(name)//name of employee is Amit
//null safety ?.let
val numberList = mutableListOf(1, 2, 3, 4, 5)
numberList.filter { it > 3 }.let {
println(it) //[4, 5]
//note -> chain of task
}
}
fun runFun() {
val employeeOne = Employee().run {
name = "Saurav"
age = 43
return@run "name is $name"
}
println(employeeOne) //name is Saurav
}
fun withFun() {
val employeeOne = with(Employee()) {
return@with "name of employee is $name"
}
println(employeeOne) //name of employee is Amit
}
fun withOrRunFun() {
val employeeOne: Employee? = null
with(employeeOne) {
this?.name = "saurav"
this?.age = 42
this?.address = "bhopal"
}
employeeOne?.run {
name = "shyam"
age = 12
address = "professor colony"
}
//note -> when u have to cross check null safety, its good to go with run or let rather than with.
}
fun applyFun() {
val employeeOne: Employee? = null
employeeOne?.apply {
name = "saurav"
age = 33
address = "patna"
}
//difference between run and apply is that return@apply is not available.
}
fun alsoFun() {
val employee = Employee().also {
it.name = "saurav"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment