SlideShare ist ein Scribd-Unternehmen logo
1 von 108
Downloaden Sie, um offline zu lesen
Sneaking inside Kotlin features
Chandra Sekhar
Sneaking inside Kotlin features
1. Variables
@iChanSek bit.ly/chansecode
1.1 lateinit properties
@iChanSek bit.ly/chansecode
lateinit properties
lateinit var user: User
@iChanSek bit.ly/chansecode
lateinit properties
public final User user;
public final User getUser() {
if (user == null) {
throwUninitializedPropertyAccessException("user");
}
return user;
}
public final void setUser(User newUser) {
checkParameterIsNotNull(newUser, "<set-?>");
user = newUser;
}
@iChanSek bit.ly/chansecode
lateinit properties
public final User getUser() {
if (user == null) {
throwUninitializedPropertyAccessException("user");
}
return user;
}
public final void setUser(User newUser) {
checkParameterIsNotNull(newUser, "<set-?>");
@iChanSek bit.ly/chansecode
lateinit properties
public final User getUser() {
if (user == null) {
throwUninitializedPropertyAccessException("user");
}
return user;
}
public final void setUser(User newUser) {
checkParameterIsNotNull(newUser, "<set-?>");
user = newUser;
}
@iChanSek bit.ly/chansecode
1.2 Delegated Properties
@iChanSek bit.ly/chansecode
Delegated Properties
class DelegatedProperties {
val x by lazy { 10 }
}
@iChanSek bit.ly/chansecode
Delegated Properties
public final class DelegatedProperties {
static final KProperty[] props = new KProperty[]{ ... }
private final Lazy xDelegate;
public final int getX() {
return ((Number)xDelegate.getValue()).intValue();
}
public DelegatedProperties() {
this.xDelegate = LazyKt.lazy((Function0)2.INSTANCE);
}
}
@iChanSek bit.ly/chansecode
Delegated Properties
public final class DelegatedProperties {
static final KProperty[] props = new KProperty[]{ ... }
private final Lazy xDelegate;
public final int getX() {
return ((Number)xDelegate.getValue()).intValue();
}
public DelegatedProperties() {
this.xDelegate = LazyKt.lazy((Function0)2.INSTANCE);
}
}
@iChanSek bit.ly/chansecode
Delegated Properties
public final class DelegatedProperties {
static final KProperty[] props = new KProperty[]{ ... }
private final Lazy xDelegate;
public final int getX() {
return ((Number)xDelegate.getValue()).intValue();
}
public DelegatedProperties() {
this.xDelegate = LazyKt.lazy((Function0)2.INSTANCE);
}
}
@iChanSek bit.ly/chansecode
Delegated Properties
public final class DelegatedProperties {
static final KProperty[] props = new KProperty[]{ ... }
private final Lazy xDelegate;
public final int getX() {
return ((Number)xDelegate.getValue()).intValue();
}
public DelegatedProperties() {
this.xDelegate = LazyKt.lazy((Function0)2.INSTANCE);
}
}
@iChanSek bit.ly/chansecode
Delegated Properties
public final class DelegatedProperties {
static final KProperty[] props = new KProperty[]{ ... }
private final Lazy xDelegate;
public final int getX() {
return ((Number)xDelegate.getValue()).intValue();
}
public DelegatedProperties() {
this.xDelegate = LazyKt.lazy(() -> 10);
}
}
@iChanSek bit.ly/chansecode
Delegated Properties
public final class DelegatedProperties {
static final KProperty[] props = new KProperty[]{ ... }
private final Lazy xDelegate;
public final int getX() {
return ((Number)xDelegate.getValue()).intValue();
}
public DelegatedProperties() {
this.xDelegate = LazyKt.lazy((Function0)2.INSTANCE);
}
}
@iChanSek bit.ly/chansecode
Delegated Properties
public final int getX() {
return ((Number)xDelegate.getValue()).intValue();
}
@iChanSek bit.ly/chansecode
fun main() {
val delegatedProp = DelegatedProperties()
println(delegatedProp.x)
println(delegatedProp.x)
}
Delegated Properties
class SynchronizedLazyImpl<out T>(initializer: () -> T, lock: Any? = null) : Lazy<T> {
private var initializer: (() -> T)? = initializer
@Volatile private var _value: Any? = UNINITIALIZED_VALUE
private val lock = lock ?: this
override val value: T
get() {
if (_value !== UNINITIALIZED_VALUE) {
return _value as T
}
return synchronized(lock) {
...
}
}
}
@iChanSek bit.ly/chansecode
fun main() {
val delegatedProp = DelegatedProperties()
println(delegatedProp.x)
println(delegatedProp.x)
}
public final int getX() {
return ((Number)xDelegate.getValue()).intValue();
}
Delegated Properties
class SynchronizedLazyImpl<out T>(initializer: () -> T, lock: Any? = null) : Lazy<T> {
private var initializer: (() -> T)? = initializer
@Volatile private var _value: Any? = UNINITIALIZED_VALUE
private val lock = lock ?: this
override val value: T
get() {
if (_value !== UNINITIALIZED_VALUE) {
return _value as T
}
return synchronized(lock) {
...
}
}
}
@iChanSek bit.ly/chansecode
Delegated Properties
class SynchronizedLazyImpl<out T>(initializer: () -> T, lock: Any? = null) : Lazy<T> {
private var initializer: (() -> T)? = initializer
@Volatile private var _value: Any? = UNINITIALIZED_VALUE
private val lock = lock ?: this
override val value: T
get() {
if (_value !== UNINITIALIZED_VALUE) {
return _value as T
}
return synchronized(lock) {
...
}
}
}
@iChanSek bit.ly/chansecode
1.3 Nullable and Non-Nullable
@iChanSek bit.ly/chansecode
Nullable and Non-Nullable
val nullableConf: Conference? = null
val confName = nullableConf?.name
@iChanSek bit.ly/chansecode
Nullable and Non-Nullable
Conference conf = nullableConf;
String confName =
conf != null ? conf.getName() : null
@iChanSek bit.ly/chansecode
Nullable and Non-Nullable
val c = a?.b?.c
@iChanSek bit.ly/chansecode
Nullable and Non-Nullable
if (a != null) {
B b = a.b;
}
@iChanSek bit.ly/chansecode
Nullable and Non-Nullable
C c;
if (a != null) {
B b = a.b;
if (b != null) {
c = b.c;
}
}
@iChanSek bit.ly/chansecode
Nullable and Non-Nullable
C c;
label1: {
if (a != null) {
B b = a.b;
if (b != null) {
c = b.c;
break label1;
}
}
c = null;
}
@iChanSek bit.ly/chansecode
Nullable and Non-Nullable
val d = a!!.b!!.c
@iChanSek bit.ly/chansecode
Nullable and Non-Nullable
if (a == null) throwNpe();
B b = a.b;
@iChanSek bit.ly/chansecode
Nullable and Non-Nullable
if (a == null) throwNpe();
B b = a.b;
if (b == null) throwNpe();
C c = b.c;
@iChanSek bit.ly/chansecode
2. Control Flows
@iChanSek bit.ly/chansecode
2.1 If Expression
@iChanSek bit.ly/chansecode
If Expression
val max = if (a > b) a else b
@iChanSek bit.ly/chansecode
If Expression
int max = a > b ? a : b
@iChanSek bit.ly/chansecode
If Expression
val max = if (a > b) {
print("a is bigger")
a
} else {
print("b is bigger")
b
}
@iChanSek bit.ly/chansecode
If Expression
int max;
if (a > b) {
S.O.P("a is bigger");
max = a;
} else {
S.O.P("b is bigger");
max = b;
}
@iChanSek bit.ly/chansecode
2.2 When Expression
@iChanSek bit.ly/chansecode
When Expression
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> print("x is neither 1 nor 2")
}
@iChanSek bit.ly/chansecode
When Expression
switch (x) {
case 1:
S.O.P("x == 1");
break;
case 2:
S.O.P("x == 2");
break;
default:
S.O.P("x is neither 1 nor 2");
break;
}
@iChanSek bit.ly/chansecode
When Expression
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> print("x is neither 1 nor 2")
}
@iChanSek bit.ly/chansecode
When Expression
when {
x == 1 -> print("x == 1")
x == 2 -> print("x == 2")
else -> print("x is neither 1 nor 2")
}
@iChanSek bit.ly/chansecode
When Expression
if (x == 1) {
S.O.P("x == 1");
} else if (x == 2) {
S.O.P("x == 2");
} else {
S.O.P("x is neither 1 nor 2”);
}
@iChanSek bit.ly/chansecode
When Expression
enum class Colour {
RED, GREEN, BLUE
}
when (colour) {
Colour.RED -> ...
Colour.GREEN -> ...
Colour.BLUE -> ...
}
@iChanSek bit.ly/chansecode
When Expression
switch(WhenMappings.$EnumSwitchMapping$0[colour.ordinal()]) {
case 1:
...
break;
case 2:
...
break;
case 3:
...
break;
......
}
@iChanSek bit.ly/chansecode
When Expression
switch(WhenMappings.$EnumSwitchMapping$0[colour.ordinal()]) {
case 1:
...
break;
case 2:
...
break;
case 3:
...
break;
......
}
@iChanSek bit.ly/chansecode
public final class WhenKt$WhenMappings {
public static final int[] $EnumSwitchMapping$0 = new
int[Colour.values().length];
static {
$EnumSwitchMapping$0[Colour.RED.ordinal()] = 1;
$EnumSwitchMapping$0[Colour.GREEN.ordinal()] = 2;
$EnumSwitchMapping$0[Colour.BLUE.ordinal()] = 3;
}
}
When Expression
switch(WhenMappings.$EnumSwitchMapping$0[colour.ordinal()]) {
case 1:
...
break;
case 2:
...
break;
case 3:
...
break;
......
}
@iChanSek bit.ly/chansecode
public final class WhenKt$WhenMappings {
public static final int[] $EnumSwitchMapping$0 = new
int[Colour.values().length];
static {
$EnumSwitchMapping$0[Colour.RED.ordinal()] = 1;
$EnumSwitchMapping$0[Colour.GREEN.ordinal()] = 2;
$EnumSwitchMapping$0[Colour.BLUE.ordinal()] = 3;
}
}
3. Classes & Interfaces
@iChanSek bit.ly/chansecode
3.1 Data Classes
@iChanSek bit.ly/chansecode
Data Classes
class User(
val name: String,
val age: Int
)
@iChanSek bit.ly/chansecode
Destructuring Declarations
class User(
val name: String,
val age: Int
)
val user = User("Chandra", 10)
val (name, age) = user
@iChanSek bit.ly/chansecode
Destructuring Declarations
class User(
val name: String,
val age: Int
)
val user = User("Chandra", 10)
val (name, age) = user
@iChanSek bit.ly/chansecode
Destructuring Declarations
data class User(
val name: String,
val age: Int
)
val user = User("Chandra", 10)
val (name, age) = user
@iChanSek bit.ly/chansecode
Destructuring Declarations
public final class User {
...
public final String component1() {
return this.name;
}
public final int component2() {
return this.age;
} val user = User("Chandra", 10)
} val (name, age) = user
@iChanSek bit.ly/chansecode
Destructuring Declarations
public final class User {
...
public final String component1() {
return this.name;
}
public final int component2() {
return this.age;
}
}
@iChanSek bit.ly/chansecode
String name = user.component1();
int age = user.component2();
3.2 Sealed Classes
@iChanSek bit.ly/chansecode
Sealed Classes
sealed class Calculation
class Add(val num1: Int, val num2: Int) : Calculation()
class Sub(val num1: Int, val num2: Int) : Calculation()
class Mul(val num1: Int, val num2: Int) : Calculation()
class Div(val num1: Int, val num2: Int) : Calculation()
@iChanSek bit.ly/chansecode
Sealed Classes
public abstract class Calculation {
private Calculation() {}
}
class Add(val num1: Int, val num2: Int) : Calculation()
class Sub(val num1: Int, val num2: Int) : Calculation()
class Mul(val num1: Int, val num2: Int) : Calculation()
class Div(val num1: Int, val num2: Int) : Calculation()
@iChanSek bit.ly/chansecode
Sealed Classes
public abstract class Calculation {
private Calculation() {}
}
public final class Add extends Calculation { ... }
public final class Sub extends Calculation { ... }
public final class Mul extends Calculation { ... }
public final class Div extends Calculation { ... }
@iChanSek bit.ly/chansecode
Sealed Classes
private fun calculate(calculator: Calculation) {
when(calculator) {
is Add -> calculator.num1 + calculator.num2
is Sub -> calculator.num1 - calculator.num2
is Mul -> calculator.num1 * calculator.num2
is Div -> calculator.num1 / calculator.num2
}
}
@iChanSek bit.ly/chansecode
Sealed Classes
private static final void calculate(Calculation calculator) {
int result;
if (calculator instanceof Add) {
result = ((Add)calculator).getNum1() + ((Add)calculator).getNum2();
} else if (calculator instanceof Sub) {
result = ((Sub)calculator).getNum1() - ((Sub)calculator).getNum2();
} else if (calculator instanceof Mul) {
result = ((Mul)calculator).getNum1() * ((Mul)calculator).getNum2();
} else if (calculator instanceof Div) {
result = ((Div)calculator).getNum1() / ((Div)calculator).getNum2();
}
}
@iChanSek bit.ly/chansecode
3.3 Inline Classes
@iChanSek bit.ly/chansecode
Inline Classes
inline class UserId(val value: Long)
@iChanSek bit.ly/chansecode
Inline Classes
public final class UserId {
private final long id;
public static long constructor_impl(long id) {
return id;
}
public static final UserId box_impl(long v) {
return new UserId(v);
}
public final long unbox_impl() {
return this.id;
}
}
@iChanSek bit.ly/chansecode
Inline Classes
public final class UserId {
private final long id;
public static long constructor_impl(long id) {
return id;
}
public static final UserId box_impl(long v) {
return new UserId(v);
}
public final long unbox_impl() {
return this.id;
}
}
@iChanSek bit.ly/chansecode
Inline Classes
public final class UserId {
private final long id;
public static long constructor_impl(long id) {
return id;
}
public static final UserId box_impl(long v) {
return new UserId(v);
}
public final long unbox_impl() {
return this.id;
}
}
@iChanSek bit.ly/chansecode
Inline Classes
public final class UserId {
private final long id;
public static long constructor_impl(long id) {
return id;
}
public static final UserId box_impl(long v) {
return new UserId(v);
}
public final long unbox_impl() {
return this.id;
}
}
@iChanSek bit.ly/chansecode
Inline Classes
fun main() {
val userId = UserId(10L)
getUser(userId)
}
private fun getUser(id: UserId) {
// Do something with id
}
@iChanSek bit.ly/chansecode
Inline Classes
public static final void main() {
long userId = UserId.constructor_impl(10L);
getUser(userId);
}
// UserId became long in the argument
private static final void getUser(long id) {
// Do something with id
}
@iChanSek bit.ly/chansecode
3.4 Default Methods
@iChanSek bit.ly/chansecode
Default Methods
interface Calculator {
fun div(a: Int, b: Int) = ...
}
@iChanSek bit.ly/chansecode
Default Methods
class DefaultCalculatorImpl : Calculator
class CalculatorImpl : Calculator {
override fun div(a: Int, b: Int): Int {
...
}
}
@iChanSek bit.ly/chansecode
Default Methods
public final class DefaultCalculatorImpl implements Calculator {
public int div(int a, int b) {
return Calculator.DefaultImpls.div(this, a, b);
}
}
public final class CalculatorImpl implements Calculator {
public int div(int a, int b) {
...
}
}
@iChanSek bit.ly/chansecode
4. Functions
@iChanSek bit.ly/chansecode
4.1 Extension Function
@iChanSek bit.ly/chansecode
Extension Function
fun IntArray.swap(index1: Int, index2: Int) {
val temp = this[index1]
this[index1] = this[index2]
this[index2] = temp
}
@iChanSek bit.ly/chansecode
Extension Function
public static final void swap(int[] arr, int index1, int index2) {
Intrinsics.checkParameterIsNotNull(arr, "arr");
int temp = arr[index1];
arr[index1] = arr[index2];
arr[index2] = temp;
}
@iChanSek bit.ly/chansecode
Extension Function
val arr = intArrayOf(1, 2, 3, 4, 5)
arr.swap(2, 4)
@iChanSek bit.ly/chansecode
Extension Function
int[] arr = new int[]{1, 2, 3, 4, 5};
swap(arr, 2, 4);
@iChanSek bit.ly/chansecode
4.2 Default Arguments
@iChanSek bit.ly/chansecode
Default Arguments
fun add(a: Int,
b : Int,
c: Int = 100,
d: Int = 200,
e: Int = 300) =
a + b + c + d + e
@iChanSek bit.ly/chansecode
Default Arguments
... int add(int a, int b, int c, int d, int e) {
return a + b + c + d + e;
}
@iChanSek bit.ly/chansecode
Default Arguments
... int add(int a, int b, int c, int d, int e) {
return a + b + c + d + e;
}
fun main() {
add(2, 3, 4, 5, 6)
}
@iChanSek bit.ly/chansecode
Default Arguments
... int add(int a, int b, int c, int d, int e) {
return a + b + c + d + e;
}
fun main() {
add(2, 3, 4, 5, 6)
add(2, 3)
}
@iChanSek bit.ly/chansecode
Default Arguments
... int add(int a, int b, int c, int d, int e) {
return a + b + c + d + e;
}
fun main() {
add(2, 3, 4, 5, 6)
add(2, 3)
add(2, 3, 4, 5)
}
@iChanSek bit.ly/chansecode
Default Arguments
... int add(int a, int b, int c, int d, int e) {
return a + b + c + d + e;
}
public static final void main() {
add(2, 3, 4, 5, 6);
add(2, 3, 0, 0, 0, 28, _);
add(2, 3, 4, 5, 0, 16, _);
}
@iChanSek bit.ly/chansecode
Default Arguments
... int add$default(int a, int b, int c, int d, int e, int var5, _) {
...
}
public static final void main() {
add(2, 3, 4, 5, 6);
add$default(2, 3, 0, 0, 0, 28, _);
add$default(2, 3, 4, 5, 0, 16, _);
}
@iChanSek bit.ly/chansecode
Default Arguments
... int add$default(int a, int b, int c, int d, int e, int var5, 
) {
...
}
public static final void main() {
add(2, 3, 4, 5, 6);
add$default(2, 3, 0, 0, 0, 22 + 23 + 24, _);
add$default(2, 3, 4, 5, 0, 24, _);
}
@iChanSek bit.ly/chansecode
Default Arguments
... int add$default(int a, int b, int c, int d, int e, int var5, _) {
if ((var5 & 4) != 0) c = 100;
if ((var5 & 8) != 0) d = 200;
if ((var5 & 16) != 0) e = 300;
return add(a, b, c, d, e);
}
@iChanSek bit.ly/chansecode
4.3 Local Functions
@iChanSek bit.ly/chansecode
Local Functions
fun outer() {
fun inner() {
println(“ Kolkata”)
}
println(“Welcome to DevFest")
if (event == "DevFest Kolkata") inner()
}
@iChanSek bit.ly/chansecode
Local Functions
public static final void outer() {
Inner inner = Inner.INSTANCE;
System.out.println("Welcome to DevFest");
if (Intrinsics.areEqual(event, "DevFest Kolkata")) {
inner.invoke();
}
}
@iChanSek bit.ly/chansecode
Local Functions
public static final void outer() {
Inner inner = Inner.INSTANCE;
System.out.println("Welcome to DevFest");
if (Intrinsics.areEqual(event, "DevFest Kolkata")) {
inner.invoke();
}
}
@iChanSek bit.ly/chansecode
final class Inner extends Lambda
implements Function0 {
... Inner INSTANCE = new Inner();
public final void invoke() {
System.out.println(" Kolkata");
}
Inner() { super(0); }
}
4.4 Lambda Functions
@iChanSek bit.ly/chansecode
Lambda Functions
val sum: (Int, Int) -> Int = { x, y -> x + y }
@iChanSek bit.ly/chansecode
Lambda Functions
val sum: (Int, Int) -> Int = { x, y -> x + y }
... Function2<_, _, _> sum = new Function2<_, _, _>() {
@Override
public final int invoke(int a, int b) {
return a + b;
}
};
@iChanSek bit.ly/chansecode
Lambda Functions
() -> Unit == class XXX implements Function0<Unit>
@iChanSek bit.ly/chansecode
Lambda Functions
() -> Unit == class XXX implements Function0<Unit>
(Int, Int) -> Int == class XXX implements Function2<Int, Int, Int>
@iChanSek bit.ly/chansecode
4.5 Lambda with Receiver
@iChanSek bit.ly/chansecode
Lambda with Receiver
val sum: (Int, Int) -> Int = { x, y -> x + y }
@iChanSek bit.ly/chansecode
Lambda with Receiver
val sum: Int.(Int) -> Int = { this + it }
@iChanSek bit.ly/chansecode
Lambda with Receiver
val sum: Int.(Int) -> Int = { this + it }
... Function2<_, _, _> sum = new Function2<_, _, _>() {
@Override
public final int invoke(int $receiver, int a) {
return $receiver + a;
}
};
@iChanSek bit.ly/chansecode
Lambda Functions
() -> Unit == class XXX implements Function0<Unit>
(Int, Int) -> Int == class XXX implements Function2<Int, Int, Int>
@iChanSek bit.ly/chansecode
Lambda Functions
() -> Unit == class XXX implements Function0<Unit>
(Int, Int) -> Int == class XXX implements Function2<Int, Int, Int>
Int.(Int) -> Int == class XXX implements Function2<Int, Int, Int>
@iChanSek bit.ly/chansecode
5. How to Sneak
@iChanSek bit.ly/chansecode
How to Sneak
@iChanSek bit.ly/chansecode
How to Sneak
@iChanSek bit.ly/chansecode
Thank You
Chandra Sekhar
@iChanSek bit.ly/chansecode

Weitere Àhnliche Inhalte

Was ist angesagt?

Scala - where objects and functions meet
Scala - where objects and functions meetScala - where objects and functions meet
Scala - where objects and functions meetMario Fusco
 
Java 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forwardJava 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forwardMario Fusco
 
Kotlin advanced - language reference for android developers
Kotlin advanced - language reference for android developersKotlin advanced - language reference for android developers
Kotlin advanced - language reference for android developersBartosz Kosarzycki
 
Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2José Paumard
 
ĐĄŃ‚ĐŸĐ»ĐżŃ‹ Ń„ŃƒĐœĐșŃ†ĐžĐŸĐœĐ°Đ»ŃŒĐœĐŸĐłĐŸ ĐżŃ€ĐŸĐłŃ€Đ°ĐŒĐŒĐžŃ€ĐŸĐČĐ°ĐœĐžŃ ĐŽĐ»Ń Đ°ĐŽĐ”ĐżŃ‚ĐŸĐČ ĐžĐžĐŸ, НоĐșĐŸĐ»Đ°Đč ĐœĐŸĐ·ĐłĐŸĐČĐŸĐč
ĐĄŃ‚ĐŸĐ»ĐżŃ‹ Ń„ŃƒĐœĐșŃ†ĐžĐŸĐœĐ°Đ»ŃŒĐœĐŸĐłĐŸ ĐżŃ€ĐŸĐłŃ€Đ°ĐŒĐŒĐžŃ€ĐŸĐČĐ°ĐœĐžŃ ĐŽĐ»Ń Đ°ĐŽĐ”ĐżŃ‚ĐŸĐČ ĐžĐžĐŸ, НоĐșĐŸĐ»Đ°Đč ĐœĐŸĐ·ĐłĐŸĐČĐŸĐčĐĄŃ‚ĐŸĐ»ĐżŃ‹ Ń„ŃƒĐœĐșŃ†ĐžĐŸĐœĐ°Đ»ŃŒĐœĐŸĐłĐŸ ĐżŃ€ĐŸĐłŃ€Đ°ĐŒĐŒĐžŃ€ĐŸĐČĐ°ĐœĐžŃ ĐŽĐ»Ń Đ°ĐŽĐ”ĐżŃ‚ĐŸĐČ ĐžĐžĐŸ, НоĐșĐŸĐ»Đ°Đč ĐœĐŸĐ·ĐłĐŸĐČĐŸĐč
ĐĄŃ‚ĐŸĐ»ĐżŃ‹ Ń„ŃƒĐœĐșŃ†ĐžĐŸĐœĐ°Đ»ŃŒĐœĐŸĐłĐŸ ĐżŃ€ĐŸĐłŃ€Đ°ĐŒĐŒĐžŃ€ĐŸĐČĐ°ĐœĐžŃ ĐŽĐ»Ń Đ°ĐŽĐ”ĐżŃ‚ĐŸĐČ ĐžĐžĐŸ, НоĐșĐŸĐ»Đ°Đč ĐœĐŸĐ·ĐłĐŸĐČĐŸĐčSigma Software
 
Demystifying functional programming with Scala
Demystifying functional programming with ScalaDemystifying functional programming with Scala
Demystifying functional programming with ScalaDenis
 
If You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are WrongIf You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are WrongMario Fusco
 
Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)Jonas Bonér
 
Privet Kotlin (Windy City DevFest)
Privet Kotlin (Windy City DevFest)Privet Kotlin (Windy City DevFest)
Privet Kotlin (Windy City DevFest)Cody Engel
 
Kotlin Developer Starter in Android projects
Kotlin Developer Starter in Android projectsKotlin Developer Starter in Android projects
Kotlin Developer Starter in Android projectsBartosz Kosarzycki
 
The Kotlin Programming Language
The Kotlin Programming LanguageThe Kotlin Programming Language
The Kotlin Programming Languageintelliyole
 
Kotlin from-scratch 2 - functions
Kotlin from-scratch 2 - functionsKotlin from-scratch 2 - functions
Kotlin from-scratch 2 - functionsFranco Lombardo
 
OOP and FP - Become a Better Programmer
OOP and FP - Become a Better ProgrammerOOP and FP - Become a Better Programmer
OOP and FP - Become a Better ProgrammerMario Fusco
 
3 kotlin vs. java- what kotlin has that java does not
3  kotlin vs. java- what kotlin has that java does not3  kotlin vs. java- what kotlin has that java does not
3 kotlin vs. java- what kotlin has that java does notSergey Bandysik
 
Introduction to kotlin
Introduction to kotlinIntroduction to kotlin
Introduction to kotlinShaul Rosenzwieg
 
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italyFrom java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italyFabio Collini
 
Java 8 Stream API. A different way to process collections.
Java 8 Stream API. A different way to process collections.Java 8 Stream API. A different way to process collections.
Java 8 Stream API. A different way to process collections.David GĂłmez GarcĂ­a
 
Scalaz 8 vs Akka Actors
Scalaz 8 vs Akka ActorsScalaz 8 vs Akka Actors
Scalaz 8 vs Akka ActorsJohn De Goes
 

Was ist angesagt? (20)

Scala - where objects and functions meet
Scala - where objects and functions meetScala - where objects and functions meet
Scala - where objects and functions meet
 
Java 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forwardJava 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forward
 
Kotlin advanced - language reference for android developers
Kotlin advanced - language reference for android developersKotlin advanced - language reference for android developers
Kotlin advanced - language reference for android developers
 
Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2
 
ĐĄŃ‚ĐŸĐ»ĐżŃ‹ Ń„ŃƒĐœĐșŃ†ĐžĐŸĐœĐ°Đ»ŃŒĐœĐŸĐłĐŸ ĐżŃ€ĐŸĐłŃ€Đ°ĐŒĐŒĐžŃ€ĐŸĐČĐ°ĐœĐžŃ ĐŽĐ»Ń Đ°ĐŽĐ”ĐżŃ‚ĐŸĐČ ĐžĐžĐŸ, НоĐșĐŸĐ»Đ°Đč ĐœĐŸĐ·ĐłĐŸĐČĐŸĐč
ĐĄŃ‚ĐŸĐ»ĐżŃ‹ Ń„ŃƒĐœĐșŃ†ĐžĐŸĐœĐ°Đ»ŃŒĐœĐŸĐłĐŸ ĐżŃ€ĐŸĐłŃ€Đ°ĐŒĐŒĐžŃ€ĐŸĐČĐ°ĐœĐžŃ ĐŽĐ»Ń Đ°ĐŽĐ”ĐżŃ‚ĐŸĐČ ĐžĐžĐŸ, НоĐșĐŸĐ»Đ°Đč ĐœĐŸĐ·ĐłĐŸĐČĐŸĐčĐĄŃ‚ĐŸĐ»ĐżŃ‹ Ń„ŃƒĐœĐșŃ†ĐžĐŸĐœĐ°Đ»ŃŒĐœĐŸĐłĐŸ ĐżŃ€ĐŸĐłŃ€Đ°ĐŒĐŒĐžŃ€ĐŸĐČĐ°ĐœĐžŃ ĐŽĐ»Ń Đ°ĐŽĐ”ĐżŃ‚ĐŸĐČ ĐžĐžĐŸ, НоĐșĐŸĐ»Đ°Đč ĐœĐŸĐ·ĐłĐŸĐČĐŸĐč
ĐĄŃ‚ĐŸĐ»ĐżŃ‹ Ń„ŃƒĐœĐșŃ†ĐžĐŸĐœĐ°Đ»ŃŒĐœĐŸĐłĐŸ ĐżŃ€ĐŸĐłŃ€Đ°ĐŒĐŒĐžŃ€ĐŸĐČĐ°ĐœĐžŃ ĐŽĐ»Ń Đ°ĐŽĐ”ĐżŃ‚ĐŸĐČ ĐžĐžĐŸ, НоĐșĐŸĐ»Đ°Đč ĐœĐŸĐ·ĐłĐŸĐČĐŸĐč
 
Demystifying functional programming with Scala
Demystifying functional programming with ScalaDemystifying functional programming with Scala
Demystifying functional programming with Scala
 
Hammurabi
HammurabiHammurabi
Hammurabi
 
If You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are WrongIf You Think You Can Stay Away from Functional Programming, You Are Wrong
If You Think You Can Stay Away from Functional Programming, You Are Wrong
 
Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)Pragmatic Real-World Scala (short version)
Pragmatic Real-World Scala (short version)
 
Privet Kotlin (Windy City DevFest)
Privet Kotlin (Windy City DevFest)Privet Kotlin (Windy City DevFest)
Privet Kotlin (Windy City DevFest)
 
Kotlin Developer Starter in Android projects
Kotlin Developer Starter in Android projectsKotlin Developer Starter in Android projects
Kotlin Developer Starter in Android projects
 
The Kotlin Programming Language
The Kotlin Programming LanguageThe Kotlin Programming Language
The Kotlin Programming Language
 
Kotlin from-scratch 2 - functions
Kotlin from-scratch 2 - functionsKotlin from-scratch 2 - functions
Kotlin from-scratch 2 - functions
 
OOP and FP - Become a Better Programmer
OOP and FP - Become a Better ProgrammerOOP and FP - Become a Better Programmer
OOP and FP - Become a Better Programmer
 
3 kotlin vs. java- what kotlin has that java does not
3  kotlin vs. java- what kotlin has that java does not3  kotlin vs. java- what kotlin has that java does not
3 kotlin vs. java- what kotlin has that java does not
 
Introduction to kotlin
Introduction to kotlinIntroduction to kotlin
Introduction to kotlin
 
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italyFrom java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
 
ES6 in Real Life
ES6 in Real LifeES6 in Real Life
ES6 in Real Life
 
Java 8 Stream API. A different way to process collections.
Java 8 Stream API. A different way to process collections.Java 8 Stream API. A different way to process collections.
Java 8 Stream API. A different way to process collections.
 
Scalaz 8 vs Akka Actors
Scalaz 8 vs Akka ActorsScalaz 8 vs Akka Actors
Scalaz 8 vs Akka Actors
 

Ähnlich wie Sneaking inside Kotlin features

Coroutines in Kotlin. In-depth review
Coroutines in Kotlin. In-depth reviewCoroutines in Kotlin. In-depth review
Coroutines in Kotlin. In-depth reviewDmytro Zaitsev
 
Coroutines in Kotlin. UA Mobile 2017.
Coroutines in Kotlin. UA Mobile 2017.Coroutines in Kotlin. UA Mobile 2017.
Coroutines in Kotlin. UA Mobile 2017.UA Mobile
 
What's in Kotlin for us - Alexandre Greschon, MyHeritage
What's in Kotlin for us - Alexandre Greschon, MyHeritageWhat's in Kotlin for us - Alexandre Greschon, MyHeritage
What's in Kotlin for us - Alexandre Greschon, MyHeritageDroidConTLV
 
NetPonto - The Future Of C# - NetConf Edition
NetPonto - The Future Of C# - NetConf EditionNetPonto - The Future Of C# - NetConf Edition
NetPonto - The Future Of C# - NetConf EditionPaulo Morgado
 
Java 8 - Nuts and Bold - SFEIR Benelux
Java 8 - Nuts and Bold - SFEIR BeneluxJava 8 - Nuts and Bold - SFEIR Benelux
Java 8 - Nuts and Bold - SFEIR Beneluxyohanbeschi
 
Agile Iphone Development
Agile Iphone DevelopmentAgile Iphone Development
Agile Iphone DevelopmentGiordano Scalzo
 
Implementing STM in Java
Implementing STM in JavaImplementing STM in Java
Implementing STM in JavaMisha Kozik
 
EcmaScript unchained
EcmaScript unchainedEcmaScript unchained
EcmaScript unchainedEduard TomĂ s
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript IntroductionDmitry Sheiko
 
Kotlin Perfomance on Android / АлДĐșŃĐ°ĐœĐŽŃ€ ĐĄĐŒĐžŃ€ĐœĐŸĐČ (Splyt)
Kotlin Perfomance on Android / АлДĐșŃĐ°ĐœĐŽŃ€ ĐĄĐŒĐžŃ€ĐœĐŸĐČ (Splyt)Kotlin Perfomance on Android / АлДĐșŃĐ°ĐœĐŽŃ€ ĐĄĐŒĐžŃ€ĐœĐŸĐČ (Splyt)
Kotlin Perfomance on Android / АлДĐșŃĐ°ĐœĐŽŃ€ ĐĄĐŒĐžŃ€ĐœĐŸĐČ (Splyt)Ontico
 
Mixing functional and object oriented approaches to programming in C#
Mixing functional and object oriented approaches to programming in C#Mixing functional and object oriented approaches to programming in C#
Mixing functional and object oriented approaches to programming in C#Mark Needham
 
Vavr Java User Group Rheinland
Vavr Java User Group RheinlandVavr Java User Group Rheinland
Vavr Java User Group RheinlandDavid Schmitz
 
6. Generics. Collections. Streams
6. Generics. Collections. Streams6. Generics. Collections. Streams
6. Generics. Collections. StreamsDEVTYPE
 
C++: Constructor, Copy Constructor and Assignment operator
C++: Constructor, Copy Constructor and Assignment operatorC++: Constructor, Copy Constructor and Assignment operator
C++: Constructor, Copy Constructor and Assignment operatorJussi Pohjolainen
 
DataTypes.ppt
DataTypes.pptDataTypes.ppt
DataTypes.pptRithikRaj25
 
ADG PoznaƄ - Kotlin for Android developers
ADG PoznaƄ - Kotlin for Android developersADG PoznaƄ - Kotlin for Android developers
ADG PoznaƄ - Kotlin for Android developersBartosz Kosarzycki
 
Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015
Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015
Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015Codemotion
 

Ähnlich wie Sneaking inside Kotlin features (20)

Coroutines in Kotlin. In-depth review
Coroutines in Kotlin. In-depth reviewCoroutines in Kotlin. In-depth review
Coroutines in Kotlin. In-depth review
 
Coroutines in Kotlin. UA Mobile 2017.
Coroutines in Kotlin. UA Mobile 2017.Coroutines in Kotlin. UA Mobile 2017.
Coroutines in Kotlin. UA Mobile 2017.
 
What's in Kotlin for us - Alexandre Greschon, MyHeritage
What's in Kotlin for us - Alexandre Greschon, MyHeritageWhat's in Kotlin for us - Alexandre Greschon, MyHeritage
What's in Kotlin for us - Alexandre Greschon, MyHeritage
 
C# 7
C# 7C# 7
C# 7
 
NetPonto - The Future Of C# - NetConf Edition
NetPonto - The Future Of C# - NetConf EditionNetPonto - The Future Of C# - NetConf Edition
NetPonto - The Future Of C# - NetConf Edition
 
Java 8 - Nuts and Bold - SFEIR Benelux
Java 8 - Nuts and Bold - SFEIR BeneluxJava 8 - Nuts and Bold - SFEIR Benelux
Java 8 - Nuts and Bold - SFEIR Benelux
 
Agile Iphone Development
Agile Iphone DevelopmentAgile Iphone Development
Agile Iphone Development
 
Implementing STM in Java
Implementing STM in JavaImplementing STM in Java
Implementing STM in Java
 
ES6 is Nigh
ES6 is NighES6 is Nigh
ES6 is Nigh
 
EcmaScript unchained
EcmaScript unchainedEcmaScript unchained
EcmaScript unchained
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript Introduction
 
Kotlin Perfomance on Android / АлДĐșŃĐ°ĐœĐŽŃ€ ĐĄĐŒĐžŃ€ĐœĐŸĐČ (Splyt)
Kotlin Perfomance on Android / АлДĐșŃĐ°ĐœĐŽŃ€ ĐĄĐŒĐžŃ€ĐœĐŸĐČ (Splyt)Kotlin Perfomance on Android / АлДĐșŃĐ°ĐœĐŽŃ€ ĐĄĐŒĐžŃ€ĐœĐŸĐČ (Splyt)
Kotlin Perfomance on Android / АлДĐșŃĐ°ĐœĐŽŃ€ ĐĄĐŒĐžŃ€ĐœĐŸĐČ (Splyt)
 
Mixing functional and object oriented approaches to programming in C#
Mixing functional and object oriented approaches to programming in C#Mixing functional and object oriented approaches to programming in C#
Mixing functional and object oriented approaches to programming in C#
 
Vavr Java User Group Rheinland
Vavr Java User Group RheinlandVavr Java User Group Rheinland
Vavr Java User Group Rheinland
 
Kotlin
KotlinKotlin
Kotlin
 
6. Generics. Collections. Streams
6. Generics. Collections. Streams6. Generics. Collections. Streams
6. Generics. Collections. Streams
 
C++: Constructor, Copy Constructor and Assignment operator
C++: Constructor, Copy Constructor and Assignment operatorC++: Constructor, Copy Constructor and Assignment operator
C++: Constructor, Copy Constructor and Assignment operator
 
DataTypes.ppt
DataTypes.pptDataTypes.ppt
DataTypes.ppt
 
ADG PoznaƄ - Kotlin for Android developers
ADG PoznaƄ - Kotlin for Android developersADG PoznaƄ - Kotlin for Android developers
ADG PoznaƄ - Kotlin for Android developers
 
Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015
Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015
Functional Programming You Already Know - Kevlin Henney - Codemotion Rome 2015
 

KĂŒrzlich hochgeladen

Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...apidays
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...apidays
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfsudhanshuwaghmare1
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Bhuvaneswari Subramani
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century educationjfdjdjcjdnsjd
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodJuan lago vĂĄzquez
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingEdi Saputra
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamUiPathCommunity
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Victor Rentea
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businesspanagenda
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MIND CTI
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusZilliz
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfOrbitshub
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...apidays
 

KĂŒrzlich hochgeladen (20)

Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 

Sneaking inside Kotlin features

  • 1. Sneaking inside Kotlin features Chandra Sekhar
  • 5. lateinit properties lateinit var user: User @iChanSek bit.ly/chansecode
  • 6. lateinit properties public final User user; public final User getUser() { if (user == null) { throwUninitializedPropertyAccessException("user"); } return user; } public final void setUser(User newUser) { checkParameterIsNotNull(newUser, "<set-?>"); user = newUser; } @iChanSek bit.ly/chansecode
  • 7. lateinit properties public final User getUser() { if (user == null) { throwUninitializedPropertyAccessException("user"); } return user; } public final void setUser(User newUser) { checkParameterIsNotNull(newUser, "<set-?>"); @iChanSek bit.ly/chansecode
  • 8. lateinit properties public final User getUser() { if (user == null) { throwUninitializedPropertyAccessException("user"); } return user; } public final void setUser(User newUser) { checkParameterIsNotNull(newUser, "<set-?>"); user = newUser; } @iChanSek bit.ly/chansecode
  • 10. Delegated Properties class DelegatedProperties { val x by lazy { 10 } } @iChanSek bit.ly/chansecode
  • 11. Delegated Properties public final class DelegatedProperties { static final KProperty[] props = new KProperty[]{ ... } private final Lazy xDelegate; public final int getX() { return ((Number)xDelegate.getValue()).intValue(); } public DelegatedProperties() { this.xDelegate = LazyKt.lazy((Function0)2.INSTANCE); } } @iChanSek bit.ly/chansecode
  • 12. Delegated Properties public final class DelegatedProperties { static final KProperty[] props = new KProperty[]{ ... } private final Lazy xDelegate; public final int getX() { return ((Number)xDelegate.getValue()).intValue(); } public DelegatedProperties() { this.xDelegate = LazyKt.lazy((Function0)2.INSTANCE); } } @iChanSek bit.ly/chansecode
  • 13. Delegated Properties public final class DelegatedProperties { static final KProperty[] props = new KProperty[]{ ... } private final Lazy xDelegate; public final int getX() { return ((Number)xDelegate.getValue()).intValue(); } public DelegatedProperties() { this.xDelegate = LazyKt.lazy((Function0)2.INSTANCE); } } @iChanSek bit.ly/chansecode
  • 14. Delegated Properties public final class DelegatedProperties { static final KProperty[] props = new KProperty[]{ ... } private final Lazy xDelegate; public final int getX() { return ((Number)xDelegate.getValue()).intValue(); } public DelegatedProperties() { this.xDelegate = LazyKt.lazy((Function0)2.INSTANCE); } } @iChanSek bit.ly/chansecode
  • 15. Delegated Properties public final class DelegatedProperties { static final KProperty[] props = new KProperty[]{ ... } private final Lazy xDelegate; public final int getX() { return ((Number)xDelegate.getValue()).intValue(); } public DelegatedProperties() { this.xDelegate = LazyKt.lazy(() -> 10); } } @iChanSek bit.ly/chansecode
  • 16. Delegated Properties public final class DelegatedProperties { static final KProperty[] props = new KProperty[]{ ... } private final Lazy xDelegate; public final int getX() { return ((Number)xDelegate.getValue()).intValue(); } public DelegatedProperties() { this.xDelegate = LazyKt.lazy((Function0)2.INSTANCE); } } @iChanSek bit.ly/chansecode
  • 17. Delegated Properties public final int getX() { return ((Number)xDelegate.getValue()).intValue(); } @iChanSek bit.ly/chansecode fun main() { val delegatedProp = DelegatedProperties() println(delegatedProp.x) println(delegatedProp.x) }
  • 18. Delegated Properties class SynchronizedLazyImpl<out T>(initializer: () -> T, lock: Any? = null) : Lazy<T> { private var initializer: (() -> T)? = initializer @Volatile private var _value: Any? = UNINITIALIZED_VALUE private val lock = lock ?: this override val value: T get() { if (_value !== UNINITIALIZED_VALUE) { return _value as T } return synchronized(lock) { ... } } } @iChanSek bit.ly/chansecode fun main() { val delegatedProp = DelegatedProperties() println(delegatedProp.x) println(delegatedProp.x) } public final int getX() { return ((Number)xDelegate.getValue()).intValue(); }
  • 19. Delegated Properties class SynchronizedLazyImpl<out T>(initializer: () -> T, lock: Any? = null) : Lazy<T> { private var initializer: (() -> T)? = initializer @Volatile private var _value: Any? = UNINITIALIZED_VALUE private val lock = lock ?: this override val value: T get() { if (_value !== UNINITIALIZED_VALUE) { return _value as T } return synchronized(lock) { ... } } } @iChanSek bit.ly/chansecode
  • 20. Delegated Properties class SynchronizedLazyImpl<out T>(initializer: () -> T, lock: Any? = null) : Lazy<T> { private var initializer: (() -> T)? = initializer @Volatile private var _value: Any? = UNINITIALIZED_VALUE private val lock = lock ?: this override val value: T get() { if (_value !== UNINITIALIZED_VALUE) { return _value as T } return synchronized(lock) { ... } } } @iChanSek bit.ly/chansecode
  • 21. 1.3 Nullable and Non-Nullable @iChanSek bit.ly/chansecode
  • 22. Nullable and Non-Nullable val nullableConf: Conference? = null val confName = nullableConf?.name @iChanSek bit.ly/chansecode
  • 23. Nullable and Non-Nullable Conference conf = nullableConf; String confName = conf != null ? conf.getName() : null @iChanSek bit.ly/chansecode
  • 24. Nullable and Non-Nullable val c = a?.b?.c @iChanSek bit.ly/chansecode
  • 25. Nullable and Non-Nullable if (a != null) { B b = a.b; } @iChanSek bit.ly/chansecode
  • 26. Nullable and Non-Nullable C c; if (a != null) { B b = a.b; if (b != null) { c = b.c; } } @iChanSek bit.ly/chansecode
  • 27. Nullable and Non-Nullable C c; label1: { if (a != null) { B b = a.b; if (b != null) { c = b.c; break label1; } } c = null; } @iChanSek bit.ly/chansecode
  • 28. Nullable and Non-Nullable val d = a!!.b!!.c @iChanSek bit.ly/chansecode
  • 29. Nullable and Non-Nullable if (a == null) throwNpe(); B b = a.b; @iChanSek bit.ly/chansecode
  • 30. Nullable and Non-Nullable if (a == null) throwNpe(); B b = a.b; if (b == null) throwNpe(); C c = b.c; @iChanSek bit.ly/chansecode
  • 31. 2. Control Flows @iChanSek bit.ly/chansecode
  • 32. 2.1 If Expression @iChanSek bit.ly/chansecode
  • 33. If Expression val max = if (a > b) a else b @iChanSek bit.ly/chansecode
  • 34. If Expression int max = a > b ? a : b @iChanSek bit.ly/chansecode
  • 35. If Expression val max = if (a > b) { print("a is bigger") a } else { print("b is bigger") b } @iChanSek bit.ly/chansecode
  • 36. If Expression int max; if (a > b) { S.O.P("a is bigger"); max = a; } else { S.O.P("b is bigger"); max = b; } @iChanSek bit.ly/chansecode
  • 37. 2.2 When Expression @iChanSek bit.ly/chansecode
  • 38. When Expression when (x) { 1 -> print("x == 1") 2 -> print("x == 2") else -> print("x is neither 1 nor 2") } @iChanSek bit.ly/chansecode
  • 39. When Expression switch (x) { case 1: S.O.P("x == 1"); break; case 2: S.O.P("x == 2"); break; default: S.O.P("x is neither 1 nor 2"); break; } @iChanSek bit.ly/chansecode
  • 40. When Expression when (x) { 1 -> print("x == 1") 2 -> print("x == 2") else -> print("x is neither 1 nor 2") } @iChanSek bit.ly/chansecode
  • 41. When Expression when { x == 1 -> print("x == 1") x == 2 -> print("x == 2") else -> print("x is neither 1 nor 2") } @iChanSek bit.ly/chansecode
  • 42. When Expression if (x == 1) { S.O.P("x == 1"); } else if (x == 2) { S.O.P("x == 2"); } else { S.O.P("x is neither 1 nor 2”); } @iChanSek bit.ly/chansecode
  • 43. When Expression enum class Colour { RED, GREEN, BLUE } when (colour) { Colour.RED -> ... Colour.GREEN -> ... Colour.BLUE -> ... } @iChanSek bit.ly/chansecode
  • 44. When Expression switch(WhenMappings.$EnumSwitchMapping$0[colour.ordinal()]) { case 1: ... break; case 2: ... break; case 3: ... break; ...... } @iChanSek bit.ly/chansecode
  • 45. When Expression switch(WhenMappings.$EnumSwitchMapping$0[colour.ordinal()]) { case 1: ... break; case 2: ... break; case 3: ... break; ...... } @iChanSek bit.ly/chansecode public final class WhenKt$WhenMappings { public static final int[] $EnumSwitchMapping$0 = new int[Colour.values().length]; static { $EnumSwitchMapping$0[Colour.RED.ordinal()] = 1; $EnumSwitchMapping$0[Colour.GREEN.ordinal()] = 2; $EnumSwitchMapping$0[Colour.BLUE.ordinal()] = 3; } }
  • 46. When Expression switch(WhenMappings.$EnumSwitchMapping$0[colour.ordinal()]) { case 1: ... break; case 2: ... break; case 3: ... break; ...... } @iChanSek bit.ly/chansecode public final class WhenKt$WhenMappings { public static final int[] $EnumSwitchMapping$0 = new int[Colour.values().length]; static { $EnumSwitchMapping$0[Colour.RED.ordinal()] = 1; $EnumSwitchMapping$0[Colour.GREEN.ordinal()] = 2; $EnumSwitchMapping$0[Colour.BLUE.ordinal()] = 3; } }
  • 47. 3. Classes & Interfaces @iChanSek bit.ly/chansecode
  • 48. 3.1 Data Classes @iChanSek bit.ly/chansecode
  • 49. Data Classes class User( val name: String, val age: Int ) @iChanSek bit.ly/chansecode
  • 50. Destructuring Declarations class User( val name: String, val age: Int ) val user = User("Chandra", 10) val (name, age) = user @iChanSek bit.ly/chansecode
  • 51. Destructuring Declarations class User( val name: String, val age: Int ) val user = User("Chandra", 10) val (name, age) = user @iChanSek bit.ly/chansecode
  • 52. Destructuring Declarations data class User( val name: String, val age: Int ) val user = User("Chandra", 10) val (name, age) = user @iChanSek bit.ly/chansecode
  • 53. Destructuring Declarations public final class User { ... public final String component1() { return this.name; } public final int component2() { return this.age; } val user = User("Chandra", 10) } val (name, age) = user @iChanSek bit.ly/chansecode
  • 54. Destructuring Declarations public final class User { ... public final String component1() { return this.name; } public final int component2() { return this.age; } } @iChanSek bit.ly/chansecode String name = user.component1(); int age = user.component2();
  • 55. 3.2 Sealed Classes @iChanSek bit.ly/chansecode
  • 56. Sealed Classes sealed class Calculation class Add(val num1: Int, val num2: Int) : Calculation() class Sub(val num1: Int, val num2: Int) : Calculation() class Mul(val num1: Int, val num2: Int) : Calculation() class Div(val num1: Int, val num2: Int) : Calculation() @iChanSek bit.ly/chansecode
  • 57. Sealed Classes public abstract class Calculation { private Calculation() {} } class Add(val num1: Int, val num2: Int) : Calculation() class Sub(val num1: Int, val num2: Int) : Calculation() class Mul(val num1: Int, val num2: Int) : Calculation() class Div(val num1: Int, val num2: Int) : Calculation() @iChanSek bit.ly/chansecode
  • 58. Sealed Classes public abstract class Calculation { private Calculation() {} } public final class Add extends Calculation { ... } public final class Sub extends Calculation { ... } public final class Mul extends Calculation { ... } public final class Div extends Calculation { ... } @iChanSek bit.ly/chansecode
  • 59. Sealed Classes private fun calculate(calculator: Calculation) { when(calculator) { is Add -> calculator.num1 + calculator.num2 is Sub -> calculator.num1 - calculator.num2 is Mul -> calculator.num1 * calculator.num2 is Div -> calculator.num1 / calculator.num2 } } @iChanSek bit.ly/chansecode
  • 60. Sealed Classes private static final void calculate(Calculation calculator) { int result; if (calculator instanceof Add) { result = ((Add)calculator).getNum1() + ((Add)calculator).getNum2(); } else if (calculator instanceof Sub) { result = ((Sub)calculator).getNum1() - ((Sub)calculator).getNum2(); } else if (calculator instanceof Mul) { result = ((Mul)calculator).getNum1() * ((Mul)calculator).getNum2(); } else if (calculator instanceof Div) { result = ((Div)calculator).getNum1() / ((Div)calculator).getNum2(); } } @iChanSek bit.ly/chansecode
  • 61. 3.3 Inline Classes @iChanSek bit.ly/chansecode
  • 62. Inline Classes inline class UserId(val value: Long) @iChanSek bit.ly/chansecode
  • 63. Inline Classes public final class UserId { private final long id; public static long constructor_impl(long id) { return id; } public static final UserId box_impl(long v) { return new UserId(v); } public final long unbox_impl() { return this.id; } } @iChanSek bit.ly/chansecode
  • 64. Inline Classes public final class UserId { private final long id; public static long constructor_impl(long id) { return id; } public static final UserId box_impl(long v) { return new UserId(v); } public final long unbox_impl() { return this.id; } } @iChanSek bit.ly/chansecode
  • 65. Inline Classes public final class UserId { private final long id; public static long constructor_impl(long id) { return id; } public static final UserId box_impl(long v) { return new UserId(v); } public final long unbox_impl() { return this.id; } } @iChanSek bit.ly/chansecode
  • 66. Inline Classes public final class UserId { private final long id; public static long constructor_impl(long id) { return id; } public static final UserId box_impl(long v) { return new UserId(v); } public final long unbox_impl() { return this.id; } } @iChanSek bit.ly/chansecode
  • 67. Inline Classes fun main() { val userId = UserId(10L) getUser(userId) } private fun getUser(id: UserId) { // Do something with id } @iChanSek bit.ly/chansecode
  • 68. Inline Classes public static final void main() { long userId = UserId.constructor_impl(10L); getUser(userId); } // UserId became long in the argument private static final void getUser(long id) { // Do something with id } @iChanSek bit.ly/chansecode
  • 69. 3.4 Default Methods @iChanSek bit.ly/chansecode
  • 70. Default Methods interface Calculator { fun div(a: Int, b: Int) = ... } @iChanSek bit.ly/chansecode
  • 71.
  • 72. Default Methods class DefaultCalculatorImpl : Calculator class CalculatorImpl : Calculator { override fun div(a: Int, b: Int): Int { ... } } @iChanSek bit.ly/chansecode
  • 73. Default Methods public final class DefaultCalculatorImpl implements Calculator { public int div(int a, int b) { return Calculator.DefaultImpls.div(this, a, b); } } public final class CalculatorImpl implements Calculator { public int div(int a, int b) { ... } } @iChanSek bit.ly/chansecode
  • 75. 4.1 Extension Function @iChanSek bit.ly/chansecode
  • 76. Extension Function fun IntArray.swap(index1: Int, index2: Int) { val temp = this[index1] this[index1] = this[index2] this[index2] = temp } @iChanSek bit.ly/chansecode
  • 77. Extension Function public static final void swap(int[] arr, int index1, int index2) { Intrinsics.checkParameterIsNotNull(arr, "arr"); int temp = arr[index1]; arr[index1] = arr[index2]; arr[index2] = temp; } @iChanSek bit.ly/chansecode
  • 78. Extension Function val arr = intArrayOf(1, 2, 3, 4, 5) arr.swap(2, 4) @iChanSek bit.ly/chansecode
  • 79. Extension Function int[] arr = new int[]{1, 2, 3, 4, 5}; swap(arr, 2, 4); @iChanSek bit.ly/chansecode
  • 80. 4.2 Default Arguments @iChanSek bit.ly/chansecode
  • 81. Default Arguments fun add(a: Int, b : Int, c: Int = 100, d: Int = 200, e: Int = 300) = a + b + c + d + e @iChanSek bit.ly/chansecode
  • 82. Default Arguments ... int add(int a, int b, int c, int d, int e) { return a + b + c + d + e; } @iChanSek bit.ly/chansecode
  • 83. Default Arguments ... int add(int a, int b, int c, int d, int e) { return a + b + c + d + e; } fun main() { add(2, 3, 4, 5, 6) } @iChanSek bit.ly/chansecode
  • 84. Default Arguments ... int add(int a, int b, int c, int d, int e) { return a + b + c + d + e; } fun main() { add(2, 3, 4, 5, 6) add(2, 3) } @iChanSek bit.ly/chansecode
  • 85. Default Arguments ... int add(int a, int b, int c, int d, int e) { return a + b + c + d + e; } fun main() { add(2, 3, 4, 5, 6) add(2, 3) add(2, 3, 4, 5) } @iChanSek bit.ly/chansecode
  • 86. Default Arguments ... int add(int a, int b, int c, int d, int e) { return a + b + c + d + e; } public static final void main() { add(2, 3, 4, 5, 6); add(2, 3, 0, 0, 0, 28, _); add(2, 3, 4, 5, 0, 16, _); } @iChanSek bit.ly/chansecode
  • 87. Default Arguments ... int add$default(int a, int b, int c, int d, int e, int var5, _) { ... } public static final void main() { add(2, 3, 4, 5, 6); add$default(2, 3, 0, 0, 0, 28, _); add$default(2, 3, 4, 5, 0, 16, _); } @iChanSek bit.ly/chansecode
  • 88. Default Arguments ... int add$default(int a, int b, int c, int d, int e, int var5, 
) { ... } public static final void main() { add(2, 3, 4, 5, 6); add$default(2, 3, 0, 0, 0, 22 + 23 + 24, _); add$default(2, 3, 4, 5, 0, 24, _); } @iChanSek bit.ly/chansecode
  • 89. Default Arguments ... int add$default(int a, int b, int c, int d, int e, int var5, _) { if ((var5 & 4) != 0) c = 100; if ((var5 & 8) != 0) d = 200; if ((var5 & 16) != 0) e = 300; return add(a, b, c, d, e); } @iChanSek bit.ly/chansecode
  • 90. 4.3 Local Functions @iChanSek bit.ly/chansecode
  • 91. Local Functions fun outer() { fun inner() { println(“ Kolkata”) } println(“Welcome to DevFest") if (event == "DevFest Kolkata") inner() } @iChanSek bit.ly/chansecode
  • 92. Local Functions public static final void outer() { Inner inner = Inner.INSTANCE; System.out.println("Welcome to DevFest"); if (Intrinsics.areEqual(event, "DevFest Kolkata")) { inner.invoke(); } } @iChanSek bit.ly/chansecode
  • 93. Local Functions public static final void outer() { Inner inner = Inner.INSTANCE; System.out.println("Welcome to DevFest"); if (Intrinsics.areEqual(event, "DevFest Kolkata")) { inner.invoke(); } } @iChanSek bit.ly/chansecode final class Inner extends Lambda implements Function0 { ... Inner INSTANCE = new Inner(); public final void invoke() { System.out.println(" Kolkata"); } Inner() { super(0); } }
  • 94. 4.4 Lambda Functions @iChanSek bit.ly/chansecode
  • 95. Lambda Functions val sum: (Int, Int) -> Int = { x, y -> x + y } @iChanSek bit.ly/chansecode
  • 96. Lambda Functions val sum: (Int, Int) -> Int = { x, y -> x + y } ... Function2<_, _, _> sum = new Function2<_, _, _>() { @Override public final int invoke(int a, int b) { return a + b; } }; @iChanSek bit.ly/chansecode
  • 97. Lambda Functions () -> Unit == class XXX implements Function0<Unit> @iChanSek bit.ly/chansecode
  • 98. Lambda Functions () -> Unit == class XXX implements Function0<Unit> (Int, Int) -> Int == class XXX implements Function2<Int, Int, Int> @iChanSek bit.ly/chansecode
  • 99. 4.5 Lambda with Receiver @iChanSek bit.ly/chansecode
  • 100. Lambda with Receiver val sum: (Int, Int) -> Int = { x, y -> x + y } @iChanSek bit.ly/chansecode
  • 101. Lambda with Receiver val sum: Int.(Int) -> Int = { this + it } @iChanSek bit.ly/chansecode
  • 102. Lambda with Receiver val sum: Int.(Int) -> Int = { this + it } ... Function2<_, _, _> sum = new Function2<_, _, _>() { @Override public final int invoke(int $receiver, int a) { return $receiver + a; } }; @iChanSek bit.ly/chansecode
  • 103. Lambda Functions () -> Unit == class XXX implements Function0<Unit> (Int, Int) -> Int == class XXX implements Function2<Int, Int, Int> @iChanSek bit.ly/chansecode
  • 104. Lambda Functions () -> Unit == class XXX implements Function0<Unit> (Int, Int) -> Int == class XXX implements Function2<Int, Int, Int> Int.(Int) -> Int == class XXX implements Function2<Int, Int, Int> @iChanSek bit.ly/chansecode
  • 105. 5. How to Sneak @iChanSek bit.ly/chansecode
  • 106. How to Sneak @iChanSek bit.ly/chansecode
  • 107. How to Sneak @iChanSek bit.ly/chansecode