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) }
pn
728x90

+ Recent posts