보초의 코딩일기장

코틀린을 이용한 안드로이드 프로그래밍 실습 -3 본문

Android/Kotlin

코틀린을 이용한 안드로이드 프로그래밍 실습 -3

장보비 2018. 7. 4. 10:29

코틀린 함수형 프로그래밍


● 1급객체

- 변수나 데이터에 할당 가능

- 인자로 사용 가능

- 리턴 값으로 사용 가능

-1급객체로 다루기 위해선 함수타입이 존재해야함

  (paramType1, ...)-> returnType

  typealias mytype = (Int, Int) ->Int

EX)

fun add(a:Int, b:Int):Int{} 를 var f:(Int,Int) ->Int= add 로 변경할 수 있음

복잡한 시그니쳐 함수를 간단하게 만들 수 있음


● 고차함수

- 함수가 1급객체이면 고차함수를 쓸 수 있음.

- 함수를 인자로 받거나 함수를 리턴하는 함수


● 람다

- 이름없는 함수를 표현식으로 기술한 것

- { p1:type, p2:type -> statement1; statement2 }  로 쓴다.

- 리턴값을 return하지 않고, 마지막 표현식의 값이 리턴됨

- 표현식에서 생략 가능한 것은 생략 가능

타입을 유추할 수 있고, 파라메터가 한개면 생략가능 ( 하나면 it으로 대체)

파라메터가 하나 또는 없고 문장만 쓰여져 있으면 람다일 확률이 높다.

- 클로저를 생성한다.

- 실질적으로는 내부의 별개의 익명 클래스로 생성되고 그 클래스의 invoke함수 (코틀린에서의 ()연산자) 가 만들어져서 함수의 바디 안으로 들어가게 된다.

- 바디의 순서가 중요하다


● 클로저

- 람다식이나 익명함수의 경우 함수외부 범위에서 선언 된 변수에 접근할 수 있음.

- 자바는 final만 접근 가능하지만 코틀린에서는 전부 접근 가능하다


● it

- 단일 매개 변수의 암시적 이름

● _

- 사용되지 않는 변수

● Inline

- 고차함수를 이용할 때 런타임

- 특정함수 파라메터를 inline 시키지 않으려면 파라메터 앞에 noinline 키워드 사용

- inline이 되면 람다에서 return을 사용 가능


● SAM (Single Abstract Method) 변환

- 추상 메소드가 하나만 있는 인터페이스를 파라메터로 받을 때 람다로 표현할 수 있게 변환

- 선언부(interface, setOnClickListener)가 자바에 있고, 코틀린에서 setOnClickListener을 호출했을 때만 SAM변환이 동작한다

- 코틀린에서 선언부가 있을 때는 객체 표현 표현식으로 처리해야한다.


● Stream or Sequence

- filter : 각 조건에 맞는 요소만 뽑아 리스트로 만든다. 

  map : 각 요소를 변환시켜 새로운 타입의 리스트로 바꿔주는 함수 (변환은 람다로 받음)

          reduce , all , any , count , find , flatMap

- 연속해서 사용할 때 분리되어 실행됨.

- Stream을 만들어 연속 실행하면 연속되어 실행.

  Stream : 분리된 결과 값을 한번에 리턴하도록 만들어 준다. (연속적으로 실행되게끔)

  filter, map 등은 람다를 가지고있을 뿐이고 foreach (종단함수) 가 호출 되었을 때 가지고 있었던 람다를 출력시킨다.

- 종단함수를 두번 이상 사용하게 되면 런타임오류가 발생한다.

- 인라인되지 않는다.


● Standard function

1. run 

- 인자가 없고 리턴은 있는 확장 멤버함수 람다를 인자로 받음

- 람다가 리턴하는 값을 리턴함

- 제너릭으로 모든 타입에 대해 확장함수로 구현

public inline fun <T,R> T.run(f: T.() -> R): R = f()

- 인라인 함수이므로 고차함수, 함수 표현식을 받을 것이 인라인

   T타입의 run, T타입을 확장시킨 것이다. 리턴타입은 R

   T.() 란? T에 속하는 파라메터를 받는다. f()가 T의 멤버함수를 쓸 수 있다. (즉 this) 


val user = User("importre").run {
   
email = "importre@example.com"
   
profile = "http://path/to"
   
this
}

# User타입의 멤버함수를 파라메터로 받음 (T와 R은 전부 User)

   User(this) 를 리턴한다. 


2. let

- 인자가 자기자신 타입 한 개를 넘기고 리턴이 있는 람다를 인자로 받음

- 람다가 리턴하는 타입을 리턴함

- 람다를 this인자로 실행하여 결과를 리턴함

public inline fun <T,R> T.let(f: (T) -> R) : R = f(this)

- Safe call로 if 검사 대신 많이 쓰임 obj>?.let()


3. apply

- 인자가 없고 리턴도 없는 확장 멤버함수 람다를 인자로 받음

- 자신의 타입을 리턴함

public inline fun <T> T.apply(f: T.() -> Unit): T { f(); return this }


Buy me a coffeeBuy me a coffee
Comments