Skip to content

Instantly share code, notes, and snippets.

@kittinunf
Last active July 11, 2024 05:58
Show Gist options
  • Save kittinunf/e5fc92f6ae475f5d413dded926ecfdfa to your computer and use it in GitHub Desktop.
Save kittinunf/e5fc92f6ae475f5d413dded926ecfdfa to your computer and use it in GitHub Desktop.
Kotlin2.0 and Beyond
package com.github.kittinunf.kotlin2_0
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
fun example1() {
// 1.
/**
* 1. Better operator and understanding code
*
*/
data class Foo(val mutableList: MutableList<Long> = mutableListOf(1, 2))
val f = Foo()
f.mutableList[0] += 1
var i: Long = 0
i += 1
// --
println(f.mutableList)
}
fun example2() {
// 2.
/**
* 2. Smart-casts from variables, this goes beyond the scope
*
*/
class Cat {
fun meow() {
println("Meow meow")
}
}
fun pet(animal: Any) {
if (animal is Cat) {
animal.meow()
}
val anotherCat = animal is Cat
if (anotherCat) {
anotherCat.meow()
}
}
//--
data class Card(val value: String?)
fun getCardValue(card: Any): String {
val cardWithValue = card is Card && card.value.isNullOrEmpty().not()
return when {
cardWithValue -> {
card.value
}
else -> "no value"
}
}
println(getCardValue(Card("value")))
// --
fun workWithStatus(status: Any) {
if (status is HttpStatus.OK || status is HttpStatus.Error) {
println(status.message())
}
}
}
sealed interface HttpStatus {
fun message(): String
interface OK : HttpStatus
interface Error : HttpStatus
interface Custom : HttpStatus
}
fun example3() {
// 3.
/**
* 3. Data flow and guarded condition
*
*/
fun getType(): Data.Type {
error("....")
}
fun doSomethingWithSearchData(
data: Sequence<Data>,
id: String
) {
val lastData = data.last { it.id == id }
when (val type = getType()) {
Data.Type.A if type.allow
-> {
// Do something with A and if it is allowed only
}
Data.Type.B -> {}
Data.Type.C -> {}
}
}
fun doSomethingBetterWithSearchData(
data: Sequence<Data>,
id: String
) {
val lastData = data.last { it.id == id }
when (val type = getType()) {
is A if type.allowed
-> {
// Do something with A and if it is allowed only
}
B -> {}
C -> {}
}
}
}
interface Data {
enum class Type {
A {
val allowed: Boolean = true
},
B {
},
C {
}
;
}
val id: String
}
fun example4() {
// 4.
/**
* 4. ADT Style smart casts
*
*/
fun <T> unwrapped(container: Container<T>): T = container.inner
fun <T> unwrappedAndDoSomething(container: Container<T>): T = when (container) {
is IntegerContainer -> container.inner
is StringContainer -> container.inner
}
}
sealed class Container<T>(val inner: T)
class IntegerContainer : Container<Int>(42)
class StringContainer : Container<String>("Kotlin")
fun example5() {
// 5.
/**
* 5. Data classes improvement
*
*/
data class User(val name: String, val surname: String)
fun doSomething(u: User) {
val (surname, name) = u
}
}
fun example6() {
// 6.
/**
* 6. Dataargs
*
*/
fun LazyColumn(
modifier: Modifier = Modifier,
state: LazyListState = rememberLazyListState(),
contentPadding: PaddingValues = PaddingValues(0),
reverseLayout: Boolean = false,
verticalArrangement: Arrangement.Vertical =
if (reverseLayout) Arrangement.Top else Arrangement.Bottom,
horizontalAlignment: Alignment.Horizontal = Alignment.Start,
userScrollEnabled: Boolean = true,
flingBehavior: FlingBehavior,
content: LazyListScope.() -> Unit
) {
// Implementation
}
dataarg class ColumnSettings(
val contentPadding: PaddingValues = PaddingValues(0),
val reverseLayout: Boolean = false,
val verticalArrangement: Arrangement.Vertical =
if (reverseLayout) Arrangement.Top else Arrangement.Bottom,
val horizontalAlignment: Alignment.Horizontal = Alignment.Start,
val userScrollEnabled: Boolean = true,
)
fun LazyColumn(
modifier: Modifier = Modifier,
state: LazyListState = rememberLazyListState(),
dataarg args: ColumnSettings,
flingBehavior: FlingBehavior,
content: LazyListScope.() -> Unit
) {
// Implementation
}
LazyColumn(reverseLayout = true) {
}
}
object Modifier
interface LazyListState
fun rememberLazyListState(): LazyListState {}
interface PaddingValues
fun PaddingValues(i: Int): PaddingValues {}
interface Arrangement {
object Top : Arrangement.Vertical
object Bottom : Arrangement.Vertical
interface Vertical : Arrangement
}
interface Alignment {
object Start : Horizontal
interface Horizontal : Alignment
}
interface FlingBehavior
interface LazyListScope
fun example7() {
// 7.
/**
* 7. Built-in Error Abstract type
*
*/
fun <T> Sequence<T>.last(predicate: (T) -> Boolean): T? {
var result: T? = null
for (element in this) {
if (predicate(element)) result = element
}
return result ?: throw NoSuchElementException()
}
// right??
// now with { it == null }
fun <T> Sequence<T>.lastImproved(predicate: (T) -> Boolean): T? {
var result: T? = null
var found: Boolean = false
for (element in this) {
if (predicate(element)) {
result = element
found = true
}
}
if (!found) throw NoSuchElementException()
return result as T
}
fun <T> Sequence<T>.lastImprovedFinal(predicate: (T) -> Boolean): T? {
var result: Any? = NotFound
for (element in this) {
if (predicate(element)) {
result = element
}
}
if (result == NotFound) throw NoSuchElementException()
return result as T
}
sealed class Value {
data class Success(value: String) : Value
object Failure : Value
}
fun <T> Sequence<T>.lastImprovedFinalFinal(predicate: (T) -> Boolean): T? {
var result: (T | NotFound) = NotFound
for (element in this) {
if (predicate(element)) {
result = element
}
}
if (result == NotFound) throw NoSuchElementException()
return result
}
}
private object NotFound
interface Value
fun example8() {
// 8.
/**
* 8. Explicit backing fields
*
*/
class Repository() {
private val _values = MutableSharedFlow<Value>()
val values: Flow<Value> get() = _values
} {
fun something() {
_values.emit(t) = ....
}
}
val r = Repository()
r.values.collect {
}
class RepositoryImproved() {
val values: Flow<Value>
field = MutableSharedFlow<Value>
}
}
fun main() {
example1()
example2()
example3()
example4()
example5()
example6()
example7()
example8()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment