PREVIEW) 5장 - 람다로 프로그래밍
1. 컬렉션을 처리하는 패턴을 표준 라이브러리 함수에 람다를 넘기는 방식으로 대체하는 예제들
2. 자바 라이브러리와 람다를 함께 사용하는 방법
- 자바에서 처음부터 람다를 고려하지 않고 만든 라이브러리라도 람다를 활용하게 만들 수 있다!
3. 수신 객체 지정 람다(lambda with receiver): 람다 선언을 둘러싸고 있는 환경과는 다른 상황에서 본문 실행
위 내용을 배우기 전에, 기본 다지기로! 람다로 프로그래밍을 하기 위한 개념을 먼저 집고 넘어가도록 하겠습니다. 꼬고!
0. 시작
람다(lambda)
다른 함수에 넘길 수 있는 작은 코드 조각
use case) 컬렉션 처리
1. 람다 소개: 코드 블록을 함수 인자로 넣기
람다가 태어나기 전...
이벤트가 발생했을 때 핸들러 실행? 데이터 구조의 모든 원소에 이 연산을 적용? = 무명클래스 사용
클래스 선언 > 그 클래스의 인스턴스를 함수에 넘김
불편해ㅠㅠ
함수를 값처럼 다룬다.(함수를 직접 다른 함수에 전달) = 함수형 프로그래밍
Java vs Kotlin
Java
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
/* 클릭시 수행*/
}
});
Kotlin
val button = findViewById<Button>(R.id.button)
button.setOnClickListener { /* 클릭시 수행할 동작 */ }
2. 람다와 컬렉션
왜? 컬렉션에서 많이 사용할까?
컬렉션을 다룰 떄 수행하는 대부분의 작업은... 일반적인 패턴이 많다! (컬렉션 내 순회 등)
- 일반적인 패턴이라면, 라이브러리 안에서 제공해야 한다. > 이걸 처리하기에 람다가 편리하다!
Java8 이전에는 람다가 존재하지 않았기 때문에 개발자들이 직접 코드를 작성하곤 했다. > 코드의 중복... 노가다...
진짜 편한가?
data class Person(val name: String, val age: Int)
val people = listOf(Person("sybang", 20), Person("mjkim", 21), Person("khji", 26))
사람들로 이뤄진 리스트가 있을 때, 가장 연장자를 찾고 싶다!
Person(name=khji, age=26)
Legacy. 컬렉션을 직접 검색
fun findTheOldest(people: List<Person>) {
var maxAge = 0
var theOldest: Person? = null
for(person in people) {
if(person.age > maxAge) {
maxAge = person.age
theOldest = person
}
}
print(theOldest)
}
@Test
fun ch_5_1_1_use_for_loop() {
val people = listOf(Person("sybang", 20), Person("mjkim", 21), Person("khji", 26))
findTheOldest(people)
}
Lately.
1) 람다를 사용해 컬렉션 검색 maxBy
가장 큰 원소를 찾기위해 비교에 사용할 값을 돌려주는 함수를 인자로 받는다.
@Test
fun ch_5_1_2_use_lambda_maxBy() {
val people = listOf(Person("sybang", 20), Person("mjkim", 21), Person("khji", 26))
println(people.maxBy { it.age })
}
2) 멤버 참조를 사용해 컬렉션 검색 ::
함수나 프로퍼티를 반환하는 역할을 수행하는 람다를 멤버 참조로!
@Test
fun ch_5_1_3_use_member_reference() {
val people = listOf(Person("sybang", 20), Person("mjkim", 21), Person("khji", 26))
println(people.maxBy (Person::age))
}
3. 람다식의 문법
문법
{ x: Int, y: Int -> x + y }
변수에 저장
직접 호출
run
@Test
fun ch_5_2_1_use_lambda() {
val people = listOf(Person("sybang", 20), Person("mjkim", 21), Person("khji", 26))
println(people.maxBy({ p:Person -> p.age}))
}
ㅠㅠㅠㅠ
구분자가 너무 많고, 컴파일러가 유추할 수 있는데 인자타입을 굳이 적어 주었다. 인자가 오직 1개일 때, 굳이 인자에 이름을 붙이지 않아도 된다!
맨 뒤에 있는 인자가 람다식이면, 그 람다를 괄호 밖으로 뺼 수 있다.
인자가 1개일 때) p. 203
인자가 여러개일 때) 람다를 밖으로 뺀다 / 람다를 괄호 안에 유지(얘가 더 보기 쉬움)
- 인자 목록의 맨 마지막 람다만 밖으로 뺼 수 있다. (추천 ㄴㄴ)
람다 파라미터의 타입도 추론할 수 있다. p.205-예제 5.8
컴파일러가 모르는 경우도 있지만, 그럴 때는 써주면 됨.
파라미터 중 일부 타입은 지정 가능.
람다를 바로 사용할 때) 람다 파라미터 이름을 디폴트 이름 it 으로 바꾸면 더 간단히. p.206-예제 5.9
tip! 람다가 중첩되는 경우에는 알아보기 힘드니까, 명시적으로 선언하는 게 더 낫다.
람다를 변수에 저장할 때) 파라미터의 타입 명시 > 파라미터의 타입을 추론할 문맥 존재 X
맨 마지막에 있는 식이 람다의 결과값이 된다.
4. 현재 영역에 있는 변수에 접근
Java & Kotlin
무명 내부 클래스& 람다: 메소드의 로컬 변수를 무명 내부 클래스에서 사용할 수 있다. p. 207 - 5.10
Java: final 변수만 = 값을 변경할 수 없다.
Kotlin: 모든 변수(val, var) = 값을 변경할 수 있다.(var) p. 208 - 5.11
람다가 포획한 변수
val, final 인 변수: 람다 코드를 변수 값과 함께 저장
var, final 이 아닌 변수: 변수를 특별한 Wrapper 로 감싸서 나중에 변경하거나, 읽을 수 있게 한 다음, 래퍼에 대한 람다 코드와 함께 저장
class Ref<T> (var value: T)
p.209 - 회색 박스
!!!!! 람다를 이벤트 핸들러/비동기 적으로 실행되는 코드로 활용하는 경우 !!!!! p. 210 - try Click...
함수 호출이 끝난 다음에 로컬 변수가 변경될 수도 있다.
WHY ? 함수 안에 정의 된 로컬 변수의 생명주기는 함수가 반환되면 끝난다.
> (추측) 람다를 사용하는 함수가 사용이 끝나면, 메모리에서 사라지므로 !!
SOLUTION ? 클래스의 프로퍼티나 전역 프로퍼티 등의 위치로 빼서, 나중에 변수 변화를 살펴 볼 수 있게 한다.
> (추측) 생명주기를 클래스에 맞춘다!
5. 멤버 참조, ::
함수를 직접 넘기는 방법, 함수를 값으로
멤버 참조, member reference, ::
참조 대상이 함수인지 프로퍼티인지와는 관계없이, 뒤에 괄호를 넣으면 안된다.
에타 변환
함수 f <-> 람다 {x -> f(x)} 를 서로 바꿔쓴다.
최상위에 선언된 함수나 프로퍼티를 참조할 수 있다.(클래스 이름 생략) - p. 211
run(::salute)
직접 위임 함수에대 대한 참조를 제공 - p. 212
생성자 참조: 클래스 생성 작업을 연기/저장 - ???? -p. 213
확장함수도 사용 가능
+ 바운드 멤버 참조 - p. 213 - 회색 박스
멤버 참조를 생성할 때, 클래스 인스턴스를 함께 생성 > 나중에 그 인스턴스에 대한 멤버를 호출 > 수신 대상 객체를 별도 지정 X
'Language > Kotlin' 카테고리의 다른 글
[Coroutine] 코루틴이란? (0) | 2022.02.03 |
---|---|
[KotlinInAction] 5장-람다로 프로그래밍(5) 수신 객체 지정 람다: with 와 apply (0) | 2021.12.08 |
[KotlinInAction] 5장-람다로 프로그래밍(5) 수신 객체 지정 람다: with 와 apply (0) | 2021.12.08 |
[KotlinInAction] 3장-함수 정의와 호출(2)컬렉션처리, 문자열다루기, 코드 다듬기(로컬함수/확장) (0) | 2021.11.03 |
[KotlinInAction] 1. 코틀린이란 무엇이며, 왜 필요한가? (0) | 2021.10.22 |