-
함수형 프로그래밍 vs 절차형 프로그래밍CS 지식/Common 2021. 4. 26. 15:32
■ 함수형 프로그래밍의 특징
1) Input / Output 구조
> 처리할 input을 넣어주는 것이 전부
2) State와 같은 다른 상태를 넣어주지 않고 때문에 외부 환경에 독립적으로 함수를 실행
3) (2) 번 때문에, 같은 input에 대해서 같은 output이 나오는 '순수함수'의 성격을 지님
[함수형 프로그래밍이 절차형에 비해 안정적인 이유]
State를 참조하여 결과물을 생성하지 않기 때문에,
State를 건드리는 외부 함수의 timing, Thread와 Queue등을 신경쓰지 않고 구현이 가능> State를 참조받지 않고 안정적인 결과들을 expect할 수 있게 프로그램을 구현할 수 있음
> 어떠한 state를 참조하더라도, 인자로 그 변수의 복사본을 가져와서 작업하기 때문에,
함수형 동작구간이 끝나는 시점까지 위의 장점이 유지됨( 사실상 변수를 변경하지 않는 프로그램은 없기에 )
■ 함수형 프로그래밍의 특징 2
1) 선언형 프로그래밍
> 명령형(절차형) 프로그래밍과 대비
※ 명령형이 절차를 순수 단위로 쪼개지 않고 한번에 여러 절차들을 거쳐서 output을 생산하는 방식이라면,
선언형은 특정 기능 순수하게 나누어 그 자체를 In / Output 단위로 생각하여 코딩하는 방식
2) 함수를 값으로 취급
> (1) 처럼 순수함수로 짠 경우, 값을 예측가능하기 때문에 함수의 행위가 값처럼 취급될 수 있음
3) 고계함수
(1) 정의 :인자로 다른 함수를 받아 결과값 또는 함수를 내보내는 함수를 의미
( High-Order Function - 함수를 다루는 함수 )
(a) 예시 1
※ 밑의 경우에 calc이 고계함수
(b) 예시 2
※ num을 받는 고계함수의 return을 해주는 op를 인자로 받는 고계함수
> (b)의 실사용 코드 예제
※ const add 함수 변수를 multiply 등으로 치환해서 바로 사용가능!
const calcWith2 = (op) => { console.log(op); return (num) => { console.log('expected : ', op(2, num)); return op(2, num); }; }; let num = 3; let add = (a, b) => {return a + b}; let add_function = calcWith2(add); console.log('add_function : ',add_function); console.log('add_function result : ',add_function(num)); >>> add_function : [Function (anonymous)] expected : 5 add_function result : 5
4) 커링
(1) 정의 : 단일 호출 함수를, 각각의 프로세스로 쪼개어 병합하여 반환하는 방식
함수 단계를 분리하므로써, 중간에 유용한 함수 조합을 분리하여 끌어쓸 수 있을 때 커링방식의 구현이 유용함
커링은 f(a, b, c)처럼 단일 호출로 처리하는 함수를 f(a)(b)(c)와 같이 각각의 인수가 호출 가능한 프로세스로 호출된 후 병합되도록 변환하는 것
추가 참조 : ko.javascript.info/currying-partials
function curry(f) { // 커링 변환을 하는 curry(f) 함수 return function(a) { return function(b) { return f(a, b); }; }; } // usage function sum(a, b) { return a + b; } let curriedSum = curry(sum); alert( curriedSum(1)(2) ); // 3
> 커링을 쓰는 좋은 예시
예를 들어, 정보를 형식화하고 출력하는 로그 함수 log (date, importance, message)가 있다고 가정해 보겠습니다. 실제 프로젝트에서 이러한 함수는 네트워크를 통해 로그를 보내는 것과 같은 많은 유용한 기능을 제공합니다. 여기서는 alert 창 을 띄우는 것으로 해보겠습니다.
function log(date, importance, message) { alert(`[${date.getHours()}:${date.getMinutes()}] [${importance}] ${message}`); } ------------------------------------------------------------------------------------- // 커링 적용 log = _.curry(log); log(new Date())("DEBUG")("some debug"); // log(a)(b)(c) // logNow 는 log 의 첫 번째 인수가 고정된 partial이 될 것입니다. // 이제 logNow 는 log의 첫 번째 인수를 고정한 것입니다. // 다른 말로 하면 “partially 적용된 함수” 또는 짧게 하면 “partial” 입니다. let logNow = log(new Date()); // use it logNow("INFO", "message"); // [HH:mm] INFO message // 디버깅 로그를 편리하게 하는 함수를 만들어 보겠습니다. let debugNow = logNow("DEBUG"); debugNow("message"); // [HH:mm] DEBUG 메세지
결과적으로
- 커링한 후에 잃은 것은 없습니다. log는 아직 보통 때처럼 호출할 수 있습니다.
- 오늘의 로그 같은 partial 함수를 쉽게 작성할 수 있습니다.
■ JS 기준
1) Vanilla JS
array API에 위와 같은 고계함수들이 많음
> map, filter 등 callback function 작성해서 함수 명령대로 수행하여 output을 받아오고
이를 functional programming처럼 cascading을 적용할 수 있음
참조 예시 : rsaravananbtech.wordpress.com/2016/02/10/javascript-cascade-function/
var Calc = function(){ this.result=0; this.add = function(){ for(var x=0; x<arguments.length; x++){ this.result += arguments[x]; } return this; }; this.sub = function(){ for(var x=0; x<arguments.length; x++){ this.result -= arguments[x]; } return this; }; this.mult = function(){ if(this.result==0)this.result = 1; for(var x=0; x<arguments.length; x++){ this.result *= arguments[x]; } return this; }; this.div = function(){ if(this.result==0) return this; for(var x=0; x<arguments.length; x++){ this.result /= arguments[x]; } return this; }; this.eq = function(){ return this.result }; } var cal1 = new Calc(); cal1.add(3).sub(1).add(2) // Here result = 4;
2) Lodash library 이용
(a) _.curry( ) Method
www.geeksforgeeks.org/lodash-_-curry-method/
(b) Lodash tutorial 예제
참조 :
www.youtube.com/watch?v=jVG5jvOzu9Y
반응형'CS 지식 > Common' 카테고리의 다른 글
CS - 공부 참조 (0) 2021.05.23 절차지향 vs 객체지향(객체지향 3대요소) (0) 2021.04.30 Overriding / Overloading 차이 (0) 2021.04.15 디자인 패턴 (python) (0) 2021.03.21