2020. 10. 29. 12:56

화면에서 프로젝트를 닫고 File -> Close Project


다음 화면에서 Configure -> Settings 를 가서 다음을 변경한다



                                                  



Appearance -> Theme 에서 색상을 고르고 Apply 버튼을 누르면 된다




2020. 10. 29. 12:23

매개변수 개수에 따라 람다식을 구성하는 방법


매개 변수와 인자 개수에 따라 람다식의 생략된 표현이 가능



* 람다식에 매개변수가 없는 경우

noParam({"Hello World!"})
fun noParam(out: () -> String) = println(out())

noParam( ) 함수의 매개 변수는 람다식 1개를 가지도 있는데 이때는 함수 사용시 소괄호 생략 가능


이 람다식에는 매개변수가 없으므로 화살표(->) 기호가 사용되지 않음


그리고 여기서 소괄호는 생략 가능


매개변수는 없지만 반환 자료형은 문자열을 반환


따라서 println( )에 의 해 "Hello World" 가 출력



* 람다식의 매개변수가 1개인 경우



람다식에 매개변수가 1개 있을 경우 람다식에 화살표(->) 기호 왼쪽에 필요한 변수를 써줘야 함


fun main( ) {


    oneParam({ a -> "Hello World! $a" })

    

    oneParam { a -> "Hello World! $a" } // 위와 동일한 결과, 소괄호 생략 가능


    oneParam { "Hello World! $it" }  // 위와 동일한 결과, it으로 대체 가능


}


// 매개 변수가 1개 있는 람다식이 oneParam( ) 함수의 매개변수 out으로 지정됨


fun oneParam(out: (String) -> String) {


    println(out("OneParam"))


}




* 람다식의 매개 변수가 2개 이상인 경우


fun main( ) {


    // 매개변수가 2개 있는 람다식


    moreParam { a, b -> "Hello World! $a $b } // 매개 변수 이름 생략 불가


}


// 매개변수가 2개 있는 람다식의 moreParam 함수의 매개변수로 지정됨

fun moreParam(out: (String, String) -> String) {


    println(out("OneParam", "TwoParam"))


}



만일 특정 람다식의 매개변수를 사용하고 싶지 않을 때는 이름 대신에 언더스코어(_)로 대체


moreParam { _, b -> "Hello World! $b" } // 첫 번째 문자열은 사용하지 않고 생략




* 일반 매개 변수와 람다식 매개 변수 같이 사용하기 



fun main( ) {


 // 1. 인자와 함께 람다식을 사용하는 경우


withArgs("Arg1", "Arg2", { a, b -> "Hello World! $a, $b })


// 2. withArgs( ) 함수의 마지막 인자가 람다식인  경우 소괄호 바깥으로 분리 가능


withArgs("Arg1", "Arg2") { a, b -> "Hello World $a, $b }



}


// withArgs( ) 함수는 일반 매개 변수 2개를 포함, 람다식을 마지막 매개변수로 가짐


fun withArgs(a: String, b: String, out: (String, String) -> String) {


    println(out(a, b))


}



* 일반 함수에 람다식 매개변수를 2개 이상 사용하기


 마지막 인자는 소괄호 밖에 둘 수 있음


({첫 번째}, {두 번째})


({첫 번째}) {두 번째}



람다식 함수가 3개가 되었을 때도 마지막 람다식만 빼내어 다음과 같이 구성


({첫 번째}, {두 번째}) {세 번째}









2020. 10. 16. 00:30

* 값에 의한 호출



코틀린에서 값에 의한 호출은 함수가 또 다른 함수의 인자로 전달될 경우


람다식 함수는 값으로 처리되어 그 즉시 함수가 수행된 후 값을 전달


이렇게 함수나 람다식의 함수 형태를 인자로 사용하면 

즉시 호출되어 실행된 후 그 값이 사용됨


val result = callByValue(lamda()) // 람다식 함수를 호출


fun callByValue(b: Boolean): Boolean { } // 일반 변수 자료형으로 선언된 매개변수


val lamda: ( ) -> Boolean = { }




* 이름에 의한 람다식 호출



람다식의 이름이 인자로 전달될 때 실행되지 않고 실제로 호출할 때 실행되도록 하면 어떨까?


val result = callByName(otherLamda) // 람다식 이름으로 호출


fun callByName(b: ( ) -> Boolean): Boolean { } // 람다식 자료형으로 선언된 매개변수


otherLamda: ( ) -> Boolean = { }



위의 코드와 거의 동일해 보이지만 람다식의 이름을 callByName( ) 함수에서 호출하는 점이 다름



이것을 잘 활용하면 상황에 맞춰 즉시 실행할 필요가 없는 코드를 작성하는 경우 


이름에 의한 호출 방법을 통해 필요할 때만 람다식이 작동하도록 만들 수 있음




* 다른 함수의 참조에 의한 일반 함수 호출



람다식이 아닌 일반 함수를 또 다른 함수의 인자에서 호출하는 고차 함수의 경우를 생각


fun sum(x: Int, y: Int) = x + y



덧셈을 하는 평범한 함수


이것을 고차함수인 funcParam( ) 에서 호출


funcParam(3, 2, sum) // 오류! sum은 람다식이 아님


fun funcParam(a: Int, b: Int, c: (Int, Int) -> Int): Int {

    return c(a, b)

}



sum 함수는 람다식이 아니므로 위와 같이 이름으로 호출할 수 없음


하지만 sum( )과 funcParam( )의 매개변수 c의 선언부 구조를 보면 인자 수와 자료형의 개수가 동일


이 때는 다음과 같이 콜론 기호를 함수 앞에 사용해 소괄호와 인자를 생략하고 사용


funcParam(3, 2, ::sum)











2020. 10. 16. 00:11

기본형 변수로 할당된 값은 스택에 있음


다른 함수에 인자로 전달하는 경우에는 해당 값이 복사되어 전달


참조형 변수로 할당된 객체는 참조 주소가 스택에 있고 객체는 힙에 있음


참조형 객체는 함수에 전달할 때는 참조된 주소가 복사되어 전달됨


JVM에서 실행되는 자바나 코틀린은 함수를 호출할 때
인자의 값만 복사하는 '값에 의한 호출'(Call by Value)이 일반적


C++에서 사용하는 포인터 주소 연산이 없기 때문에 주소 자체를 사용해 호출하는
'참조에 의한 호출(Call by Reference)'은 자바나 코틀린에서 사용되지 않음


자바는 객체가 전달될 때 주소 자체를 전달하는 것이 아닌 값을 복사하는데 이것은 참조에 의한 호출처럼 보이지만 그 값이 주소일 뿐


코틀린은 람다식을 사용하면서 몇 가지 확장된 호출 방법을 사용할 수 있음



2020. 10. 13. 12:54

var result: Int


result = highOrder({x, y -> x + y}, 10, 20) // 람다식을 매개변수와 인자로 사용


fun highOrder(sum: (Int, Int) -> Int, a: Int, b: Int): Int {

    

    return sum(a, b)


}



2020. 10. 13. 12:47

* 변수에 할당하는 람다식 작성


val multi = {x: Int, y: Int -> x * y} // 일반 변수에 람다식 할당


var result = multi(10, 20) // 람다식이 할당된 변수는 함수처럼 사용 가능



변수 multi는 x와 y를 인자로 받아 곱하여 변환하는 람다식이 할당


multi 변수는 자료형이 생략되어 있지만 (Int, Int) -> Int에 의해 Int 형으로 자료 추론


람다식이 변수에 할당되어 변수 이름이 multi( )와 같이 함수 형태로 사용


multi(10, 20)에 전달된 10과 20은 람다식 x, y에 전달


그런 다음 화살표( -> ) 기호 오른쪽의 연산 x * y에 의해 두 값을 곱하여 반환



         람다식의 자료형 선언           람다식의 매개 변수  람다식의 처리 내용


val multi:        (Int, Int) -> Int         =    {x: Int, y: Int     ->     x * y}


변수를 함수처럼 람다식의 선언 자료형은   선언 자료형이     함수의 내용과 결과
 사용 가능       매개변수에 자료형이      명시되어 있으면  반환, 표현식이 여러
                   명시된 경우 생략 가능    생략 가능         줄인 경우 마지막
                                                                    표현식이 반환



화살표( -> )를 기준으로 왼쪽에는 람다식의 매개변수 x: Int, y: Int를 작성


오른쪽에는 함수의 내용과 반환 값 x * y를 적음


함수 내용에 표현식이 2줄 이상이라면 마지막 표현식이 반환



val multi2: (Int, Int) -> Int = {x: Int, y: Int ->

    println("x * y")

    x * y // 마지막 표현식이 반환

}



람다식의 매개변수에 자료형이 지정되어 있다면 변수의 자료형은 생략



val multi: (Int, Int) -> Int = {x: Int, y: Int -> x * y} // 생략되지 않은 전체 표현


val multi = {x: Int, y: Int -> x * y} // 선언 자료형 생략


val multi = (Int, Int) -> Int = {x, y -> x * y} // 람다식 매개변수 자료형 생략




* 반환 자료형이 아예 없거나 매개변수가 하나만 있을때 표현 방법



val greet: ( ) -> Unit = { println("Hello World!") }


val square: (Int) -> Int = { x -> x * x }



첫 번째 람다식에는 매개 변수와 반환값이 없음


그래서 greet의 자료형은 ( ) -> Unit 


람다식 본문을 보면 매개변수를 표현할 필요가 없으므로


화살표 앞쪽과 화살표 자체가 생략



변수 square는 (Int) -> Int로 람다식의 자료형을 지정


람다식을 보고 매개변수와 반환값을 추론할 수 있다면 람다식의 매개변수 자료형은 생략



* 람다식 안의 람다식


val nestedLamda: ( ) -> ( ) -> Unit = {{println("nested")}}


아무것도 없는 람다식 { }에 람다식 {println("nested")}를 넣음



// 람다식의 자료형 생략


val greet = {println("Hello World!")} // 추론 가능


val square = {x: Int -> x * x} // square의 자료형을 생략하려면 x의 자료형을 명시


val nestedLamda = {{println("nested")}}


2020. 10. 13. 12:09

* 인자에 일반 함수 사용하기


val res = mul(sum(3, 3), 3) // 인자에 함수 사용


fun sum(a: Int, b: Int) = a + b


fun mul(a : Int, b: Int) = a * b



mul( ) 함수의 첫 번째 인자에 sum( ) 함수를 사용




* 반환 값에 일반 함수 사용하기


fun sum(a : Int, b: Int) = a + b


fun funcFunc( ): Int { // 함수의 반환값으로 함수 사용

    return sum(2, 2)

}



funcFunc( ) 함수의 반환 값으로 sum( ) 함수를 사용



2020. 10. 7. 09:55

* 고차 함수 (High-order Function)


 - 다른 함수를 인자로 사용하거나 함수를 결과값으로 반환하는 함수


 - 일급 객체 또는 일급 함수를 서로 주고 받을 수 있는 함수



예)


fun main( ) {

    println(highFunc({x, y -> x + y }, 10, 20)) // 람다식 함수를 인자로 넘김

}


// sum 매개변수는 함수

fun highFunc(sum: (Int, Int) -> Int, a: Int, b: Int): Int = sum(a, b) 



highFunc( ) 함수는 sum이라는 매개 변수가 있음


하지만 이 sum은 람다식 함수 형식으로 선언


즉 highFunc( ) 함수는 sum을 통해서 람다식 함수를 인자로 받아들이는 고차함수


2020. 10. 7. 09:46

 * 일급 객체 (First Class Citizen)


 - 일급 객체는 함수의 인자로 전달할 수 있음


 - 일급 객체는 함수의 반환값에 사용할 수 있음


 - 일급 객체는 변수에 담을 수 있음



만약 함수가 일급 객체이면 일급 함수라고 부름


일급 함수에 이름이 없는 경우 '람다식 함수' 또는 '람다식'이라고 부름

2020. 10. 7. 09:44

람다식

프로그래밍/Kotlin 2020. 10. 7. 09:44

 * 람다식


람다식은 람다 대수(Lamda Calculus)에서 유래한 것


{ x, y -> x + y } // 람다식의 예(이름이 없는 함수 형태)


위의 식을 보면 함수의 이름이 없고 화살표 (->)가  사용


수학에서 말하는 람다 대수는 이름이 없는 함수


2개 이상의 입력을 1개의 출력으로 단순화한다는 개념



함수형 프로그래밍의 람다식


 - 다른 함수의 인자로 넘기는 함수


 - 함수의 결과값을 반환하는 함수


 - 변수에 저장하는 함수




 * 람다 대수


변수의 네임 바인딩과 대입의 방법을 이용하여 함수 정의, 함수 적용, 귀납적 함수 추상화를 수행하고 수학 연산을 표현하는 형식




2020. 10. 6. 21:51

* 함수형 프로그래밍


 - 순수 함수를 작성하여 프로그램의 부작용을 줄이는 프로그래밍 기법


 - 함수형 프로그래밍에서는 람다식과 고차 함수를 사용



 - 순수 함수를 사용


 - 람다식, 고차 함수를 사용 가능



* 순수 함수

 

 - 부작용이 없는 함수 : 함수가 같은 인자에 대하여 항상 같은 결과를 반환

 

 - 순수 함수 : 부작용이 없는 함수가 함수 외부의 어떤 상태도 바꾸지 않음



예) 


fun sum(a: Int, b: Int): Int {

    return a + b // 동일한 인자인 a, b를 입력받아 항상 a + b를 출력 (부작용이 없음)

}


함수 안에서 함수 외부의 어떤 변수 상태도 바꾸지 않음



* 순수 함수의 조건


 - 같은 인자에 대하여 항상 같은 값을 반환


 - 함수 외부의 어떤 상태도 바꾸지 않음



사실 프로그램이 커지다 보면 부작용을 완벽하게 통제할 수 있는 

순수 함수를 만들기 어려움


평소에 가능한 한 순수 함수에 가깝게 안전한 함수를 구현하려고 노력



예) 순수 함수가 아닌 함수의 예


fun check( ) {

    val test = User.grade() // check( ) 함수에 없는 외부의 User 객체를 사용

    // 변수 test는 User.grade( )의 실행 결과에 따라 달라짐

    if (test != null) process(test)

}



check( ) 함수는 함수 안에서 함수 외부에 있는 User 객체의 함수인 grade( ) 실행


또 grade( )의 함수의 결과값을 test에 저장하여 조건문에 사용


심지어 process( ) 함수는 조건을 만족하지 못하면 실행되지 않음


쉽게 말해 check( ) 함수의 실행 결과를 예측하기 어려움


이런 함수가 순수 함수의 조건을 만족하지 못함


2020. 9. 14. 20:04

파일 이름과 클래스 이름이 같으면 Project 창에서 파일의 확장자를 표시하지 않음


패키지를 생성하면 .으로 붙은 이름에 폴더 생성 후 폴더 안으로 들어감


package 이름을 사용하여 패키지 이름 확인


패키지를 사용할 때는 import 키워드로 선언하여 사용


기본 패키지는 이름에 걸맞게 import 키워드로 패키지를 선언하지 않아도 바로 사용



코틀린 기본 패키지


kotlin.*               Any, Int, Double 등 핵심 함수와 자료형


kotlin.text.*          문자와 관련된 API


kotlin.sequences.*  컬렉션 자료형의 하나로 반복이 허용되는 개체를 열거


kotlin.ranges.*       if 문이나 for 문에서 사용할 범위 관련 요소


kotlin.io.*             입출력 관련 API


kotlin.collections.*   List, Set, Map 등의 컬렉션


kotlin.annotation.*   표기 관련 API



2020. 9. 11. 19:26

Hellokotlin 프로젝트 만들기

 

1. 메뉴에서 File -> New -> Project 를 누른다

 

 


 


2. Java -> Kotlin/JVM 을 선택 후 Next를 누른다

 

 

 

3. 프로젝트 이름을 입력하고 Finish 버튼을 누른다

 

 

 

 

 

 

 

 

 

 

 

 

 

2020. 9. 11. 18:53

Kotlin은 IntelliJ IDEA 라는 프로그램에서 빌드하고 실행한다


IntelliJ IDEA라는 프로그램은 Android Studio를 설치해도 나타난다


IntelliJ IDEA는 젯브레인즈에서 만든 개발도구


Communitiy Edition은 개인과 기업에 상관 없이 무료로 이용 가능


기능 제한, 웹 개발이 빠져 있음


Ultimate Edition은 유료이지만 완전한 기능 제공


IntelliJ IDEA 다운로드 사이트



https://www.jetbrains.com/idea/download/



자바 SDK 설치


Kotlin/JVM 환경을 실습하기 위해 OpenJDK인 Zulu 설치


다운로드 사이트


https://www.azul.com/downloads/zulu