본문 바로가기
책정리/자바스크립트

함수형 자바스크립트 - 2장 일급 함수와 응용형 프로그래밍

by 난파선 2017. 1. 9.


2.1 일급 함수의 특징

  • 함수형 프로그래밍의 정의를 간단히 '일급 함수' 와 '편의성'이라는 두 용어로 요약할 수 있다.
  • '일급'이라는 용어에는 모든 것을 값으로 취급한다는 의미가 내포되어 있다.
var a = function() {}    // 함수를 변수에 저장할 수 있다.

function b(f) {    // 함수에 전달인자로 전달 할 수 있다.
    f();
}

function c() {
    return function() {};    // 함수를 리턴 할 수 있다.
}
  • 함수를 인자로 받거나 리턴하는 함수를 고차원 함수라고 부른 다.

2.1.1 자바스크립트의 다중 패러다임

  • 명령행 프로그래밍
    • 동작을 자세히 설명하는 방식에 기반한 프로그래밍.
  • 프로토타입 기반 객체 지향 프로그래밍
    • 프로토타입형 객체와 인스턴스에 기반한 프로그래밍.
  • 메타프로그래밍
    • 자바스크립트의 실행 모델의 기반을 변경하는 프로그래밍

명령행 프로그래밍

  • 일반적인 for문을 사용하는 프로그래밍을 말한다.
  • 알고리즘 세부 구현의 정교함을 특징으로 한다.
  • 명령행 코드는 보통 규격명세와 일치하는 수준으로 동작하므로 대부분 일회용 코드이며 재사용하기가 어렵다.
var lyrics = [];

for (var bottles = 99; bottles > 0; bottles--) {
  lyrics.push(bottles + " bottles of beer on the wall");
  lyrics.push(bottles + " bottles of beer");
  lyrics.push("Take one down, pass it around");

  if (bottles > 1) {
    lyrics.push((bottles - 1) + " bottles of beer on the wall.");
  }
  else {
    lyrics.push("No more bottles of beer on the wall!");
  }
}

함수형 방식

  • 추상화된 함수를 이용해서 본래의 기능을 수행하도록 재조립하였다.
function lyricSegment(n) {
  return _.chain([])
    .push(n + " bottles of beer on the wall")
    .push(n + " bottles of beer")
    .push("Take one down, pass it around")
    .tap(function(lyrics) {
           if (n > 1)
             lyrics.push((n - 1) + " bottles of beer on the wall.");
           else
             lyrics.push("No more bottles of beer on the wall!");
         })
    .value();
}

function song(start, end, lyricGen) {
  return _.reduce(_.range(start,end,-1),
    function(acc,n) {
      return acc.concat(lyricGen(n));
    }, []);
}

자바8의 명령행과 함수형.. 참고만

public class TheCompanyProcess {
    public String cleanNames(List<String> listOfNames) {
        StringBuilder result = new StringBuilder();
        for(int i = 0; i < listOfNames.size(); i++) {
            if (listOfNames.get(i).length() > 1) {
                result.append(capitalizeString(listOfNames.get(i))).append(",");
            }
        }
        return result.substring(0, result.length() - 1).toString();
    }

    public String capitalizeString(String s) {
        return s.substring(0, 1).toUpperCase() + s.substring(1, s.length());
    }



    public String cleanNames(List<String> names) {
        if (names == null) return "";
        return names
                .stream()
                .filter(name -> name.length() > 1)
                .map(name -> capitalize(name))
                .collect(Collectors.joining(","));
    }

    private String capitalize(String e) {
        return e.substring(0, 1).toUpperCase() + e.substring(1, e.length());
    }
}

2.2 응용형 프로그래밍

  • 응용형 프로그래밍은 함수 A 내부의 함수 B를 호출하는 방식으로 이루어진다. 이때 함수 A의 결과를 함수 B의 인자로 제공한다.
var nums = [1,2,3,4,5];

function doubleAll(array) {
  return _.map(array, function(n) { return n*2 });    // map안에서 *2를 하는 함수가 호출된다.
}

doubleAll(nums);
//-> [2, 4, 6, 8, 10]

function average(array) {
  var sum = _.reduce(array, function(a, b) { return a+b });
  return sum / _.size(array);
}

average(nums);
//-> 3

function onlyEven(array) {
  return _.filter(array, function(n) {
    return (n%2) === 0;
  });
}

onlyEven(nums);
//-> [2, 4]

2.2.1 컬렉션 중심 프로그래밍

  • 컬렉션 중심 프로그래밍의 핵심은 컬렉션을 처리하는 일반적인 처리 방법을 만들어서 재사용할 수 있는 포괄적인 함수 집합을 구축하는 데 있다.
_.map({a: 1, b: 11}, _.identity);
//-> [1, 11]

2.2.3 응용형 함수 만들기

  • 다른 함수를 인자로 받는 함수를 정의하고 그 다음에 인자로 받은 함수를 호출해서 정의한 함수를 완성한다.
function cat() {
  var head = _.first(arguments);
  if (existy(head))
    return head.concat.apply(head, _.rest(arguments));    // 인자로 배열을 받는 다. 인자로 함수를 받지 않기 때문에 응용형 함수라 할 수 없다.
  else
    return [];
}

cat([1,2,3], [4,5], [6,7,8]);
//-> [1, 2, 3, 4, 5, 6, 7, 8]
  • 인자로 함수를 받을 수 있게 개선한 프로그램
function construct(head, tail) {
  return cat([head], _.toArray(tail));
}

construct(42, [1,2,3]);
//-> [42, 1, 2, 3]

function mapcat(fun, coll) {
  return cat.apply(null, _.map(coll, fun));
}

mapcat(function(e) {
  return construct(e, [","]);
}, [1,2,3]);
//-> [1,",",2,",",3]

function butLast(coll) {
  return _.toArray(coll).slice(0, -1);
}

function interpose (inter, coll) {
  return butLast(mapcat(function(e) {
    return construct(e, [inter]);
  },
  coll));
}

interpose(",", [1,2,3]);
//-> [1,",",2,",",3]


댓글