함수형 프로그래밍
-
정의 : 프로그래밍 패러다임이며, 함수로 모든걸 하는 프로래래밍, 제일 유행하는 프로래밍 방식
- 예. 명령형프로그래밍(C), 객체지향프로그래밍(JAVA)
-
자바스크립트에서 왜 함수형 프로그래밍일까?
- 자바스크립트로 객체지향을 구현할때 어려움(prototypees, this....)
- 버그가 적고, 작성하기 쉽다, 유지보수에 용이
-
어떻게?
-
함수형프로그래밍은 모든걸 함수로 표현한다(Input => Output)
-
인풋과 아웃풋의 플로우를 생각해서 작성해야 한다.
-
Not Functional
-
위에서 아래로 명령형 프로그래밍같이 작동한다. 단순히 콘솔에 보여주기만 한다.
아웃풋이 없다.
-
인풋과 아웃풋을 표현하지 않음
-
var name = "Jun"; var greeting = "Hi, I'm "; console.log(greeting + name); => "Hi, I'm Jun
-
-
Functional
- 함수를 정의하고, 매개변수(Input), return(Output)을 정의한다.
function greet(name){ return "Hi, I'm " + name; } greeting("Jun"); => "Hi, I'm Jun
-
-
Avoid side effects(use "pure" functions)
-
최대한 순수하게 생각하자 => 인풋으로 계산해서 아웃풋을 만들어 반환하자
-
오직 순수함수를 사용하여 부수효과를 줄이자
-
주어진 인풋에서 아웃풋을 계산하여 반환하지 않는다
-
전역변수로 아웃풋이 나온다면 순수함수가 아니다.(함수 외부의 것이 함수의 결과에 영향을 주는것이니까)
// 순수함수가 아닌 이유 : 인풋이 없고, 아웃풋 또한 없으며 단순히 콘솔 창에 찍어주는것만 한다. var name = 'Jun' function greet() { console.log("Hi, I'm " + name) } // 순수함수 : 아웃풋에 영향을 주는것 인풋 밖에 없다 function greet(name) { return "Hi, I'm " + name }
-
오직 인풋만을 가지고 계산하여 아웃풋을 반환하여야 순수함수라고 할 수 있다.
-
-
Use higher-order functions(1급 함수 => 인풋과 아웃풋을 함수로 사용할수있다. 함수로 받아서 함수로 반환 할 수 있다.)
- 자바스크립트에서는 모든것이 객체이기 때문에 함수를 객체로 인풋과 아웃풋을 할 수 있다.
- 함수내에 함수가 있는 구조로 만들수 있다.
function makebeverage(fruit){ return function(string){ return fruit + string } } var apple = makebeverage('apple'); apple('soda'); => 'apple soda'
- 다른 패러다임에서 없는것!!
-
Don't Iterate(for, while)
- 반복문 대신 자바스크립트 내장함수인 map, reduce, filter를 사용하자
- 고차함수 === map, reduce, filter
const arr = [1, 2, 3, 4, 5] arr.map((value, index, arr) => { // 배열에서 value, index를 하나씩 가지고 오며, // return 값에 원하는 결과값을 넣으면 해당 인덱스에 새로운 값을 넣어 새로운 배열을 리턴한다. }) arr.reduce((acc, value, index, arr) => { return acc + value // return의 결과값은 누산기(acc)에 할당되고 해당결과 누산값을 리턴 // intial은 누산값의 초기값으로 만약이 없다면, 배열의 첫번째 요소를 사용한다. }, intial) arr.filter((value, index, arr) => { // return 조건신이 참일때만 해당 벨류를 반환하여 새로운 배열을 리턴한다 })
-
Avoid mutability => use immutable data (변화하는 데이터보단 변화하지 않는 데이터를 사용하자)
-
변화란 : 객체의 위치 변경, 안에 있는 데이터 변경 객체의 주소는 변하지 않지만, 객체 안에 있는 값들의 주소가 변경됨 우리는 객체의 주소를 가지고 핸들링 하기 때문에 변화를 캐치하기 힘들다.
-
의도치 않은 변화로 인해 문제가 발생할 수 있다(다른 곳에서 rooms를 사용하고 있는데 rooms의 값이 변경되면 의도지않은 결과 발생(에러))
var rooms = ['h1','h2','h3']; rooms[2] = 'h4'; rooms; => ['h1','h2','h4']
-
immutable data : 고정된 위치 객체
-
map함수를 이용해 변경된 새로운 데이터를 만든다 원래 데이트는 불변성을 지킨다.
var rooms = ['h1','h2','h3']; var newRooms = rooms.map(rm => { if(rm === 'h3'){return 'h4'} else{return rm} }) newRooms; => ['h1','h2','h4'] rooms; => ['h1','h2','h3'] ```
-
-
Persistent data structures for efficient immutability => Mori, Immutable.js
- 데이터가 많고 객체가 거대하다면 원래 데이터를 복사하고 수정하는데 비효율적이다.
- 데이터를 트리로 만들고 변화하는 새로운 노드를 만들어 원래 노드와 연결해서 새로운 트리를 만든다
- 장점 : 원래 데이터를 전체 복사할 필요없이 새로운 노드를 만들어 연결시키면 효율성 증대
var xs = [0, 1, 2] var ys = [3, 4, 5]
var zs = xs ++ ys
xs = [a, b, c, d, f, g, h]; fun insert (x, E) = T (E, x, E)| insert (x, s as T (a, y, b)) = if x < y then T (insert (x, a), y, b) else if x > y then T (a, y, insert (x, b)) else s
var ys = insert('e', xs)