> For the complete documentation index, see [llms.txt](https://choi-junsu.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://choi-junsu.gitbook.io/docs/dev/til/2022.09/09-06-tue.md).

# 09/06 (Tue)

### fun

#### vararg

인자의 개수가 정해지지 않은 함수를 사용할 때는 파라미터 정의 앞에 `vararg` 변경를 붙이면 된다.\
함수 내부에서는 적절한 배열 타입으로 사용할 수 있다.\
또한, 스프레드 (\*) 연산자를 사용하여 배열을 가변 인자 대신 넘길 수 있다.

```kotlin
fun printNums(vararg num: String) {
    print(num.contentToString()) // [ 1, 2, 4]
}

fun main() {
    val number = arrayOf(1,2,4)
    printNums(*number) // 스프레드 연산자 사용
}
```

**스프레드 연산자를 사용하면 배열을 복사한다** 따라서 함수내에서 배열에 대한 값을 변경하여도, main 함수내에 number 에 값은 변경되지 않는다.&#x20;

하지만 이때 **얕은 복사**가 이뤄진다. 배열 내부에 (위 예는 int)  참조가 들어있는 경우에는 참조가 복사되기 때문에 참조가 가리키는 데이터가 호출하는 쪽과 함수 내부 배열에서 공유된다.

```kotlin
fun change(vararg item: IntArray) { // IntArray = 참조타입
    items[0][0] = 100
}

fun main() {
    val a = intArrayOf(1, 2, 3)
    val b = intArrayOf(2, 3, 4)
    change(a, b)
    print(a.contentToString()) // [100, 2, 3] 호출하는 쪽에서도 값이 변
}
```

*깊은 복사(Deep Copy) - 얕은 복사(Shallow Copy)*

> ***깊은복사란 객체의 모든 값을 다른 메모리 주소에 복사한다.***
>
> 1. data class 인 경우, copy() 함수를 사용하면 깊은복사가 이루어진다.
> 2. 기본클래스를 사용하는 경우에는 직접 구현을 통해 사용할 수 있다.
>
> ***얕은복사는 객체의 참조주소값을 복사한다.***
>
> 1. *복사된 객체의 값을 변경하면 같은 주소값을 바라보는 원본객체에도 영향을 끼친다.*
> 2. 코틀린(자바)에서 '=' 을 통해 다른 인스턴스에 대입을 하면 얕은복사가 된다.

### Any, Nothing, Unit

#### Any

코틀린에서의 최상위 클래스가 `Any` 이다. 자바에 `Object` 와 비슷하다. 코틀린에서도 `Object` 를 사용할 수 있다.\
그렇다면 `Any` 와 `Object`의 차이점은 무엇인가?

> 1. 자바에서는 primitive 타은 계층 구조유형이 아니며, 암시적으로 boxing 해야 하지만 *(ex) int > Integer*\
>    코틀린에 `Any` 에서는 모든 유형의 상위 유형이다.
> 2. Any 는 null 값을 가질 수 없다. 다른 타입과 마찬가지로 `Any?` 를 사용해 Nullable 처리를 할 수있다.

#### Unit

자바에서의 Void 와 동일하다. 주요 특징으로는 다음과 같다.

> 1. Unit 은 인자로 사용할 수 있다.
> 2. Unit 타의 값은 하나만 존재한다
> 3. 암시적으로 반환된다. return 문 작성 시 뒤에 리턴값을 작성하지않으면, Unit을 반환한

#### Nothing

자바에는 존재하지 않는 타입이다. 함수가 정상적으로 종료되지 않을 때 반환 값이 의미가 없을 때 사용한다.

### for 문

for 루프는 컨테이너가 `iteractor()` 함수를 지원하기만 하면 어떠한 타입도 반복문으로 사용할 수 있다.\
※ 문자,배열 등에서 사용할 수 있지만, 확장 메커니즘을 사용하여 어떠한 타입이든 해당 함수를 덧붙일 수 있다.\
\
`Iteractor` 는 컬렉션의 기본 구조를 노출하지 않고 순차적으로 요소에 대한 액세스를 제공한다.

```kotlin
// Iteractor interface
public interface Iterator<out T> {
    // Returns the next element in the iteration.
    public operator fun next(): T

    // Returns `true` if the iteration has more elements.
    public operator fun hasNext(): Boolean
}
```

### 꼬리 재귀 함수(tail recursive)

코틀린은 꼬리 재귀 함수에 대한 최적한 컴파일을 지원한다.\
재귀 함수란 자기 자신을 호출하는 함수를 의미한다. 코드의 가독성이 증가한다는 장점이 있지만 성능차원에서 약간의 부가 비용이 발생하고, `스택오버플로우` 가 발생할 가능성이 있다.

\
`스택오버플로우`란 말 그대로 Stack 의 사이즈를 초과하였을 때 발생한다. 함수에서 지역변수, 파라미터 등 여러가지를 Stack 에 할당되고 함수를 호출하고나서 끝날 때 해당 Stack 을 제거한다.\
그러나 재귀함수를 통해 무한으로 함수를 호출하면 스택에 최대 크기 이상의 메모리를 사용하게 되어 에러가 발생한다.

코틀린에서는 `tailrec` 키워드를 함수 앞에 붙이면 컴파일러가 재귀 함수를 비재귀적인 코드로 자동으로 변환해준다.\
해당 키워드 하나만으로 재귀 함수의 간결함과 비재귀 함수의 성능을 모두 취할 수 있다.
