728x90
강의 링크 : https://www.edwith.org/boostcourse-mo-kotlin-basic1/joinLectures/28611
함수 선언과 호출
fun sum(a:Int, b:Int): Int{
var sum = a+b
return sum
}
- fun 키워드로 함수 선언
- 매개변수 (이름 : type) 선언
- 함수의 반환 타입 결정 (fun _ : type)
- 반환 필요 시 return
- 함수의 간략화된 선언 - 바로 return하는 경우
fun sum(a:Int, b:Int) : Int = a+b
//매개변수를 통해 return 추론이 가능한 경우 return 자료형도 생략 가능
fun sum(a:Int, b:Int) = a+b
- 매개변수의 기본값 : 인자가 전달되지 않을 때 기본으로 사용할 값 설정 가능
fun email(ID : String, domain : String = "naver.com")
{
println("your email is ${ID}@${domain}")
}
fun main(){
email("Kildong") //your email is Kildong@naver.com
email("Kildong", "Gmail.com") //your email is Kildong@Gmail.com
}
- 반환값이 없는 함수 : Unit return
fun out(name : String) : Unit
{
println("name : ${name}")
return Unit
//return Unit은 아무것도 반환하지 않음(생략 가능)
}
fun outp(name : String) : Unit = println("name : ${name}") //위 함수와 동일하게 동작
- 함수 매개변수 지정
- 기본값이 있는 매개변수의 경우 지정하여 대입 가능
fun sum(a : Int = 1, b : Int = 2) = a+b
fun main()
{
println("1+2 = ${sum()}") //1+2 = 3
println("1+4 = ${sum(b = 4)}") //1+4 = 5
println("3+2 = ${sum(a = 3)}") //3+2 = 5
}
- 가변인자 : vararg 키워드로 여러 개의 인수를 받을 수 있음
- for문을 이용하여 함수에서 처리 가능
fun varprint(vararg a : Int)
{
for (n in a)
{
println("number is ${n}")
}
println("===========================")
}
fun main()
{
varprint(1)
varprint(1,2)
varprint(1,2,3,4,5,6,7,8,9)
}
/*출력결과
number is 1
===========================
number is 1
number is 2
===========================
number is 1
number is 2
number is 3
number is 4
number is 5
number is 6
number is 7
number is 8
number is 9
===========================
*/
함수형 프로그래밍 패러다임 (1)
- 코틀린은 멀티 패러다임 언어 : 함수형 / 객체지향
- 함수형 프로그래밍
- 단순한 코드 지향
- 코드의 테스트나 재사용성 증가
- 람다식, 고차함수 활용 : 함수의 인자에 함수를 대입 가능
- 순수 함수 제공
- 순수 함수
- 부작용이 없는 함수 : 동일 입력 - 동일 출력
- 값의 예측이 가능
- 함수 외부의 상태를 바꾸지 않음 : 함수에 없는 외부 객체가 사용되는 경우(함수 리턴값을 대입하는 등)
- 람다식, 고차함수 사용을 위해 필요한 개념
- 입력 - 내용을 분리하여 재사용성이 높음
- 병행 작업 시 안전
- 테스트, 디버깅 시 유리
- 람다식
- 익명 함수의 일종으로 이름 선언 없이 사용 가능
{x, y -> x+y}
- 고차 함수에 인자로 넘기거나 결과값으로 사용할 수 있음
- 일급 객체(First Class Citizen)
- 함수의 인자, 반환값으로 쓰일 수 있음
- 변수에 대입할 수 있음
- 코틀린의 함수는 일급 객체로 다룸
- 고차 함수
- 함수 인자가 함수가 되는 것
fun highFunc(sum : (Int, Int) -> Int, a : Int, b : Int) : Int
{
//첫 번째 매개변수 : sum이라는 람다식 변수는 Int 2개를 받아 Int를 반환
return sum(a, b)
}
fun main()
{
println(highFunc({x, y -> x + y}, 10, 20))
}
함수형 프로그래밍 패러다임 (2)
- 고차함수의 호출 방법 : 값에 의한 호출, 이름에 의한 호출, 참조에 의한 호출
- 값에 의한 호출 : 함수 인자는 값으로 처리되어 수행된 값을 전달
fun main() {
val result = callByValue(lambda()) // 람다식 함수를 호출
println(result)
}
fun callByValue(b: Boolean): Boolean { // 일반 변수 자료형으로 선언된 매개변수
println("callByValue function")
return b
}
val lambda: () -> Boolean = { // 람다 표현식이 두 줄이다
println("lambda function")
true // 마지막 표현식 문장의 결과가 반환
}
- 이름에 의한 호출 : 함수 이름을 매개변수로 전달하여, 함수가 사용될 때 실행
fun main() {
val result = callByName(otherLambda) // 람다식 이름으로 호출
println(result)
}
fun callByName(b: () -> Boolean): Boolean { // 람다식 함수 자료형으로 선언된 매개변수
println("callByName function")
return b()
}
val otherLambda: () -> Boolean = {
println("otherLambda function")
true
}
- 참조에 의한 호출 : 콜론 기호(::)를 이용한 호출
fun main() {
// 1. 인자와 반환값이 있는 함수
val res1 = funcParam(3, 2, ::sum)
println(res1)
// 2. 인자가 없는 함수
hello(::text) // 반환값이 없음
// 3. 일반 변수에 값처럼 할당
val likeLambda = ::sum
println(likeLambda(6,6))
}
fun sum(a: Int, b: Int) = a + b
fun text(a: String, b: String) = "Hi! $a $b"
fun funcParam(a: Int, b: Int, c: (Int, Int) -> Int): Int {
return c(a, b)
}
fun hello(body: (String, String) -> String): Unit {
println(body("Hello", "World"))
}
익명함수, 인라인 함수
- 익명 함수 : 이름이 없는 함수
- 람다식 함수를 위한 임시 함수로 사용
- 람다식에서 쓰기 어려운 return, break continue 등을 사용하기 위함
fun (x:Int, y:Int) : Int = x+y
val add : (Int, Int) -> Int = fun(x,y) = x+y
val add = fun(x : Int, y:Int) = x+y // 람다식과 유사한 형태
- 인라인 함수 : 함수가 호출되는 곳에 함수 내용을 복사
- 함수 호출 시 코드가 분기하는데, 이 부분이 없어지므로 성능이 증가
- 과도한 호출 시 main 함수 자체의 크기가 커질 수 있음
inline fun foo(...)
{
...
}
fun main(){
foo() // foo 내용이 복사
}
인라인 함수의 제한
- 코드가 복사되므로 내용이 많은 인라인 함수는 파일 크기를 증가시킬 수 있음
- noinline : 람다식 함수는 인라인 되지 않도록 할 수 있음
inline fun foo(bar1 : () -> Unit, noinline bar2 : () -> Unit)
{
... //bar1 람다식은 인라인 복사되지만, bar2는 인라인 x
}
- 확장 함수
- 클래스의 멤버 함수를 외부에서 추가할 수 있음
- 동일한 멤버나 메소드 존재 시 기존의 함수가 우선하여 호출됨
중위 함수, 재귀 함수
- 중위 함수
- 클래스 멤버 호출 시 점을 생략하고, 함수 이름 뒤의 소괄호를 생략
- 조건
- 멤버의 메소드 혹은 확장 함수
- 매개변수가 존재
- infix 키워드로 정의
infix fun Int.multiply(x:Int) : Int
{
return this * x
}
fun main
{
// 기존 표현법 : val multi = 3.multiply(10)
val multi = 3 multiply 10 // 30
}
- 재귀 함수
- 자기 자신을 다시 호출
- 필수 조건
- 탈출 조건을 만들어야 함(무한루프 방지)
- 호출 회수에 제한(함수 호출은 스택을 이용하므로)
- 꼬리 재쉬 함수
- 함수 분기 없이 재귀 호출 시 함수 영역을덮어씌우면서 호출 (스택 영역을 사용하지 않음)
- 무한히 호출하더라도 stack overflow가 없음
- tailrec 키워드로 선언
// 팩토리얼 함수
fun factorial(n:Int): Long
{
return if(n == 1) n.toLong() else n*factorial(n-1)
}
//꼬리재귀 팩토리얼
tailrec fun factorial(n : Int, run : Int = 1) : Long
{
return if(n ==1) run.toLong() else factorial(n-1, run * n)
}
pn728x90