-
함수형 프로그래밍 (Functional Programming)
함수형 프로그래밍(functional programming)은 자료 처리를 수학적 함수의 계산으로 취급하고 상태와 가변 데이터를 멀리하는 프로그래밍 패러다임의 하나이다.
하나의 프로그래밍 패러다임, (패러다임 : 한 시대의 사람들의 견해나 사고를 근본적으로 규정하고 있는 인식의 체계)
소프트웨어에서의 패러다임은 방법론 -> 프로그래머에게 프로그래밍의 관점을 갖게 해 준다.
위키에 정의된 내용인데 맞는 거 같다. 개발을 처음 접할 때 어느 패러다임을 접하는가에 따라 마치 모국어가 정해지 듯 처음 접한 것에 익숙해진다. 나중에 다른 것을 배우더라도 이전에 있던 것에 대입하면서 비교하면서 배우게 된다.
선언적인 방식으로 구현 -> for나 if에 따른 로직과 특정 기능의 메서드를 호출하는 게 아닌 데이터가 입력으로 주어지고 데이터를 다루는 과정을 정의하는 형식
특정 작업을 함수형 프로그래밍으로 만들면 그 기능은 순수 함수이므로 어디서든 가져다 써도 특정 값에 대해 같은 값을 반환할 거다. 만약 전역 변수라던가 다른 오염원을 사용하면 순수 함수가 아니게 되고 그럼 함수형 프로그래밍의 목적 중 하나인 사이드 이펙트를 없애는 것에서 문제가 발생하기에 옳지 않은 함수형 프로그래밍이 된다.
함수형 프로그래밍과 객체지향 프로그래밍의 차이
내 생각에는 객체지향 프로그래밍은 거대한 프로젝트를 설계할 때 좋은 거 같다.
너무 방대하기 때문에 나눠서 구현을 해야 하고 그러면 객체라는 개념이 너무 알맞게 작용을 한다.
근데 그 객체 안에서 여러 기능이나 공통된 기능은 함수형으로 빼도 좋은 거 같다. 물론 java에는 함수로서 다 대체가 가능할 거 같지만
특징
함수가 1등 시민
함수를 타입으로 지정하거나,
인자 값으로 넘기거나,
리턴 값으로 받을 수 있다.
이런 조건을 지키지 않으면 메소드와 다를게 무엇인가?
함수형 프로그래밍의 전제조건
1급 객체
- 변수나 데이터 구조(자료구조) 안에 넣을 수 있다.
- 파라미터로 전달 가능
- 동적으로 프로퍼티 할당 가능
- 리턴 값으로 사용 가능
자바는 함수형 인터페이스로 구현 가능 이미 있는 유틸을 사용하는 것을 추천
순수 함수
같은 입력에 대해 항상 같은 출력을 반환하는 함수 => 멀티스레드에서 안전, 병렬 처리 및 계산도 가능
순수 함수를 만들기 위해선 매개변수를 지역변수로 바꿔서 사용하는 게 좋다. 원시 타입은 상관이 없고, 레퍼런스 타입은 딥 카피를 해서 사용해야지 힙에 있는 원래의 값이 바뀌지 않고 사용 가능하다.
void make(HashSet <Integer> a){
HashSet<Integer> Hs=new HashSet <>();
a.stream(). forEach(item->Hs.add(item));
}배열 같은 경우는 Arrays.copyof를 통해 깊은 복사를 할 수 있다.. clone() 메서드를 통해서도 깊은 복사가 가능한데 Cloneable를 구현해야 가능하다.. clone함수는 2차원 배열 까지는 깊은 복사를 지원하지 않기 때문에 2차원 배열의 깊은 복사는 개발자가 구현해야 한다.
고차 함수
함수의 인자로 함수를 전달할 수 있다.
함수의 리턴 값으로 함수를 사용할 수 있다.
public class Main {
public static void main(String args []){
result.apply("1");
}
}
static Function <String result=(name)->{
int i = Integer.parseInt(name);
System.out.println(i); return i;
};
static Function<String , Integer> Sample2(Function<String ,Integer> function){
//함수를 인자로 전달 가능 , 리턴 가능
return function;
}메서드 레퍼런스를 통해 만든 함수 result를 Sample2 함수에서는 파라미터와 리턴 타입을 사용하고 있다.
익명 함수
이름이 없는 함수를 말하며 람다식으로 표현되는 함수 구현을 말한다.
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("dd");
}
}). start();
//익명 함수(람다식)
new Thread(() -> {
System.out.println("dd");
}). start();함수형 인터페이스
@FunctionalInterface
public interface MathInterface {
int Sum(Set <Integer> set);
}public int sum(Set <Integer> factors) {
MathInterface mathInterface=set ->set.stream(). reduce(0, (integer, integer2) -> integer+integer2);
return mathInterface.Sum(factors);
}java.util.function 패키지
미리 java에서 만들어 놓은 함수형 인터페이스(1등 시민)가 있다. 이 것들을 적절히 사용하자.
종류 추상 메소드특징 비고 Consumer 인자는 있고, 리턴값은 없음 BiConsumer Supplier 인자는 없고, 리턴값은 있음 Operator 인자도 있고, 리턴값도 있음, 주로 매개값을 연산하고 결과를 리턴 Predicate 인자는 있고, 리턴값은 boolean, 매개값을 조사하고 true/false를 리턴 BiFunction Function 인자도 있고, 리턴값도 있음, 주로 매개값을 연산하고 결과를 리턴 BiFunction Function <T, R>
함수를 지원, 하나의 인자와 리턴을 가짐
Function <String, Integer> LamdaF=str->Integer.parseInt(str);
Integer result=LamdaF.apply("1");함수 LamdaF는 String을 인자로 받아서 Integer로 돌려준다.
사용법은 함수 이름. apply(인자 값);
Consumer <T>
Consumer <String> F=text->System.out.println(text);
Consumer <Integer> F2= input->System.out.println(input*2);
F.accept("dd"); // dd
F2.accept(1);입력만 받고 리턴 값은 없다. void인 메서드를 소지함
Consumer <String> F=System.out::println;
F.accept("Dd");위처럼 줄여 쓰기가 가능하다. 어차피 값은 String하나만 들어오니까 명시하지 않은 것이다..
Supplier <T>
Supplier <String> F= () -> "dd";
String s = F.get();인자는 받지 않고 리턴 타입만 존재하는 메서드를 가지고 있음.
항상 같은 값을 리턴할 때 사용
Predicate <T>
하나의 인자를 받고 리턴 타입이 있다. 리턴 타입은 boolean 고정 Function <T, Boolean>이라 보면 됨
Predicate <Integer> F=input->input>5;
Consumer <Boolean> F2=System.out::println;
F2.accept(F.test(7));
F2.accept(F.test(4));입력값을 출력해주는 Consumer와 boolean으로 반환하는 predicate를 사용
굳이 이렇게 써야 할까? 의문이 든다.
기타 등등..
multifrontgarden.tistory.com/125
'TIL' 카테고리의 다른 글
람다와 Stream (0) 2021.01.19 2021.01.19 기록장 (0) 2021.01.18 2021.01.18 기록장 (0) 2021.01.17 Solid 란 (0) 2021.01.17 2021.01.17 기록장 (0) 2021.01.16