CS_함수형 프로그래밍

이경환·2023년 2월 8일
0

CS

목록 보기
2/6

학습 계획

  • 함수형 프로 그래밍에 대해 전반적으로 알아보며 더 나아가 java에서는 함수형 프로그래밍이 어떻게 쓰이는지 알아보자.

불변객체와 가변객체

  • 불변객체 만드는법
    1. 객체의 상태를 변경하는 메서드(변경자)를 제공하지 않는다. 즉, setter 등의 메서드를 사용하지 않는다.
    2. 클래스를 확장할 수 없도록 한다. final 클래스로 선언 등의 방법으로 상속을 막는다.
    3. 모든 필드를 final로 선언한다. ,모든 필드를 private으로 선언한다.
    4. 자신 외에는 내부의 가변 컴포넌트에 접근할 수 없도록 한다.
    5. 클래스에 가변 객체를 참조하는 필드가 하나라도 있다면, 클라이언트가 그 객체의 참조를 그대로 반환받도록 하지 말고 방어적 복사를 수행해야 한다.
  • final이 불변은 아니다.
    • 필드에 final을 붙인다고해서 불변이 되는것은 아니다. 밑 과같이 Record라는 참조변수가 setterFunction 과같이 final도 아닌 setter로 열려있다면
      이러한 필드를 가진 Record 객체는 가변 객체일 것이다. 이러한 객체로 Person을 조작 하여 불변성을 깰수있다.
public class Person {
    private final String name;
    private final Record record;

    public Person(String name, Record record) {
        this.name = name;
        this.Record = record;
    }

    public String getName() {
        return name;
    }

    public Record getRecord() {
        return record;
    }
}
 public class Record {
    private long score;

    public Record(long score) {
        this.score = score;
    }

    public void setterFunction(long score) { // setter
        this.score = score;
    }
}
  • 컬렉션의 불변
    - copyOf를 통한 방어적 복사와 필드들의 final을 통해 불변성을 유지하는것 처럼 보이지만
    재할당이 불가능하다(Unmodifiable) 다고해서 불변성(Immutable)인 것은 아니다.
Lotto lotto = new Lotto(Arrays.asList(1,2,3,4,5,6));
List<Integer> numbers =lotto.getLottoNumbers();
numbers.add(7);

가령 이러한 코드가 있다한다면 getLottoNumbers로 필드인 lottoNumbers는 final이지만 외부로 꺼낼 수 있다.

add, remove 등 list의 메서드들을 사용하여 컬렉션에 변화를 줄수 있고. lottoNumbers가 재할당이 불가능 한것이지 불변객체가 아니기 때문에 list에 add를 객체를 변경 시킬수 있다. (새로운 List 객체를 만드는 것이아닌 요소를 추가하는 것 일뿐)

이러한 컬렉션 list를 불변으로 지키고싶다Collections.unmodifiableList를 사용해야한다
결론 적으로는 단순히 final은 재할당을 막아줄뿐 불변성을 만들어 주지는 않는다.

public class Lotto {
    private final List<Integer> lottoNumbers;

    public Lotto(List<Integer> lottoNumbers) {
        this.lottoNumbers = List.copyOf(lottoNumbers);
    }

    public List<Integer> getLottoNumbers() {
        return lottoNumbers;
    }
}
  • Unmodifiable 과 Immutable
    • Unmodifiable 수정 할수 없다. 즉 'Read-Only' 용도로만 사용할 수 있다. set(), add()메서드들을 사용하면 예외가 발생한다.

      하지만 Collections.unmodifiableList 사용시 주의 할점이있다. 기존 list와의 참조(연결)을 끊지 않았기 때문에 add하면 값이 추가된다.

    • Immutable 어떤 레퍼런스를 이용해서라도 수정할 수 없어야 한다. 기존 컬렉션의 데이터를 새로운 컬렉션으로 복사한 다음,
      새로운 컬렉션으로의 수정(modify) 접근을 제한하는게 일반적이다.

    • 따라서 컬렉션의 불변성을 유지하기 위해서는 생성자에서는 방어적 복사를 하고, 불변성을 보장하기 위해서는, getter에서는 방어적 복사 또는
      unmodifiableList 반환 중 선택해서 진행하는 것을 권장한다.

public class Test {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        list.add("a");
        List<String> unmodifiableList = Collections.unmodifiableList(list);
        list.add("d");
        System.out.println(unmodifiableList.get(3));
    }
}

프로그래밍에서 함수는 수학에서의 함수와 좀 다르다

  • 수학에서 함수가 1:1 대응이라면 프로그래밍에서는 예전부터(프로시저)라는 이름으로 쓰기도 했고 입력값이 없는경우도 있고 다양한 형태가있다.

함수 합성

  • 자바에 함수형 인페이스를 수혀한 람다식을 결합하는 것이 가능하다. 여러가지 기능을 &&,|| 연산자처럼 합치는 것이가능하다.
    참고자료: https://staticclass.tistory.com/122

게으른연산,지연연산(Lazy Evaluation)

  • 불필요한 연산을 하지 않을 수있다. 함수형 프로그래밍을 이해하기 위해서는 이해해야한다. 반대로는 Eager Evaluation(조급한 연산)
    보통의 반복문으로 모든 조건을 다 계산하고 구한다(조급한 연산) Stream을 이용해 첫번째 조건을 구하면 다음 조건은 피한다. (느긋한 연산)

  • 참고자료 : https://dororongju.tistory.com/137

람다,클로저의 캡쳐 ,쉐도윙

  • 클로저 :람다식 내에 자유변수가 사용되는 것을 클로저라고 한다. 자유변수란 람다식 내에서 정의되지 않고, 또 파라미터로도 전달되지 않은
    외부 Local variable를 참조하는 변수.
  • Variable capture 란 람다식에서 사용한 데이터를 자유변수에 저장 하는 것을 말한다. 더 나아가 다른 스레드에서 스택 영역에 있는
    변수를 복사해서 람다 표현식에서 사용 가능하도록한다.
    • 외부 local 변수가 final로 선언되어야 한다.
    • 외부 local 변수가 final이 아니라면 final처럼 동작해야 한다. 이를 유사 파이널(effectively final)이라고 한다.
  • 일반적인 Lambda와 Closure의 차이

고차함수

  • 고차 함수는 함수를 인자(argument)로 받을 수 있고, 함수의 형태로 리턴할 수 있는 함수이다. 자바에서는 익명객체 람다를 이용

커링

  • 이런게 커링 함수이다.. 함수를 리턴하는 함수
function curry(f) { // 커링 변환을 하는 curry(f) 함수
    return function (a) {
        return function (b) {
            return f(a, b);
        };
    };
}
profile
개선하는 개발자, 이경환입니다

0개의 댓글