23.06.15
DEVOTEE를 활성화 시키면
지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.
버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.
| 컨텐츠 유형 | 제목 | 저장일 | 삭제 |
|---|
본인인증 로그인에 실패하였습니다.
회원이 아니시거나 본인인증 등록이
완료되지 않은 사용자입니다.
프로그래밍의 기본이 순차, 조건, 반복이다.
이제 생각한대로 프로그램을 작성할 수 있으나, 매번 동일한 코드를 작성하는 것은 프로그램의 운영/유지보수를 어렵게 한다.
특정 아규먼트만 다르고, 하는일이 동일하다면 함수(Function) 을 작성하여 재사용성을 높인다면 프로그램의 운영/유지보수가 편할 것이다.
kotlin에서 function 기본 문법은 다음과 같다.
fun fun_name(a: data_type, b: data_type, ......): return_type {
// 프로그램 영역
return
}fun
함수의 시작은 fun 키워드로 시작한다. fun으로 시작하고 { } 로 끝이 나는 부분까지 함수라는 것을 가리킨다.
fun_name
함수의 이름이다. 함수는 가급적 1가지 일만 하도록 작성하는 것이 좋다. 그럴때 함수가 무엇을 하는지 대표하는 이름을 작성하자.
(a: data_type, b: data_type, ...)
함수에 전달될 아규먼트목록을 나열한다. 매개변수 (a, b 등) 과 이 매개변수가 어떠한 자료형을 갖는지 data_type으로 작성한다.
: return_type
반환되는 자료형을 나타낸다.
return
반환해야할 값이 있다면 return <반환값> 형태로 작성한다.
다음은 단순한 문자열을 출력하는 함수이다.
입력 아규먼트와 반환값도 없는 매우 단순한 함수이다.
fun printStory() {
println("""
Consectetur nisi dolore est quis est elit nulla irure irure. Id occaecat eu consequat consequat nisi adipisicing magna est amet eu laborum laborum magna. Tempor deserunt labore eu fugiat incididunt minim labore amet ut labore. Occaecat in magna aliquip ullamco dolor commodo ipsum nulla laboris. Quis do cupidatat eiusmod culpa nulla ut mollit laboris in.
Anim fugiat laborum aliqua minim occaecat. Magna laborum culpa adipisicing culpa. Ea deserunt labore proident ad deserunt. Labore esse pariatur adipisicing excepteur aliqua elit quis pariatur sunt ea officia fugiat. Proident mollit in minim ea commodo excepteur enim do exercitation proident magna. Pariatur dolor tempor non deserunt eu in. Commodo cillum tempor labore enim ea magna ea eiusmod irure minim velit id incididunt.
"""
)
}
fun main(args: Array<String>) {
printStory()
}함수 호출은 '함수이름()' 의 형태로 작성하면 된다.
다음은 사칙연산을 수행하는 함수를 작성해보자.
2개의 정수를 입력받고, 연산자에 따라 사칙연산 결과를 반환하는 함수이다.
fun calculator(a: Int, b: Int, op: String): Int {
when(op.lowercase()) {
"sum" -> return (a + b)
"sub" -> return (a - b)
"mul" -> return (a * b)
"div" -> return (a / b)
else -> return -999
}
}
fun main(args: Array<String>) {
println("SUM: %d".format(calculator(10, 5, "SUM")))
println("SUB: %d".format(calculator(10, 5, "SUB")))
println("MUL: %d".format(calculator(10, 5, "MUL")))
println("DIV: %d".format(calculator(10, 5, "DIV")))
println("ELSE: %d".format(calculator(10, 5, "?")))
}위 함수는 값 a, b 를 입력받고, 연산자 op 를 입력받아 op에 따라 사칙연산을 수행한 결과를 반환하는 함수이다.
각 사칙연산에 따라 결과를 계산한 후 return 으로 값을 반환하고 있다.
SUM: 15
SUB: 5
MUL: 50
DIV: 2
ELSE: -999반환값이 없는경우 kotlin은 Unit 이라는 타입으로 반환한다.
fun nonReturnValue(name: String, age: Int): Unit {
println("My name is ${name}. I'm ${age} years old.")
}
fun main(args: Array<String>) {
nonReturnValue("UNCLE", 40)
}My name is UNCLE. I'm 40 years old.위와 같이 Unit 을 이용하면 반환값이 없는 확인할 수 있다.
아규먼트를 어떠한 값이든 받으려면 Any 타입을 사용하자.
Java에서 Object 타입이 kotlin에서는 Any 타입이다.
fun anyTypeArg(a: Any): Unit {
when(a) {
is Int -> println("${a}는 정수형 아규먼트입니다.")
is String -> println("${a}는 문자형 아규먼트입니다.")
else -> println("${a}는 취급하지 않는 아규먼트입니다.")
}
}
fun main(args: Array<String>) {
anyTypeArg(100)
anyTypeArg("Hello")
anyTypeArg(10.0f)
}위 함수는 Any 타입의 값 a를 받고, when 구문을 통해서 타입이 무엇인지 검사하게 된다.
결과는 다음과 같다.
100는 정수형 아규먼트입니다.
Hello는 문자형 아규먼트입니다.
10.0는 취급하지 않는 아규먼트입니다.kotlin은 1급 시민이 함수이다.
즉 함수를 파라미터로 전달할 수도 있고, 결과로 반환할 수도 있다.
fun sum(a: Int, b: Int): Int = a + b
fun mul(a: Int, b: Int): Int = a * b
fun printOp(a: Int, b: Int, f: (Int, Int) -> Int): Int {
println("${a}와 ${b}를 받아 함수를 실행한 결과 %d가 되었습니다.".format(f(a, b)))
return f(a, b)
}
fun main(args: Array<String>) {
printOp(10, 20, ::sum)
printOp(10, 2, ::mul)
}실행결과는 다음과 같다.
10와 20를 받아 함수를 실행한 결과 30가 되었습니다.
10와 2를 받아 함수를 실행한 결과 20가 되었습니다.함수를 인자로 받는 것 뿐만 아니라, 함수 자체를 반환할 수 도 있다.
fun sum(a: Int, b: Int): Int = a + b
fun sub(a: Int, b: Int): Int = a - b
fun mul(a: Int, b: Int): Int = a * b
fun div(a: Int, b: Int = 1): Int = a / b
fun etc(a: Int, b: Int): Int = a
fun getOp(op: Char): (Int, Int) -> Int {
when(op) {
'+' -> return ::sum
'-' -> return ::sub
'*' -> return ::mul
'/' -> return ::div
else -> return ::etc
}
}
fun main(args: Array<String>) {
println("sum is %d".format(getOp('+')(10, 20)))
println("sub is %d".format(getOp('-')(10, 20)))
println("mul is %d".format(getOp('*')(10, 20)))
println("div is %d".format(getOp('/')(10, 2)))
}위 코드는 getOp 함수가 오퍼랜드 아규먼트를 받아서(op: Char) 오퍼렌드에 해당하는 함수를 반환한다.
그리고 그 함수를 이용하여 연산을 수행하게 된다.
결과는 다음과 같다.
sum is 30
sub is -10
mul is 200
div is 5Lambda는 이름이 없는 함수를 말한다.
Lambda는 변수에 담겨 처리될 수 있다.
람다는 다음과 같이 정의할 수 있다.
val lambdaName : Type = { argumentList -> code }위와 같이 lambdaName 라는 이름으로 할당이 가능하며 반환 타입으로 Type를 가질 수 있다. (타입을 지정하지 않으면 자동으로 타입 추론이 수행된다.)
람다함수에 전달이 필요한 아규먼트는 argumentList 로 전달이 가능하다.
'->' (arrow) 연산자를 통해서 몸체를 구성할 수 있다.
01.lambda_sample01.kt 파일을 만들고 다음과 같이 작성하자.
fun main(args: Array<String>) {
val square = { number : Int -> number * number }
println(square(10))
}square라는 변수에 람다를 지정했다.
입력값은 number: Int 로 정수형 타입 값을 입력받는다.
결과는 자동으로 추론되어 Int 타입이 될 것이다.
람다 몸체는 number * number 로 제곱을 수행한다.
println을 통해서 해당 람다 함수 실행 결과를 출력할 수 있다.
100결과로 10 * 10 의 값인 100이 출력 되었다.
가끔 타입 추론이 안되는 경우도 있다.
또한 명시적으로 입력/출력 타입을 명시하여 더욱 명확하게 람다 함수를 작성할 수 있다.
파라미터는 ()로 묶어주어야한다.
val time_of_ten : (Int) -> Int = { num -> num }
val params_lambda : (String, Int) -> String = { str, int -> str + int }
val noRet : (Int) -> Unit = { num -> println(num) } time_of_ten 은 정수형 파라미터를 입력받고, 정수형 결과를 반환한다. 내부 처리 결과는 정수 * 10의 결과를 반환하게 된다.
params_lambda 는 (문자열, 정수형) 파라미터를 받고, 두 값을 더한 결과 (문자열)를 반환한다.
noRet 은 반환값이 없을때이다. 반환값이 없을때는 Unit 타입으로 반환할 수 있다고 했다. Unit은 void와 유사하다.
02.lambda_sample02.kt 파일을 만들고 다음과 같이 작성하자.
fun main(args: Array<String>) {
val time_of_ten : (Int) -> Int = { num -> num }
println(time_of_ten(2))
val params_lambda : (String, Int) -> String = { str, int -> str + int }
println(params_lambda("I'm ", 20))
val noRet : (Int) -> Unit = { num -> println(num) }
noRet(100)
}결과는 다음과 같다.
2
I'm 20
100이미 존재하는 객체에 람다함수를 정의하는 방법도 있다.
기존 타입을 확장할 수 있도록 원본타입.(입력파라미터타입) 으로 원본타입을 확장할 수 있다.
(입력파라미터타입) 은 확장에 사용할 람다함수의 파라미터 타입이다.
03.lambda_sample03.kt 파일을 생성하고 다음과 같이 작성하자.
fun string_extends(str: String, num: Int) : String {
val plus2 : String.(Int) -> String = { this + it }
return str.plus2(num)
}
fun main(args: Array<String>) {
println(string_extends("Hello ", 20))
}결과는 다음과 같다.
Hello 20즉 결과적으로 string_extends 라는 함수를 만들고, 내부에서 String.(Int) 를 이용하여 문자열을 확장했다.
반환값은 String이고, 내부에서 this 를 통해서 스트링 자체가 된다.
람다함수에 아규먼트가 1개라면 it라는 예약어를 사용하여 파라미터를 표현할 수 있다.
04.lambda_sample04.kt 를 만들고 다음과 같이 작성하자.
fun main(args: Array<String>) {
val arr_str = arrayOf("Apple", "Banana", "Grape", "PineApple")
// 람다 함수 내부에 item 파라미터를 arr_str로 부터 전달받아 출력한다.
arr_str.forEach { item -> println(item) }
println("-----------------------------------")
// it를 이용하면 다음과 같이 단순한 코드가 된다.
arr_str.forEach { println(it) }
}결과는 다음과 같다.
Apple
Banana
Grape
PineApple
-----------------------------------
Apple
Banana
Grape
PineApple즉, it를 이용하여 코드를 단순하게 만들 수 있다.
함수의 파라미터로 람다를 전다할 수 있다.
05.lambda_sample05.kt 파일을 만들고 다음과 같이 작성하자.
fun pass_lambda(compare: (Int, Int) -> Boolean) : Boolean {
return compare(100, 100)
}
fun main(args: Array<String>) {
val compare : (Int, Int) -> Boolean = { int1, int2 -> int1 == int2 }
println(pass_lambda(compare))
}위와 같이 pass_lambda함수는 파라미터로 lambda 를 입력받는다.
lambda의 형식은 (Int, Int) -> Boolean 의 형식이다.
main 함수에 compare라는 람다 함수를 선언하고, pass_lambda 함수의 파라미터로 전달했다.
결과는 다음과 같다.
true메소드 레퍼런스를 이용하여 이미 존재하는 메소드를 참조할 수 있다.
06.lambda_sample06.kt 파일을 만들고 다음과 같이 작성한다.
fun main(args: Array<String>) {
val reference = Double::isFinite
println(reference(Double.MAX_VALUE))
println(reference(Double.NaN))
}reference 함수는 Double::isFinite 와 같이 '::' 메소드 레퍼런스를 이용해서 isFinite 함수를 사용했다.
Double.MAX_VALUE 나 기타 더블형 값은 모두 finite 이다. (유한 실수이다.)
Double.NaN 은 무한 실수이다.
결과는 다음과 같다.
true
false람다 파라미터에 변수를 직접 지정할수도 있다.
07.lambda_sample07.kt 파일을 만들고 다음과 같이 작성하자.
fun main(args: Array<String>) {
val multiple = { a: Int, b: Int -> a * b }
println(multiple(2, 100))
}위와 같이 a, b 로 정수형을 받아들이는 파라미터 변수를 지정했다.
결과는 다음과 같다.
200지금까지 lambda에 대해서 알아보았다.
코틀린은 lambda를 이용하여 익명의 함수를 만들고 변수에 할당할 수 있다.
또한 람다함수를 이용하여 파라미터로 전달하거나, 함수 결과로 반환할 수도 있다.
DEVOTEE를 활성화 시키면
지금 작성한 댓글에 AI가 댓글을 달아줍니다.