코틀린

    [Kotlin] Coroutine 동기화 처리

    멀티 스레드 처리는 애플리케이션의 퍼포먼스에 큰 이점을 주지만 경쟁 상태(race condition)를 적절히 조절해 주지 않는다면 데이터의 손실을 야기할 수 있다. - 경쟁 상태란 여러 개의 스레드가 하나의 공유/변경 가능한 자원에 접근하는 것을 말한다. 자세히 보기 데이터 손실을 막기 위해서는 동기화(synchronization)를 통해 race condition을 제어하여 올바른 멀티 스레드 환경을 구축해야 한다. 그러기 위한 여러 방법 중 하나로 Mutex를 고를 수 있다. Mutex Mutex는 공유자원에 변경이 일어나는 순간 적절한 block을 통해 race condition을 제어하는 동기화 제어 기법이다. 코드가 임계 구역에 있는 경우 절대로 동시성이 발생하지 않게 하고 오직 하나의 루틴만..

    [Kotlin] inline 함수

    코틀린 inline 코틀린에선 고차 함수를 사용할 수 있다. 함수를 인자 혹은 반환값으로 사용할 경우 내부적인 동작에서 무의미한 객체/함수를 생성하여 메모리를 낭비시키고 성능 저하를 일으킬 수 있다. 이러한 무의미한 행위를 줄이기 위해 inline 키워드가 제공되는데, 해당 키워드를 사용할 경우 고차 함수 내부의 코드가 그대로 복사되므로 위에서 말한 페널티를 줄일 수 있다. 원본 코드 fun main(){ val someText = foo("main"){ println("in") } } fun foo(value: String, doSomeThing: () -> Unit): String{ doSomeThing() return value + "foo()" } 인라인이 아닐경우 (Java 변환) public ..

    [Kotlin] Flow

    Flow란? 코틀린의 플로우는 순차적으로 값을 내보내고 정삭적으로 또는 예외로 완료되는 비동기적 데이터 스트림이다. map, filter, take, zip 등과 같은 flow의 중간 연산자는 업스트림 flow나 flow에 적용되어 추가 연산자를 적용할 수 있는 다운 스트림 flow를 반환하는 함수다. 위 중간 연산자는 flow에서 코드를 실행하지 않고 함수 자체를 일시 중단하지 않는다. 단지 향후 실행과 신속한 복귀를 위해 일련의 작업을 설정한다. 이를 cold flow라고 부른다. flow의 터미널 연산자는 collect, single, reduce, toList 등과 같은 일시 중단 함수이거나 지정된 스코프에서 flow 수집을 시작하는 launchIn 연산자이다. 이는 업스트림 flow에 적용되며 ..

    [Kotlin] 리스트를 통한 명령형 방식과 함수형 방식 비교

    코틀린의 리스트는 명령형 방식과 함수형 방식을 모두 제공한다. 함수형 방식으로 작성하는 경우 고차 함수를 체이닝 하면 명령형 프로그래밍에서 for와 if문을 사용해서 작성하는 로직을 간결하게 표현할 수 있다. 예를 들면 입력 리스트의 값을 제곱하여 10보다 작은 첫 번째 값을 리턴하는 함수를 명령형으로 작성해보자. fun imperativeWay(): Int { val bigIntList = (1..10000000).toList() var firstSquare = 0 for (value in bigIntList) { val doubleValue = value * value if (doubleValue < 10) { firstSquare = doubleValue break } } return firstSq..

    [Kotlin] 커링(Currying) 함수

    여러 개의 매개 변수를 받는 함수를 분리하여, 단일 매개 변수만 받는 부분 적용 함수의 체인으로 만드는 방법이다. 함수형 프로그래밍에서 커링을 사용하는 이유는 다양한 재사용과 마지막 매개변수가 입력될 때까지 함수의 실행 타이밍을 조절할 수 있다. 아래 코드는 코틀린의 확장함수를 사용하여 multiThree 함수와 같이 매개변수가 3개인 커링 함수를 일반화 하는 과정이다. curried() 확장 함수를 사용하여 매개변수가 3개인 함수를 커링 함수로 변환할 수 있다. 반대로 커링 함수를 일반 함수로 변환하는 unCurried() 함수도 구현했다. class Currying { fun ((P1, P2, P3) -> R).curried(): (P1) -> (P2) -> (P3) -> R = { p1: P1 ->..

    [Kotlin] Tailrec

    Tailrec? Tailrec은 언어 차원에서 제공하는 기능으로 해당 키워드가 명시된 함수가 꼬리 재귀의 조건에 부합하지 않으면 IDE에서 경고 메시지를 주고, 컴파일러 최적화가 발생하지 않는다. 꼬리 재귀란? 꼬리 재귀란 어떤 함수가 직간접적으로 자기 자신을 호출하면서도 그 호출이 마지막 연산인 경우를 뜻한다. 그리고 이 마지막 연산인 호출을 '꼬리 호출'이라 한다. 여기서 주의할 점은 마지막 호출에서 재귀 함수만 호출되어야 한다는 것이다. 일반적으로 재귀 호출이 반복되면서 깊이가 깊어지면 스택 오버플로우가 발생할 수 있는데, 꼬리 호출일 때는 스택 오버플로우가 발생하지 않는다. 왜냐하면 컴파일러가 해당 문제를 일으키는 스택 프레임을 재사용하기 때문이다. 이 경우 재귀를 사용했지만, 반복문을 사용한 것..