티스토리 뷰
● 도입
1. Scope(스코프 / 유효범위)
- Scope : 변수에 접근할 수 있는 범위
- 함수 안에 함수가 있을 때 내부 함수에서 외부 함수에 있는 변수에 접근이 가능하다.(lexical scope)
- 그 반대는 불가능
- 내부에 있는 Lambda가 다른 함수의 return 값이 되어도(다른 곳으로 넘어가더라도) 여전히 생성 당시의 상위 스코프에서 접근 가능했던 변수들에는 접근 가능하다. 이것을 lexical scope라고 한다.
- Lambda 안에서는 Lambda 밖에 있는 변수에 접근 가능하다. 그 반대는 불가능
public static Supplier<String> getStringSupplier() {
String hello = "Hello";
Supplier<String> supplier = () -> {
String world = "World";
return hello + world;
};
return supplier; // String을 return 하는 Supplier를 return
}
- 일반적으로 method는 호출이 끝나면 method 안에서 선언된 변수들은 사라진다.
- 하지만 return 된 supplier Lambda는 여전히 hello 라는 변수가 필요하다.
- getStringSupplier method를 호출한 후 return 된 supplier Lambda를 호출하면 어떻게 될까?
- supplier Lambda가 사용하는 외부 변수는 여전히 존재하며 문제 없이 사용할 수 있다.
--> 이때 사용되는 개념이 바로 'Closure' 이다.
2. Closure
- Closure : 내부 함수가 존재하는 한 내부 함수가 사용한 외부 함수의 변수들 역시 계속 존재한다.
- 이렇게 lexical scope를 포함하는 함수를 closure라 한다.
- 이 때 내부 함수가 사용한 외부 함수의 변수(위의 예에서는 hello 변수)들은 내부 함수 선언 당시로부터 변할 수 없기 때문에 final로 선언되지 않더라도 암묵적으로 final로 취급된다.
cf) hello 변수를 바꾸려고 하면 compile error 가 발생한다.
3. Curry
BiFunction<Integer, Integer, Integer> add = (x, y) -> x + y;
=>
Function<Integer, Function<Integer, Integer>> add = x -> y -> x + y;
- x를 먼저 받은 후 나중에 y를 받아 최종적으로 (x + y)를 return
- Function<Integer, Function<Integer, Integer>>의 return 값으로 설정된 Function<Integer, Integer>은
return 되어 다른 곳으로 가더라도 여전히 x 값을 사용할 수 있다.(Closure 덕분)
- Closure의 개념을 응용한 것이다.
- 여러 개의 매개변수를 받는 함수를 더 적은 수의 매개 변수를 받는 여러 개의 중첩된 함수로 쪼개어 매개 변수를 한 번에 받지 않고 여러 단계에 걸쳐 나눠 받을 수 있게 하는 기술
● 실습
package com.fastcampus.functionalprogramming.chapter9;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
public class Chapter9Section1 {
public static void main(String[] args) {
// 1. Scope & Closure
// getStringSupplier를 호출해 return 되는 supplier를 받았다.
Supplier<String> supplier = getStringSupplier();
// return 값으로 받은 supplier를 호출
System.out.println(supplier.get());
/*
* [결과값] = HelloWorld
* - 일반적으로 생각하면 getStringSupplier method의 호출이 끝났을 때 hello 변수는 사라져야 한다.
* - 하지만 return 된 supplier가 계속해서 hello 변수를 사용해야하기 때문에
* - System.out.println(supplier.get())를 호출하는 시점에도 hello 변수는 여전히 남아있는 것이다.
*/
// ===================================================================================================
// 2. Curry
BiFunction<Integer, Integer, Integer> add = (x, y) -> x + y;
int result = add.apply(3, 10);
System.out.println("result : " + result);
// x를 먼저 받고 나중에 y를 받는 식으로 함수를 쪼개고 싶다.
Function<Integer, Function<Integer, Integer>> curriedAdd = x -> y -> x + y;
Function<Integer, Integer> addThree = curriedAdd.apply(3);
int result2 = addThree.apply(10);
System.out.println("result2 : " + result2);
/*
* curriedAdd.apply(3)을 통해 Function을 return 받은 addThree 변수는
* 어디를 가더라도 '3'이라는 숫자를 사용할 수 있다.
*/
}
public static Supplier<String> getStringSupplier() {
String hello = "Hello";
Supplier<String> supplier = () -> {
String world = "World";
return hello + world;
};
return supplier;
}
}
'Backend > Java8' 카테고리의 다른 글
#36 Design Pattern (0) | 2022.10.25 |
---|---|
#35 함수형 프로그래밍 응용 - Lazy Evaluation(for 최적화) (0) | 2022.10.24 |
#33 Advanced Stream - Parallel Stream(병렬 Stream) (0) | 2022.10.22 |
#32 Advanced Stream - forEach (0) | 2022.10.21 |
#31 Advanced Stream - Partitioning By (0) | 2022.10.20 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 코딩테스트
- 프로세스
- db
- 빅데이터 분석기사
- java
- jpa
- 프로그래머스
- Spring Boot
- 빅데이터
- 코테
- Java8
- 운영체제
- 메모리
- Phaser
- 알고리즘
- git
- MySQL
- SpringBoot
- Stream
- node.js
- API
- 자료구조
- spring
- Advanced Stream
- SQL
- nosql
- OS
- DART
- Phaser3
- MongoDB
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
글 보관함