SlideShare a Scribd company logo
Idiomatic Kotlin
Dmitry Jemerov <yole@jetbrains.com>
Expressions
Use ‘when’ as expression body
fun parseNum(number: String): Int? {
when (number) {
"one" -> return 1
"two" -> return 2
else -> return null
}
}
Use ‘when’ as expression body
fun parseNum(number: String): Int? {
when (number) {
"one" -> return 1
"two" -> return 2
else -> return null
}
}
fun parseNum(number: String) =
when (number) {
"one" -> 1
"two" -> 2
else -> null
}
Use ‘try’ as expression body
fun tryParse(number: String): Int? {
try {
return Integer.parseInt(number)
}
catch (e: NumberFormatException) {
return null
}
}
Use ‘try’ as expression body
fun tryParse(number: String): Int? {
try {
return Integer.parseInt(number)
}
catch (e: NumberFormatException) {
return null
}
}
fun tryParse(number: String) =
try {
Integer.parseInt(number)
}
catch (e: NumberFormatException) {
null
}
Use ‘try’ as expression
fun tryParse(number: String): Int? {
try {
return Integer.parseInt(number)
}
catch (e: NumberFormatException) {
return null
}
}
fun tryParse(number: String): Int? {
val n = try {
Integer.parseInt(number)
} catch (e: NumberFormatException) {
null
}
println(n)
return n
}
Use elvis with ‘return’ and ‘throw’
fun processPerson(person: Person) {
val name = person.name
if (name == null)
throw IllegalArgumentException(

"Named required")
val age = person.age
if (age == null) return
println("$name: $age")
}
class Person(val name: String?,
val age: Int?)
Use elvis with ‘return’ and ‘throw’
fun processPerson(person: Person) {
val name = person.name
if (name == null)
throw IllegalArgumentException(

"Named required")
val age = person.age
if (age == null) return
println("$name: $age")
}
fun processPerson(person: Person) {
val name = person.name ?:
throw IllegalArgumentException(
"Name required")
val age = person.age ?: return
println("$name: $age")
}
class Person(val name: String?,
val age: Int?)
Use range checks instead of comparison pairs
fun isLatinUppercase(c: Char) =
c >= 'A' && c <= 'Z'
Use range checks instead of comparison pairs
fun isLatinUppercase(c: Char) =
c >= 'A' && c <= 'Z'
fun isLatinUppercase(c: Char) =
c in 'A'..'Z'
Classes and Functions
Don’t create classes just to put functions in
class StringUtils {
companion object {
fun isPhoneNumber(s: String) =
s.length == 7 &&
s.all { it.isDigit() }
}
}
Don’t create classes just to put functions in
class StringUtils {
companion object {
fun isPhoneNumber(s: String) =
s.length == 7 &&
s.all { it.isDigit() }
}
}
object StringUtils {
fun isPhoneNumber(s: String) =
s.length == 7 &&
s.all { it.isDigit() }
}
Don’t create classes just to put functions in
class StringUtils {
companion object {
fun isPhoneNumber(s: String) =
s.length == 7 &&
s.all { it.isDigit() }
}
} fun isPhoneNumber(s: String) =
s.length == 7 &&
s.all { it.isDigit() }
object StringUtils {
fun isPhoneNumber(s: String) =
s.length == 7 &&
s.all { it.isDigit() }
}
Use extension functions copiously
fun isPhoneNumber(s: String) =
s.length == 7 &&
s.all { it.isDigit() }
Use extension functions copiously
fun isPhoneNumber(s: String) =
s.length == 7 &&
s.all { it.isDigit() }
fun String.isPhoneNumber() =
length == 7 &&
all { it.isDigit() }
Avoid using member extension functions 

(unless required for DSLs)
class PhoneBook {
fun String.isPhoneNumber() =
length == 7 &&
all { it.isDigit() }
}
Avoid using member extension functions 

(unless required for DSLs)
class PhoneBook {
fun String.isPhoneNumber() =
length == 7 &&
all { it.isDigit() }
}
class PhoneBook {
}
private fun
String.isPhoneNumber() =
length == 7 &&
all { it.isDigit() }
Don't use member extensions with 

containing class as the receiver
class PhoneBook {
fun PhoneBook.find(name: String)=
"1234567"
}
Don't use member extensions with 

containing class as the receiver
class PhoneBook {
fun PhoneBook.find(name: String)=
"1234567"
}
class PhoneBook {
fun find(name: String) =
"1234567"
}
Consider extracting non-essential API

of classes into extensions
class Person(val firstName: String,
val lastName: String) {
val fullName: String
get() = "$firstName $lastName"
}
Consider extracting non-essential API

of classes into extensions
class Person(val firstName: String,
val lastName: String) {
val fullName: String
get() = "$firstName $lastName"
}
class Person(val firstName: String,
val lastName: String)
val Person.fullName: String
get() = "$firstName $lastName"
Use default parameter values instead of overloads
wherever possible
class Phonebook {
fun print() {
print(",")
}
fun print(separator: String) {
}
}
fun main(args: Array<String>) {
Phonebook().print("|")
}
Use default parameter values instead of overloads
wherever possible
class Phonebook {
fun print() {
print(",")
}
fun print(separator: String) {
}
}
fun main(args: Array<String>) {
Phonebook().print("|")
}
class Phonebook {
fun print(

separator: String = ",") {
}
}
fun main(args: Array<String>) {
Phonebook().print(
separator = "|")
}
Use ‘lateinit’ for properties that can’t be initialised
in a constructor
class MyTest {
class State(val data: String)
var state: State? = null
@Before fun setup() {
state = State("abc")
}
@Test fun foo() {
Assert.assertEquals(

"abc", state!!.data)
}
}
Use ‘lateinit’ for properties that can’t be initialised
in a constructor
class MyTest {
class State(val data: String)
var state: State? = null
@Before fun setup() {
state = State("abc")
}
@Test fun foo() {
Assert.assertEquals(

"abc", state!!.data)
}
}
class MyTest {
class State(val data: String)
lateinit var state: State
@Before fun setup() {
state = State("abc")
}
@Test fun foo() {
Assert.assertEquals(

"abc", state.data)
}
}
Use type aliases for functional types and
collections
class EventDispatcher {
fun addClickHandler(

handler: (Event) -> Unit) {
}
fun removeClickHandler(
handler: (Event) -> Unit) {
}
}
Use type aliases for functional types and
collections
class EventDispatcher {
fun addClickHandler(

handler: (Event) -> Unit) {
}
fun removeClickHandler(
handler: (Event) -> Unit) {
}
}
typealias ClickHandler =
(Event) -> Unit
class EventDispatcher {
fun addClickHandler(
handler: ClickHandler) {
}
fun removeClickHandler(
handler: ClickHandler) {
}
}
Use type aliases for functional types and
collections
class EventDispatcher {
fun addClickHandler(

handler: (Event) -> Unit) {
}
fun removeClickHandler(
handler: (Event) -> Unit) {
}
}
typealias ClickHandler =
(Event) -> Unit
typealias HandlerMap =
Map<EventType, List<Event>>
Use data classes to return multiple values
fun namedNum(): Pair<Int, String> =
1 to "one"
fun main(args: Array<String>) {
val pair = namedNum()
val number = pair.first
val name = pair.second
}
Use data classes to return multiple values
fun namedNum(): Pair<Int, String> =
1 to "one"
fun main(args: Array<String>) {
val pair = namedNum()
val number = pair.first
val name = pair.second
}
data class NamedNumber(
val number: Int,
val name: String)
fun namedNum() =
NamedNumber(1, "one")
fun main(args: Array<String>) {
val (number, name) =

namedNum()
}
Use destructuring in loops
fun printMap(m: Map<String, String>) {
for (e in m.entries) {
println("${e.key} -> ${e.value}")
}
}
Use destructuring in loops
fun printMap(m: Map<String, String>) {
for (e in m.entries) {
println("${e.key} -> ${e.value}")
}
}
fun printMap(m: Map<String, String>) {
for ((key, value) in m) {
println("$key -> $value")
}
}
Use destructuring with lists
fun splitNameExt(fn: String): NameExt {
if ('.' in fn) {
val parts = fn.split('.', limit = 2)
return NameExt(parts[0], parts[1])
}
return NameExt(fn, null)
}
data class NameExt(val name: String,
val ext: String?)
Use destructuring with lists
fun splitNameExt(fn: String): NameExt {
if ('.' in fn) {
val parts = fn.split('.', limit = 2)
return NameExt(parts[0], parts[1])
}
return NameExt(fn, null)
}
fun splitNameExt(fn: String): NameExt {
if ('.' in fn) {
val (name, ext) =
fn.split('.', limit = 2)
return NameExt(name, ext)
}
return NameExt(fn, null)
}
data class NameExt(val name: String,
val ext: String?)
Use ‘copy’ method for data classes
class Person(val name: String,
var age: Int)
fun happyBirthday(person: Person) {
person.age++
}
Use ‘copy’ method for data classes
class Person(val name: String,
var age: Int)
fun happyBirthday(person: Person) {
person.age++
}
data class Person(val name: String,
val age: Int)
fun happyBirthday(person: Person) =
person.copy(
age = person.age + 1)
The Standard Library
Use ‘coerceIn’ to ensure a number is in range
fun updateProgress(value: Int) {
val newValue = when {
value < 0 -> 0
value > 100 -> 100
else -> value
}
}
Use ‘coerceIn’ to ensure a number is in range
fun updateProgress(value: Int) {
val newValue = when {
value < 0 -> 0
value > 100 -> 100
else -> value
}
}
fun updateProgress(value: Int) {
val newValue = 

value.coerceIn(0, 100)
}
Use ‘apply’ for object initialisation
fun createLabel(): JLabel {
val label = JLabel("Foo")
label.foreground = Color.RED
label.background = Color.BLUE
return label
}
Use ‘apply’ for object initialisation
fun createLabel(): JLabel {
val label = JLabel("Foo")
label.foreground = Color.RED
label.background = Color.BLUE
return label
}
fun createLabel() =
JLabel("Foo").apply {
foreground = Color.RED
background = Color.BLUE
}
Use ‘filterIsInstance’ to filter a list by object type
fun findStrings(objs: List<Any>) =
objs.filter { it is String }
Use ‘filterIsInstance’ to filter a list by object type
fun findStrings(objs: List<Any>) =
objs.filter { it is String }
fun findStrings(objs: List<Any>) =
obs.filterIsInstance<String>()
Use ‘mapNotNull’ to apply a function and select
items for which it returns a non-null value
fun listErrors(

results: List<Result>) =
results
.map { it.error }
.filterNotNull()
data class Result(val data: Any?,
val error: String?)
Use ‘mapNotNull’ to apply a function and select
items for which it returns a non-null value
fun listErrors(

results: List<Result>) =
results
.map { it.error }
.filterNotNull()
fun listErrors(
results: List<Result>) =
results.mapNotNull { 

it.error
}
data class Result(val data: Any?,
val error: String?)
Use ‘compareBy’ for multi-step comparisons
fun sortPersons(persons: List<Person>) =
persons.sortedWith(
Comparator<Person> { p1, p2 ->
val rc =
p1.name.compareTo(p2.name)
if (rc != 0)
rc
else
p1.age - p2.age
})
class Person(val name: String,
val age: Int)
Use ‘compareBy’ for multi-step comparisons
fun sortPersons(persons: List<Person>) =
persons.sortedWith(
Comparator<Person> { p1, p2 ->
val rc =
p1.name.compareTo(p2.name)
if (rc != 0)
rc
else
p1.age - p2.age
})
fun sortPersons(persons: List<Person>) =
persons.sortedWith(
compareBy(Person::name,
Person::age))
class Person(val name: String,
val age: Int)
Use ‘groupBy’ to group items in a collection
fun analyzeLog(log: List<Request>) {
val map = mutableMapOf<String,
MutableList<Request>>()
for (request in log) {
map.getOrPut(request.url)
{ mutableListOf() }
.add(request)
}
}
class Request(val url: String,
val remoteIP: String,
val timestamp: Long)
Use ‘groupBy’ to group items in a collection
fun analyzeLog(log: List<Request>) {
val map = mutableMapOf<String,
MutableList<Request>>()
for (request in log) {
map.getOrPut(request.url)
{ mutableListOf() }
.add(request)
}
}
fun analyzeLog(log: List<Request>) {
val map = log.groupBy(Request::url)
}
class Request(val url: String,
val remoteIP: String,
val timestamp: Long)
Use String methods for string parsing
val pattern = Regex("(.+)/([^/]*)")
fun splitPath(path: String): PathParts {
val match = pattern.matchEntire(path)
?: return PathParts("", path)
return PathParts(match.groupValues[1],
match.groupValues[2])
}
data class PathParts(val dir: String,
val name: String)
Use String methods for string parsing
val pattern = Regex("(.+)/([^/]*)")
fun splitPath(path: String): PathParts {
val match = pattern.matchEntire(path)
?: return PathParts("", path)
return PathParts(match.groupValues[1],
match.groupValues[2])
}
fun splitPath(path: String) =
PathParts(
path.substringBeforeLast('/', ""),
path.substringAfterLast(‘/'))
data class PathParts(val dir: String,
val name: String)
Q&A
yole@jetbrains.com
@intelliyole

More Related Content

What's hot

From object oriented to functional domain modeling
From object oriented to functional domain modelingFrom object oriented to functional domain modeling
From object oriented to functional domain modeling
Mario Fusco
 
[Kotlin 讀書會第五梯次] 深入淺出 Kotlin 第一章導讀
[Kotlin 讀書會第五梯次] 深入淺出 Kotlin 第一章導讀[Kotlin 讀書會第五梯次] 深入淺出 Kotlin 第一章導讀
[Kotlin 讀書會第五梯次] 深入淺出 Kotlin 第一章導讀
Shengyou Fan
 
Functional Programming Patterns (NDC London 2014)
Functional Programming Patterns (NDC London 2014)Functional Programming Patterns (NDC London 2014)
Functional Programming Patterns (NDC London 2014)
Scott Wlaschin
 
enums
enumsenums
enums
teach4uin
 
Java conditional statements
Java conditional statementsJava conditional statements
Java conditional statements
Kuppusamy P
 
Java Foundations: Methods
Java Foundations: MethodsJava Foundations: Methods
Java Foundations: Methods
Svetlin Nakov
 
Introduction to Kotlin coroutines
Introduction to Kotlin coroutinesIntroduction to Kotlin coroutines
Introduction to Kotlin coroutines
Roman Elizarov
 
Introduction to kotlin
Introduction to kotlinIntroduction to kotlin
Introduction to kotlin
Shaul Rosenzwieg
 
java 8 new features
java 8 new features java 8 new features
java 8 new features
Rohit Verma
 
Introduction to Coroutines @ KotlinConf 2017
Introduction to Coroutines @ KotlinConf 2017Introduction to Coroutines @ KotlinConf 2017
Introduction to Coroutines @ KotlinConf 2017
Roman Elizarov
 
Java 8 - CJ
Java 8 - CJJava 8 - CJ
Java 8 - CJ
Sunil OS
 
React hooks
React hooksReact hooks
React hooks
Ramy ElBasyouni
 
The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)
Scott Wlaschin
 
A quick and fast intro to Kotlin
A quick and fast intro to Kotlin A quick and fast intro to Kotlin
A quick and fast intro to Kotlin
XPeppers
 
Java 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional InterfacesJava 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional Interfaces
Ganesh Samarthyam
 
Utilizing kotlin flows in an android application
Utilizing kotlin flows in an android applicationUtilizing kotlin flows in an android application
Utilizing kotlin flows in an android application
Seven Peaks Speaks
 
React hooks
React hooksReact hooks
React hooks
Sadhna Rana
 
Java 8-streams-collectors-patterns
Java 8-streams-collectors-patternsJava 8-streams-collectors-patterns
Java 8-streams-collectors-patterns
José Paumard
 
QA Fes 2016. Алексей Виноградов. Page Objects: лучше проще, да лучшe
QA Fes 2016. Алексей Виноградов. Page Objects: лучше проще, да лучшeQA Fes 2016. Алексей Виноградов. Page Objects: лучше проще, да лучшe
QA Fes 2016. Алексей Виноградов. Page Objects: лучше проще, да лучшe
QAFest
 

What's hot (20)

From object oriented to functional domain modeling
From object oriented to functional domain modelingFrom object oriented to functional domain modeling
From object oriented to functional domain modeling
 
[Kotlin 讀書會第五梯次] 深入淺出 Kotlin 第一章導讀
[Kotlin 讀書會第五梯次] 深入淺出 Kotlin 第一章導讀[Kotlin 讀書會第五梯次] 深入淺出 Kotlin 第一章導讀
[Kotlin 讀書會第五梯次] 深入淺出 Kotlin 第一章導讀
 
Functional Programming Patterns (NDC London 2014)
Functional Programming Patterns (NDC London 2014)Functional Programming Patterns (NDC London 2014)
Functional Programming Patterns (NDC London 2014)
 
enums
enumsenums
enums
 
Java conditional statements
Java conditional statementsJava conditional statements
Java conditional statements
 
Java Foundations: Methods
Java Foundations: MethodsJava Foundations: Methods
Java Foundations: Methods
 
Introduction to Kotlin coroutines
Introduction to Kotlin coroutinesIntroduction to Kotlin coroutines
Introduction to Kotlin coroutines
 
Introduction to kotlin
Introduction to kotlinIntroduction to kotlin
Introduction to kotlin
 
java 8 new features
java 8 new features java 8 new features
java 8 new features
 
Introduction to Coroutines @ KotlinConf 2017
Introduction to Coroutines @ KotlinConf 2017Introduction to Coroutines @ KotlinConf 2017
Introduction to Coroutines @ KotlinConf 2017
 
Java 8 - CJ
Java 8 - CJJava 8 - CJ
Java 8 - CJ
 
React hooks
React hooksReact hooks
React hooks
 
The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)The Power of Composition (NDC Oslo 2020)
The Power of Composition (NDC Oslo 2020)
 
Java I/O
Java I/OJava I/O
Java I/O
 
A quick and fast intro to Kotlin
A quick and fast intro to Kotlin A quick and fast intro to Kotlin
A quick and fast intro to Kotlin
 
Java 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional InterfacesJava 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional Interfaces
 
Utilizing kotlin flows in an android application
Utilizing kotlin flows in an android applicationUtilizing kotlin flows in an android application
Utilizing kotlin flows in an android application
 
React hooks
React hooksReact hooks
React hooks
 
Java 8-streams-collectors-patterns
Java 8-streams-collectors-patternsJava 8-streams-collectors-patterns
Java 8-streams-collectors-patterns
 
QA Fes 2016. Алексей Виноградов. Page Objects: лучше проще, да лучшe
QA Fes 2016. Алексей Виноградов. Page Objects: лучше проще, да лучшeQA Fes 2016. Алексей Виноградов. Page Objects: лучше проще, да лучшe
QA Fes 2016. Алексей Виноградов. Page Objects: лучше проще, да лучшe
 

Similar to Idiomatic Kotlin

かとうの Kotlin 講座 こってり版
かとうの Kotlin 講座 こってり版かとうの Kotlin 講座 こってり版
かとうの Kotlin 講座 こってり版
Yutaka Kato
 
Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2
Kirill Rozov
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
Aleksandar Prokopec
 
Benefits of Kotlin
Benefits of KotlinBenefits of Kotlin
Benefits of Kotlin
Benjamin Waye
 
Scala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 WorldScala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 World
BTI360
 
SDC - Einführung in Scala
SDC - Einführung in ScalaSDC - Einführung in Scala
SDC - Einführung in Scala
Christian Baranowski
 
Scala taxonomy
Scala taxonomyScala taxonomy
Scala taxonomy
Radim Pavlicek
 
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kirill Rozov
 
Kotlin
KotlinKotlin
Pooya Khaloo Presentation on IWMC 2015
Pooya Khaloo Presentation on IWMC 2015Pooya Khaloo Presentation on IWMC 2015
Pooya Khaloo Presentation on IWMC 2015
Iran Entrepreneurship Association
 
A swift introduction to Swift
A swift introduction to SwiftA swift introduction to Swift
A swift introduction to Swift
Giordano Scalzo
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
Swift 함수 커링 사용하기
Swift 함수 커링 사용하기Swift 함수 커링 사용하기
Swift 함수 커링 사용하기
진성 오
 
Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014
Baruch Sadogursky
 
여자개발자모임터 6주년 개발 세미나 - Scala Language
여자개발자모임터 6주년 개발 세미나 - Scala Language여자개발자모임터 6주년 개발 세미나 - Scala Language
여자개발자모임터 6주년 개발 세미나 - Scala Language
Ashal aka JOKER
 

Similar to Idiomatic Kotlin (20)

かとうの Kotlin 講座 こってり版
かとうの Kotlin 講座 こってり版かとうの Kotlin 講座 こってり版
かとうの Kotlin 講座 こってり版
 
Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2
 
Introduction to Scala
Introduction to ScalaIntroduction to Scala
Introduction to Scala
 
Benefits of Kotlin
Benefits of KotlinBenefits of Kotlin
Benefits of Kotlin
 
Scala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 WorldScala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 World
 
SDC - Einführung in Scala
SDC - Einführung in ScalaSDC - Einführung in Scala
SDC - Einführung in Scala
 
Scala taxonomy
Scala taxonomyScala taxonomy
Scala taxonomy
 
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3
 
Kotlin
KotlinKotlin
Kotlin
 
Pooya Khaloo Presentation on IWMC 2015
Pooya Khaloo Presentation on IWMC 2015Pooya Khaloo Presentation on IWMC 2015
Pooya Khaloo Presentation on IWMC 2015
 
A swift introduction to Swift
A swift introduction to SwiftA swift introduction to Swift
A swift introduction to Swift
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
Swift 함수 커링 사용하기
Swift 함수 커링 사용하기Swift 함수 커링 사용하기
Swift 함수 커링 사용하기
 
Scala
ScalaScala
Scala
 
Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014
 
Scala introduction
Scala introductionScala introduction
Scala introduction
 
여자개발자모임터 6주년 개발 세미나 - Scala Language
여자개발자모임터 6주년 개발 세미나 - Scala Language여자개발자모임터 6주년 개발 세미나 - Scala Language
여자개발자모임터 6주년 개발 세미나 - Scala Language
 

More from intelliyole

Kotlin: Why Do You Care?
Kotlin: Why Do You Care?Kotlin: Why Do You Care?
Kotlin: Why Do You Care?
intelliyole
 
Feel of Kotlin (Berlin JUG 16 Apr 2015)
Feel of Kotlin (Berlin JUG 16 Apr 2015)Feel of Kotlin (Berlin JUG 16 Apr 2015)
Feel of Kotlin (Berlin JUG 16 Apr 2015)
intelliyole
 
From Renamer Plugin to Polyglot IDE
From Renamer Plugin to Polyglot IDEFrom Renamer Plugin to Polyglot IDE
From Renamer Plugin to Polyglot IDE
intelliyole
 
How to Build Developer Tools on Top of IntelliJ Platform
How to Build Developer Tools on Top of IntelliJ PlatformHow to Build Developer Tools on Top of IntelliJ Platform
How to Build Developer Tools on Top of IntelliJ Platform
intelliyole
 
The Kotlin Programming Language
The Kotlin Programming LanguageThe Kotlin Programming Language
The Kotlin Programming Languageintelliyole
 
IntelliJ IDEA: Life after Open Source
IntelliJ IDEA: Life after Open SourceIntelliJ IDEA: Life after Open Source
IntelliJ IDEA: Life after Open Source
intelliyole
 
Smoothing Your Java with DSLs
Smoothing Your Java with DSLsSmoothing Your Java with DSLs
Smoothing Your Java with DSLsintelliyole
 
Implementing Refactorings in IntelliJ IDEA
Implementing Refactorings in IntelliJ IDEAImplementing Refactorings in IntelliJ IDEA
Implementing Refactorings in IntelliJ IDEA
intelliyole
 
IntelliJ IDEA Architecture and Performance
IntelliJ IDEA Architecture and PerformanceIntelliJ IDEA Architecture and Performance
IntelliJ IDEA Architecture and Performance
intelliyole
 

More from intelliyole (9)

Kotlin: Why Do You Care?
Kotlin: Why Do You Care?Kotlin: Why Do You Care?
Kotlin: Why Do You Care?
 
Feel of Kotlin (Berlin JUG 16 Apr 2015)
Feel of Kotlin (Berlin JUG 16 Apr 2015)Feel of Kotlin (Berlin JUG 16 Apr 2015)
Feel of Kotlin (Berlin JUG 16 Apr 2015)
 
From Renamer Plugin to Polyglot IDE
From Renamer Plugin to Polyglot IDEFrom Renamer Plugin to Polyglot IDE
From Renamer Plugin to Polyglot IDE
 
How to Build Developer Tools on Top of IntelliJ Platform
How to Build Developer Tools on Top of IntelliJ PlatformHow to Build Developer Tools on Top of IntelliJ Platform
How to Build Developer Tools on Top of IntelliJ Platform
 
The Kotlin Programming Language
The Kotlin Programming LanguageThe Kotlin Programming Language
The Kotlin Programming Language
 
IntelliJ IDEA: Life after Open Source
IntelliJ IDEA: Life after Open SourceIntelliJ IDEA: Life after Open Source
IntelliJ IDEA: Life after Open Source
 
Smoothing Your Java with DSLs
Smoothing Your Java with DSLsSmoothing Your Java with DSLs
Smoothing Your Java with DSLs
 
Implementing Refactorings in IntelliJ IDEA
Implementing Refactorings in IntelliJ IDEAImplementing Refactorings in IntelliJ IDEA
Implementing Refactorings in IntelliJ IDEA
 
IntelliJ IDEA Architecture and Performance
IntelliJ IDEA Architecture and PerformanceIntelliJ IDEA Architecture and Performance
IntelliJ IDEA Architecture and Performance
 

Recently uploaded

Launch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in MinutesLaunch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in Minutes
Roshan Dwivedi
 
Vitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdfVitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
NYGGS Automation Suite
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
Adele Miller
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
Georgi Kodinov
 
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Globus
 
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
informapgpstrackings
 
Graphic Design Crash Course for beginners
Graphic Design Crash Course for beginnersGraphic Design Crash Course for beginners
Graphic Design Crash Course for beginners
e20449
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
Globus
 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
Paco van Beckhoven
 
GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
Neo4j
 
Pro Unity Game Development with C-sharp Book
Pro Unity Game Development with C-sharp BookPro Unity Game Development with C-sharp Book
Pro Unity Game Development with C-sharp Book
abdulrafaychaudhry
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
Philip Schwarz
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
Fermin Galan
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
Globus
 
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
Google
 
GlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote sessionGlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote session
Globus
 
Introduction to Pygame (Lecture 7 Python Game Development)
Introduction to Pygame (Lecture 7 Python Game Development)Introduction to Pygame (Lecture 7 Python Game Development)
Introduction to Pygame (Lecture 7 Python Game Development)
abdulrafaychaudhry
 
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptxText-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
ShamsuddeenMuhammadA
 
Top 7 Unique WhatsApp API Benefits | Saudi Arabia
Top 7 Unique WhatsApp API Benefits | Saudi ArabiaTop 7 Unique WhatsApp API Benefits | Saudi Arabia
Top 7 Unique WhatsApp API Benefits | Saudi Arabia
Yara Milbes
 

Recently uploaded (20)

Launch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in MinutesLaunch Your Streaming Platforms in Minutes
Launch Your Streaming Platforms in Minutes
 
Vitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdfVitthal Shirke Java Microservices Resume.pdf
Vitthal Shirke Java Microservices Resume.pdf
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
 
May Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdfMay Marketo Masterclass, London MUG May 22 2024.pdf
May Marketo Masterclass, London MUG May 22 2024.pdf
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
 
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
 
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
 
Graphic Design Crash Course for beginners
Graphic Design Crash Course for beginnersGraphic Design Crash Course for beginners
Graphic Design Crash Course for beginners
 
Enhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdfEnhancing Research Orchestration Capabilities at ORNL.pdf
Enhancing Research Orchestration Capabilities at ORNL.pdf
 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
 
GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
 
Pro Unity Game Development with C-sharp Book
Pro Unity Game Development with C-sharp BookPro Unity Game Development with C-sharp Book
Pro Unity Game Development with C-sharp Book
 
A Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of PassageA Sighting of filterA in Typelevel Rite of Passage
A Sighting of filterA in Typelevel Rite of Passage
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
 
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing SuiteAI Pilot Review: The World’s First Virtual Assistant Marketing Suite
AI Pilot Review: The World’s First Virtual Assistant Marketing Suite
 
GlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote sessionGlobusWorld 2024 Opening Keynote session
GlobusWorld 2024 Opening Keynote session
 
Introduction to Pygame (Lecture 7 Python Game Development)
Introduction to Pygame (Lecture 7 Python Game Development)Introduction to Pygame (Lecture 7 Python Game Development)
Introduction to Pygame (Lecture 7 Python Game Development)
 
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptxText-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
 
Top 7 Unique WhatsApp API Benefits | Saudi Arabia
Top 7 Unique WhatsApp API Benefits | Saudi ArabiaTop 7 Unique WhatsApp API Benefits | Saudi Arabia
Top 7 Unique WhatsApp API Benefits | Saudi Arabia
 

Idiomatic Kotlin

  • 1. Idiomatic Kotlin Dmitry Jemerov <yole@jetbrains.com>
  • 3. Use ‘when’ as expression body fun parseNum(number: String): Int? { when (number) { "one" -> return 1 "two" -> return 2 else -> return null } }
  • 4. Use ‘when’ as expression body fun parseNum(number: String): Int? { when (number) { "one" -> return 1 "two" -> return 2 else -> return null } } fun parseNum(number: String) = when (number) { "one" -> 1 "two" -> 2 else -> null }
  • 5. Use ‘try’ as expression body fun tryParse(number: String): Int? { try { return Integer.parseInt(number) } catch (e: NumberFormatException) { return null } }
  • 6. Use ‘try’ as expression body fun tryParse(number: String): Int? { try { return Integer.parseInt(number) } catch (e: NumberFormatException) { return null } } fun tryParse(number: String) = try { Integer.parseInt(number) } catch (e: NumberFormatException) { null }
  • 7. Use ‘try’ as expression fun tryParse(number: String): Int? { try { return Integer.parseInt(number) } catch (e: NumberFormatException) { return null } } fun tryParse(number: String): Int? { val n = try { Integer.parseInt(number) } catch (e: NumberFormatException) { null } println(n) return n }
  • 8. Use elvis with ‘return’ and ‘throw’ fun processPerson(person: Person) { val name = person.name if (name == null) throw IllegalArgumentException(
 "Named required") val age = person.age if (age == null) return println("$name: $age") } class Person(val name: String?, val age: Int?)
  • 9. Use elvis with ‘return’ and ‘throw’ fun processPerson(person: Person) { val name = person.name if (name == null) throw IllegalArgumentException(
 "Named required") val age = person.age if (age == null) return println("$name: $age") } fun processPerson(person: Person) { val name = person.name ?: throw IllegalArgumentException( "Name required") val age = person.age ?: return println("$name: $age") } class Person(val name: String?, val age: Int?)
  • 10. Use range checks instead of comparison pairs fun isLatinUppercase(c: Char) = c >= 'A' && c <= 'Z'
  • 11. Use range checks instead of comparison pairs fun isLatinUppercase(c: Char) = c >= 'A' && c <= 'Z' fun isLatinUppercase(c: Char) = c in 'A'..'Z'
  • 13. Don’t create classes just to put functions in class StringUtils { companion object { fun isPhoneNumber(s: String) = s.length == 7 && s.all { it.isDigit() } } }
  • 14. Don’t create classes just to put functions in class StringUtils { companion object { fun isPhoneNumber(s: String) = s.length == 7 && s.all { it.isDigit() } } } object StringUtils { fun isPhoneNumber(s: String) = s.length == 7 && s.all { it.isDigit() } }
  • 15. Don’t create classes just to put functions in class StringUtils { companion object { fun isPhoneNumber(s: String) = s.length == 7 && s.all { it.isDigit() } } } fun isPhoneNumber(s: String) = s.length == 7 && s.all { it.isDigit() } object StringUtils { fun isPhoneNumber(s: String) = s.length == 7 && s.all { it.isDigit() } }
  • 16. Use extension functions copiously fun isPhoneNumber(s: String) = s.length == 7 && s.all { it.isDigit() }
  • 17. Use extension functions copiously fun isPhoneNumber(s: String) = s.length == 7 && s.all { it.isDigit() } fun String.isPhoneNumber() = length == 7 && all { it.isDigit() }
  • 18. Avoid using member extension functions 
 (unless required for DSLs) class PhoneBook { fun String.isPhoneNumber() = length == 7 && all { it.isDigit() } }
  • 19. Avoid using member extension functions 
 (unless required for DSLs) class PhoneBook { fun String.isPhoneNumber() = length == 7 && all { it.isDigit() } } class PhoneBook { } private fun String.isPhoneNumber() = length == 7 && all { it.isDigit() }
  • 20. Don't use member extensions with 
 containing class as the receiver class PhoneBook { fun PhoneBook.find(name: String)= "1234567" }
  • 21. Don't use member extensions with 
 containing class as the receiver class PhoneBook { fun PhoneBook.find(name: String)= "1234567" } class PhoneBook { fun find(name: String) = "1234567" }
  • 22. Consider extracting non-essential API
 of classes into extensions class Person(val firstName: String, val lastName: String) { val fullName: String get() = "$firstName $lastName" }
  • 23. Consider extracting non-essential API
 of classes into extensions class Person(val firstName: String, val lastName: String) { val fullName: String get() = "$firstName $lastName" } class Person(val firstName: String, val lastName: String) val Person.fullName: String get() = "$firstName $lastName"
  • 24. Use default parameter values instead of overloads wherever possible class Phonebook { fun print() { print(",") } fun print(separator: String) { } } fun main(args: Array<String>) { Phonebook().print("|") }
  • 25. Use default parameter values instead of overloads wherever possible class Phonebook { fun print() { print(",") } fun print(separator: String) { } } fun main(args: Array<String>) { Phonebook().print("|") } class Phonebook { fun print(
 separator: String = ",") { } } fun main(args: Array<String>) { Phonebook().print( separator = "|") }
  • 26. Use ‘lateinit’ for properties that can’t be initialised in a constructor class MyTest { class State(val data: String) var state: State? = null @Before fun setup() { state = State("abc") } @Test fun foo() { Assert.assertEquals(
 "abc", state!!.data) } }
  • 27. Use ‘lateinit’ for properties that can’t be initialised in a constructor class MyTest { class State(val data: String) var state: State? = null @Before fun setup() { state = State("abc") } @Test fun foo() { Assert.assertEquals(
 "abc", state!!.data) } } class MyTest { class State(val data: String) lateinit var state: State @Before fun setup() { state = State("abc") } @Test fun foo() { Assert.assertEquals(
 "abc", state.data) } }
  • 28. Use type aliases for functional types and collections class EventDispatcher { fun addClickHandler(
 handler: (Event) -> Unit) { } fun removeClickHandler( handler: (Event) -> Unit) { } }
  • 29. Use type aliases for functional types and collections class EventDispatcher { fun addClickHandler(
 handler: (Event) -> Unit) { } fun removeClickHandler( handler: (Event) -> Unit) { } } typealias ClickHandler = (Event) -> Unit class EventDispatcher { fun addClickHandler( handler: ClickHandler) { } fun removeClickHandler( handler: ClickHandler) { } }
  • 30. Use type aliases for functional types and collections class EventDispatcher { fun addClickHandler(
 handler: (Event) -> Unit) { } fun removeClickHandler( handler: (Event) -> Unit) { } } typealias ClickHandler = (Event) -> Unit typealias HandlerMap = Map<EventType, List<Event>>
  • 31. Use data classes to return multiple values fun namedNum(): Pair<Int, String> = 1 to "one" fun main(args: Array<String>) { val pair = namedNum() val number = pair.first val name = pair.second }
  • 32. Use data classes to return multiple values fun namedNum(): Pair<Int, String> = 1 to "one" fun main(args: Array<String>) { val pair = namedNum() val number = pair.first val name = pair.second } data class NamedNumber( val number: Int, val name: String) fun namedNum() = NamedNumber(1, "one") fun main(args: Array<String>) { val (number, name) =
 namedNum() }
  • 33. Use destructuring in loops fun printMap(m: Map<String, String>) { for (e in m.entries) { println("${e.key} -> ${e.value}") } }
  • 34. Use destructuring in loops fun printMap(m: Map<String, String>) { for (e in m.entries) { println("${e.key} -> ${e.value}") } } fun printMap(m: Map<String, String>) { for ((key, value) in m) { println("$key -> $value") } }
  • 35. Use destructuring with lists fun splitNameExt(fn: String): NameExt { if ('.' in fn) { val parts = fn.split('.', limit = 2) return NameExt(parts[0], parts[1]) } return NameExt(fn, null) } data class NameExt(val name: String, val ext: String?)
  • 36. Use destructuring with lists fun splitNameExt(fn: String): NameExt { if ('.' in fn) { val parts = fn.split('.', limit = 2) return NameExt(parts[0], parts[1]) } return NameExt(fn, null) } fun splitNameExt(fn: String): NameExt { if ('.' in fn) { val (name, ext) = fn.split('.', limit = 2) return NameExt(name, ext) } return NameExt(fn, null) } data class NameExt(val name: String, val ext: String?)
  • 37. Use ‘copy’ method for data classes class Person(val name: String, var age: Int) fun happyBirthday(person: Person) { person.age++ }
  • 38. Use ‘copy’ method for data classes class Person(val name: String, var age: Int) fun happyBirthday(person: Person) { person.age++ } data class Person(val name: String, val age: Int) fun happyBirthday(person: Person) = person.copy( age = person.age + 1)
  • 40. Use ‘coerceIn’ to ensure a number is in range fun updateProgress(value: Int) { val newValue = when { value < 0 -> 0 value > 100 -> 100 else -> value } }
  • 41. Use ‘coerceIn’ to ensure a number is in range fun updateProgress(value: Int) { val newValue = when { value < 0 -> 0 value > 100 -> 100 else -> value } } fun updateProgress(value: Int) { val newValue = 
 value.coerceIn(0, 100) }
  • 42. Use ‘apply’ for object initialisation fun createLabel(): JLabel { val label = JLabel("Foo") label.foreground = Color.RED label.background = Color.BLUE return label }
  • 43. Use ‘apply’ for object initialisation fun createLabel(): JLabel { val label = JLabel("Foo") label.foreground = Color.RED label.background = Color.BLUE return label } fun createLabel() = JLabel("Foo").apply { foreground = Color.RED background = Color.BLUE }
  • 44. Use ‘filterIsInstance’ to filter a list by object type fun findStrings(objs: List<Any>) = objs.filter { it is String }
  • 45. Use ‘filterIsInstance’ to filter a list by object type fun findStrings(objs: List<Any>) = objs.filter { it is String } fun findStrings(objs: List<Any>) = obs.filterIsInstance<String>()
  • 46. Use ‘mapNotNull’ to apply a function and select items for which it returns a non-null value fun listErrors(
 results: List<Result>) = results .map { it.error } .filterNotNull() data class Result(val data: Any?, val error: String?)
  • 47. Use ‘mapNotNull’ to apply a function and select items for which it returns a non-null value fun listErrors(
 results: List<Result>) = results .map { it.error } .filterNotNull() fun listErrors( results: List<Result>) = results.mapNotNull { 
 it.error } data class Result(val data: Any?, val error: String?)
  • 48. Use ‘compareBy’ for multi-step comparisons fun sortPersons(persons: List<Person>) = persons.sortedWith( Comparator<Person> { p1, p2 -> val rc = p1.name.compareTo(p2.name) if (rc != 0) rc else p1.age - p2.age }) class Person(val name: String, val age: Int)
  • 49. Use ‘compareBy’ for multi-step comparisons fun sortPersons(persons: List<Person>) = persons.sortedWith( Comparator<Person> { p1, p2 -> val rc = p1.name.compareTo(p2.name) if (rc != 0) rc else p1.age - p2.age }) fun sortPersons(persons: List<Person>) = persons.sortedWith( compareBy(Person::name, Person::age)) class Person(val name: String, val age: Int)
  • 50. Use ‘groupBy’ to group items in a collection fun analyzeLog(log: List<Request>) { val map = mutableMapOf<String, MutableList<Request>>() for (request in log) { map.getOrPut(request.url) { mutableListOf() } .add(request) } } class Request(val url: String, val remoteIP: String, val timestamp: Long)
  • 51. Use ‘groupBy’ to group items in a collection fun analyzeLog(log: List<Request>) { val map = mutableMapOf<String, MutableList<Request>>() for (request in log) { map.getOrPut(request.url) { mutableListOf() } .add(request) } } fun analyzeLog(log: List<Request>) { val map = log.groupBy(Request::url) } class Request(val url: String, val remoteIP: String, val timestamp: Long)
  • 52. Use String methods for string parsing val pattern = Regex("(.+)/([^/]*)") fun splitPath(path: String): PathParts { val match = pattern.matchEntire(path) ?: return PathParts("", path) return PathParts(match.groupValues[1], match.groupValues[2]) } data class PathParts(val dir: String, val name: String)
  • 53. Use String methods for string parsing val pattern = Regex("(.+)/([^/]*)") fun splitPath(path: String): PathParts { val match = pattern.matchEntire(path) ?: return PathParts("", path) return PathParts(match.groupValues[1], match.groupValues[2]) } fun splitPath(path: String) = PathParts( path.substringBeforeLast('/', ""), path.substringAfterLast(‘/')) data class PathParts(val dir: String, val name: String)
  • 54.
  • 55.