mingg IT

[함수형 프로그래밍] 6장 변경 가능한 데이터 구조를 가진언어에서 불변성 유지하기 본문

FrontEnd

[함수형 프로그래밍] 6장 변경 가능한 데이터 구조를 가진언어에서 불변성 유지하기

mingg123 2023. 10. 14. 14:18

6장 변경 가능한 데이터 구조를 가진언어에서 불변성 유지하기

 

장바구니를 예시로 들었을때 동작에서 읽기, 쓰기를 분류할 수 있음 

 

 

읽기

  • 데이터를 바꾸지 않고 정보를 꺼내는 것 

쓰기

  • 데이터를 바꾸는 것 

 

장바구니 동작 

 

  • 제품 개수 가져오기 => 읽기
  • 제품 이름으로 제품 가져오기 => 읽기
  • 제품 추가하기 => 쓰기 
  • 제품 이름으로 제품 빼기 => 쓰기 
  • 제품 이름으로 제품 구매 수량 바꾸기 => 쓰기

 

함수형 프로그래밍에선 쓰기 동작은 불변성 원칙에 따라 구현해서 최대한 읽기로 바꾸어야함. 

 

 

 

카피-온-라이트 원칙 3단계

 

  • 복사본 만들기
  • 복사본 변경하기
  • 복사본 리턴하기 

 

 

연습문제 1

 

적용 전 

var mailing_list = [];

function add_contact(email) {
	mailing_list.push(email);
}

function submit_form_handler(event) {
	var form = event.target;
	var email = form.elements['email'].value;
	add_contact(email);
}

 

내가 작성한 해답

var mailing_list = [];

function add_contact(mailList, email) {
    var newMailList = mailList.slice();

    newMailList.push(email);
    return newMailList;
}


function submit_form_handler(event) {
	var form = event.target;
	var email = form.elements['email'].value;
	mailing_list = add_contact(email);
}

 

 

연습문제 2

 

적용 전 

var a = [1, 2, 3, 4];
var b = a.pop ();
console.log(b); // 4를 출력 console.log(a); // [1, 2, 3] 을 출력

 

내가 작성한 해답

// 읽기, 쓰기 함수로 나누기
function drop_element(array) {
	var newArray = array.slice();
	newArray.pop();
	return newArray;
}

// 값 두개를 리턴하는 함수로 만들기
function print(array) {
	var newArray = array.slice();
	var first = newArray.pop();
	return {
		first: first,
		array: newArray,
	};
}

 

 

연습문제 3

 

Q. push 함수를 카피- 온 라이트형식으로 변경 

 

내가 작성한 해답 

function push(array, elem) {
    var newArray = array.slice();
    newArray.push(elem);
    return newArray;
}

 

요약

 

  • 변경 가능한 데이터를 읽는 것은 액션
  • 쓰기는 데이터를 변경 가능한 구조로 만듬
  • 어떤 데이터에 쓰기가 없다면 데이터는 변경 불가능한 데이터임
  • 불변 데이터 구조를 읽는 것은 계산임 
  • 쓰기를 읽기로 바꾸면 코드에 계산이 많아짐 

 

매번 복사 객체를 만드는건 너무 비효율적인 것이 아닌가?

 

  • 변경 가능한 데이터 구조보다 메모리를 더 많이쓰고 느린 것은 맞음
  • 언제든 최적화 할 수 있음 
    • 불변의 데이터 구조를 사용하고 속도가 느린 부분이 있다면 그때 최적하 해라 
  • 가비지 콜렉터가 매우 빠름 
    • 언어에서 제공하는 GC를 사용해라 
  • 생각보다 많이 복사하지 않음 
    • 얕은 복사는 같은 메모리를 가르키는 참조에 대한 복사본을 만듬 
  • 함수형 프로그래밍 언어에는 빠른 구현체가 있음 
    • 데이터 구조를 복사할 때 최대한 많은 구조를 공유하여, 적은 매모리를 사용함. (클로저 내부) 이는 카피 - 온 라이트 구조를 띰 

 

객체애 대한 카피-온-라이트

 

var object = {a:1, b:2};
var object_copy = Object.assign({}, object);

난  spread 연산자를 많이써서 Object.assign은 잘 사용하지 않았음. 

 

 

중첩된 쓰기를 읽기로 바꾸기

 

적용 전

function setPriceByName(cart, name, price) {
    for (var i = 0; i < cart.lenth; i++) {
        if (cart[i].name === name)
            cart[i].price = price;
    }
}

 

수정 후 

function setPriceByName(cart, name, price) {
	var cartCopy = cart.slice();
	for (var i = 0; i < cartCopy.length; i++) {
		if (cartCopy[i].name === name) cartCopy[i] = setPrice(cartCopy[i], price);
	}
	return cartCopy;
}

function setPrice(item, new_price) {
	return objectSet(item, 'price', new_price);
}

function objectSet(object, key, value) {
	var copy = Object.assign({}, object);
	copy[key] = value;
	return copy;
}
  • objectSet을 살펴보면 두번째 인자로 key를 받음으로써 price 뿐만 아니라 다른 속성을 불변으로 만듬에 사용 가능하다.
  • Object.assign은 얕은 복사 임으로 최상위 데이터 구조만 복사한다. 

Object.assign 사용 예시

  • 위 사진을 보면 shoes의 price만 10 -> 13으로 변경됨을 확인할 수 있다. 

 

요약

 

  • 함수형 프로그래밍에서 불변 데이터가 필요함
  • 카피-온-라이트는 데이터를 불변형으로 유지할 수 있는 원칙임. 복사본을 만들고 원본 대신 복사본을 변경하는것을 의미함
  • 카피-온-라이트는 값을 변경하기 전에 얕은 복사를 진행하고 리턴함. 
  • 보일러 플레이트 코드를 줄이기 위해 기본적인 배열과 객체 동작에 대한 카피-온-라이트 버전을 만들어두는 것이 좋음 

 

 

 

 

 

 

 

 

 

Comments