
기트허브 코드 링크!(Github code link)

05-01 람다 함수와 고차 함수
람다 함수
- 람다 함수는 익명 함수(anonymous function) 정의 기법이다
- 주로 함수를 간단하게 정의할 때 이용
▪ 코틀린으로 프로그램 작성하면 많이 사용한다
▪ 그 이유는 코트린은 고차 함수 지원
람다 함수 선언과 호출
- 일반 함수는 fun 을 이용하지만 람다는 fun 키워드 이용하지않고 함수 이름도 없다
- 람다는 중괄호 { } 로 표현한다
▪ 일반적 형식: fun 함수명 (매개변수명 : 타입): 반환타입{…..}
▪ 람다 형식: {매개변수 -> 함수 본문}
- 람다 함수 규칙:
▪ 람다는 중괄호 { } 로 표현한다
▪ { } 안에 화살표(->) 가 있으며 화살표 왼쪽은 매개변수, 오른쪽은 함수 본문이다
▪ 함수의 반환값은 함수 본문의 마지막 표현식이다
- 비교:
fun sum(no1: Int, no2: Int):Int{
return no1 + no2
}
와
//요거는 같은거라
val sum = {no1: Int, no2: Int ->no1+no2}
- 람다는 함수는 이름이 없으므로 함수명으로 호출 불가능
- 만약 대입 위에 있는 예제처럼 sum으로 대입해서 하면 sum(10,20) 이런 방법으로 호출 가능
- 그래도 람다 함수 선언하자마자 호출하고 싶으면 람다 함수뒤에다가 호출하면 된다
- Ex: val sum = {no1: Int, no2: Int ->no1+no2}(10,20)
매개변수 없는 람다 함수
- 함수에 항상 매개변수가 있어야 하는 것은 아님
- 예시)
//매개변수 없는 람다 함수
{-> println("function call")}
- 화살표도 생략가능
매개변수가 1개인 람다 함수
- 매개변수가 1개일 때는 매개변수를 선언하지 않아도 함수로 전달된 값으로 이용 가능
예시1) 매개변수가 1개인 람다함수
val some = {no: Int -> println(no)}
some(10)
//=>10
예시2)매개변수 1개인 람다 함수 it 키워드 사용 (더욱 간력하게 표현하기)
val some: (Int) -> Unit = { println(it)}
some(10)
- (Int) -> Unit 이 매개변수가 1개인 람다 함수임을 알려 준다
- 매개변수가 1개일 때는 중괄화 안에서 매개변수 선언을 생략하고 println(it) 처럼 it 키워드로 매개변수를 이용 가능
-
람다 함수의 반환
- 람다 함수에서는 return 문을 사용할 수 없다
- 람다 함수의 반환값은 본분에서 마지막 줄의 실행 결과이다
예시)
//람다 함수의 반환문
fun main() {
val some2 = {no1: Int, no2: Int ->
println("lambda function")
no1*no2 //lambda function return value (반환값)
}
println("result: ${some2(10,20)}")
}
결과:
lambda function
result: 200
함수 타입과 고차 함수
함수 타입 선언
- 함수 타입이란 함수를 선언할 때 나타내는 매개변수와 반환 타입을 의미
//일반 함수
fun something(no1: Int, no2: Int):Int{
return no1 + no2
}
- 노란색으로 하이라트 한걸 (Int, Int) ->Int 로 표현 가능
▪ 물런 그렇게하면 그에 맞는 함수를 대입해야한다
예시)
//함수 타입을 이용해 함수를 변수에 대입
val something:(Int,Int) ->Int = {no1: Int, no2: Int ->no1+no2}
타입 별칭 -typealias
- typealias는 타입의 별칭을 선언하는 키워드
▪ 함수 타입뿐만 아니라 데이터 타입도 가능
예시)
//타입 별칭 typealias 예시!
typealias MyInt = Int
typealias MyFuncType = (Int, Int) -> Boolean
fun main() {
//타입 별칭 typealias 예시!
val somesortOfData1: Int = 10
val somesortOfData2: MyInt = 10
val someFun: MyFuncType = {no1: Int, no2: Int ->
no1>no2
}
println(someFun(10,20))
println(someFun(50,20))
}
매개변수 타입 생략
- 람다 함수 하면서 만약 매개변수의 타입을 유추할 수 있다면 타입 선언을 생략할 수 있다
예)
typealias MyFuncType = (Int, Int) -> Boolean
val someFun: MyFuncType = {no1: Int, no2: Int ->
no1>no2
}
을….
typealias MyFuncType = (Int, Int) -> Boolean
val someFun: MyFuncType = {no1, no2 ->
no1>no2
}
로 할수 있다!
- 보통은 오류가 나지만 이 겨우가 되는 이유는…..:
▪ 위 예시 같은 경우에는 MyFuncType이 Int 타입의 매개변수를 2개 받고 있어서 실제 함수를 선언할 때 군이 타입 명시 불필요 (이미 Int임을 알 수 있기 때문에)
예시2) typealias가 아닐때
//매겨변수 타입 선언 생략 예 (without typealias)
val someFun2:(Int,Int) -> Boolean = {no1,no2 ->
no1>no2
}
예시3)
//변수 선언 시 타입 생략
val someFun3 = {no1:Int,no2:Int ->
no1>no2
}
- someFun3 변수에 대입한 함수를 보면 타입 유추가 가능해서 생략 가능
고차 함수
- 고차 함수(high order function)란 함수를 매개변수로 전달받거나 함수를 의미한다
▪ 일반적으로 함수의 매개변수나 반환값은 데이터이지만….
▪ 데이터가 아닌 함수를 매개변수나 반환값을 이용하는 함수를 고차 함수
고차 함수 예시)
//고차 함수 예시
fun hofFunc(arg: (Int)-> Boolean): ()->String{
val result = if(arg(10)){
"valid"
}else{
"invalid"
}
return {"hofFunc result: $result"}
}
fun main() {
val result = hofFunc({no->no >0}) //'no' has parameter Int
println(result())
}
05-02 널 안전성
널 안전성이란?
- 기본 지식Null):
▪ 널(null)이란 객체가 선언되었지만 초기화되지 않은 상테
▪ 널은 객체가 주소를 가지지 못한 상태를 의미
▪ 널인 상태의 객체를 이용하면 널 포인트 예외(NullPointException) 에러가 발생한다
- 널 오류를 발생하지 않게 작성하는게 개발자가 코드를 만들때 중요하다
- 코틀린에서 개발자들을 위래서 코틀인이 제공하는 널 안정성 연산자가 있다
널 안전성 연산자
- Null은 nullable과 not null로 구분한다
- 만약 null을 그냥 대입하면 오류가 뜨지만 타입 뒤에 ? 연산자를 추가하면 널 허용변수 되어 null 대입 가능
예시)
//널 안전성 호출 -?.연산자
//널 포인터 예외 오류
/
var data: String? ="Stefano!" //?은 널 허용
var lenght = data.length //error! (data는 널 허용이지만 lenght는 아니라서)
/
var data: String? ="Stefano!" //?은 널 허용
var lenght = data?.length //성공!
엘비스 -?.연산자
- 엘비스 연산자란 ?: 기호를 말한다
- 어떤 경우에는 null을 대입해야하는 경우도 있을때 이때 엘비스 연산자를 사용한다
예시)
fun main() {
//엘비스 연산자 사용
var data1: String? = "stefbang"
println("data = $data1 : ${data1?.length}")
println("data = $data1 : ${data1?.length?:-1}")
data1 = null
println("data = $data1 : ${data1?.length?:-1}")
}
=> Result:
data = stefbang : 8
data = stefbang : 8
data = null : -1
예외 발생 -!! 연산자
- !! 는 객체가 널일 때 예외(exception)를 일으키는 연산자이다
▪ 가끔식 예외를 발생시켜야 할 때도 있다
예시)
fun errorCause(data: String?): Int{
return data!!.length
}
fun main() {
//예외 발생 연산자
println(errorCause("8Letters"))
println(errorCause(null))
}
=> result:
8
Exception in thread "main" java.lang.NullPointerException
- 'errorCause' 함수에 문자열을 전달하면 문제 없이 작동되지만 null을 전잘하면 data!!.length 크드로 예외 메시지가 출력된다