전공 수업 정리 겸, 잘 쓰질 않다보니 계속 까먹는 코틀린 문법 위주로 정리해보았다.
String templates
파이썬의 경우 format 형태를 쓰기도 했는데 코틀린은 $ 하나면 된다.
val i = 10
println("i = $i") // i = 10
만약 length와 같은 함수를 써야하는 경우는 ${}를 활용한다. 연산의 경우도 마찬가지
val s = "abc"
println("$s.length is ${s.length}")
// {}없이 $s.length 로 해버리면 .length라고 문자 그대로 출력하게 됨
println("I have ${numberOfShirts + numberOfPants} items of clothing")
Variable
코틀린은 변수의 타입을 한번 선언한 이상, 다른 타입으로 바꿀 수 없다.
var book : String = "book"
book = 1 // 오류 발생! val book = "book"으로 해도 결과는 마찬가지

또 하나 주의해야할 점은 var / val 의 구별이다.
파이썬이나 C언어만 쓰다가 이쪽 계열(?) 언어를 쓰다보면 헷갈리게 되는데 꼭 알아둬야한다.
var
- Mutable (Changeable)
- 변수의 값을 바꿀 수 있다 (타입말고)
val
- Immutable (Unchangeable)
- 변수의 값을 바꿀 수 없다
- 보통 val 로 선언하는 것을 추천
var count = 1
count = 2
// ok
val size = 1
size = 2
//Error: val cannot be reassigned
Ranges
내용 중에 if 문도 있긴 했는데 얘네는 c언어의 if문과 형태가 같아서 넘어갔다.
val numberOfStudents = 50
if (numberOfStudents in 1..100) {
println(numberOfStudents)
}
// numberOfStudents이 1 부터 100 사이인지 확인하고, 맞으면 출력하기
여기서 1..100 같이 range를 쓸 때 .. 사이에 빈칸이 있으면 안된다. (1. .100 와 같이 빈칸을 두면 안됨)

for (i in 1..5) print(i)
//12345
for (i in 5 downTo 1) print(i)
//54321
for (i in 3..6 step 2) print(i)
//3부터 시작해서 2 간격으로 루프를 돈다. 3 -> 5 -> 7인데 6까지 끝
//35
for (i in 'd'..'g') print (i)
//defg
when
코틀린에서는 switch 문 대신 when 구절을 사용한다.
when (results) {
0 -> println("No results")
in 1..39 -> println("Got results!")
else -> println("That's a lot of results!")
}
// results의 값에 따라 출력되는 내용이 다르다.
for ((index, element) in pets.withIndex()) {
println("Item at $index is $element\n")
}
// python의 enumerate 문법과 같이 쓸 수 있다.
// index와 요소의 값을 한꺼번에 추출 가능
"""
Item at 0 is dog
Item at 1 is cat
Item at 2 is canary
"""
val pets = arrayOf("dog", "cat", "canary")
for (index in pets.withIndex()) {
println("Item at $index is \n")
}
// 만약 (index, element)로 안하고 index 하나만 둔다면
"""
Item at IndexedValue(index=0, value=dog) is
Item at IndexedValue(index=1, value=cat) is
Item at IndexedValue(index=2, value=canary) is
"""
Lists and Array
Lists
val instruments = listOf("trumpet", "piano", "violin")
println(instruments)
// [trumpet, piano, violin]
mutableListOf()로도 쓸 수 있다.
val myList = mutableListOf("trumpet", "piano", "violin")
myList.remove("violin")
// 만약 mutableListOf로 안 했다면 오류가 뜸
근데 val은 변수의 값을 바꿀 수 없다 하지 않았나?
하지만 list의 경우, 보는 시각이 조금 다르다. list의 내용이 바뀐거지, list가 아예 다른건 아니지 않나
맞는 비유인지는 모르겠지만 건물 리모델링한거랑 건물을 부시고 새로 만든다고 생각하면 되지 않을까?
Array
- size는 고정이다.
- Array의 요소들의 타입이 다 달라도 상관없다.
- 연산자 + 사용 가능
val mix = arrayOf("hats", 2)
val numbers = intArrayOf(1,2,3)
val numbers2 = intArrayOf(4,5,6)
val combined = numbers2 + numbers
println(Arrays.toString(combined))
// [4, 5, 6, 1, 2, 3]
Null safety
- 코틀린은 변수는 기본적으로 null일 수 없다.
- safe call operator인 ?를 통해 null을 쓸 수 있게 한다.
- !! 를 사용하여 해당 변수가 null이 아니라는걸 보증(?) 한다.
var numberOfBooks: Int = null
// error: null can not be a value of a non-null type Int
var numberOfBooks: Int? = null
var numberOfBooks = 6
numberOfBooks = numberOfBooks?.dec()
// null이 아니면 값을 1 감소 시키자.
val len = s!!.length
// s가 null이 아니야! 그니까 length를 쓸 수 있어!
// s가 null이면 NullPointerException 발생
numberOfBooks = numberOfBooks?.dec() ?: 0
// numberOfBooks가 null이 아니면 1 감소하고
// null이면 0으로 할당해주자
여기서 조금 귀여웠던 내용..
?: 를 Elvis operator라고 부르기도 하는데 그 이유가 :) 를 웃는 표정으로 보듯
?: 를 옆으로 보면 Elvis 헤어스타일을 한 것같이 보인단다.
Lambda, Higher-order functions
Lambda
얘는 그냥 사진으로 보여주는 게 빠를 듯하다.

Higher-order functions
- 고차 함수라고도 한다.
- 함수를 파라미터로 받거나, 함수를 반환하면 고차원 함수.
fun encodeMsg(msg: String, encode: (String) -> String): String {
return encode(msg)
}
encode라는 함수를 파라미터로 받고, 해당 함수를 반환한다.

encode는 함수 타입 (String) -> String을 요구하기 때문에 (String) -> String 형태인 enc1을 선언하여 넣는것이다.
:: 연산자를 사용하여 선언된 함수를 다른 함수에 인수로 전달할 수도 있다고 한다. 근데 이렇게 많이 쓰나??
fun enc2(input:String): String = input.reversed()
encodeMessage("abc", ::enc2)
// :: 를 쓰지않으면 오류 뜬다.
자료를 번역해보면 :: 연산자는 코틀린에게 함수 참조를 인수로 전달하고 함수를 호출하려고 하지 않는다는 것을 알려준다고 한다.
그니까 함수를 인수로 전달만 할 뿐이지, 얘를 불러서 실행시킨다던지 그 느낌이 아니라는 걸 알려주는 것 같다.. (자신은 없음 ㅠㅠ)
혹은 람다 형식으로 넣어줄 수 있다.
encodeMessage("acronym", { input -> input.toUpperCase() })
// () 밖에서 해도 됨
encodeMsg("acronym") { input -> input.toUpperCase() }
List Filter, Lazy, Eager
Filter의 경우 별 다른 설명없이 예제 코드만 쓰고 넘어간다. 그냥 조건을 넣어서 필터링 한다 그 뿐이기 때문에..
val ints = listOf(1, 2, 3)
ints.filter { it > 0 }
ints.filter{n:Int->n>0}
// 혹은
ints.filter{n->n>0}
val books = listOf("nature", "biology", "birds")
println(books.filter { it[0] == 'b' })
//[biology, birds]
val instruments = listOf("viola", "cello", "violin")
val eager = instruments.filter { it [0] == 'v' }
println("eager: " + eager)
//eager: [viola, violin]
- lazy : 런타임에 필요한 경우에만 발생한다. (값이 클 경우 유용)
- eager : 결과가 사용되었는지 여부에 관계없이 발생한다.