언더스코어

1 밑줄 문자

밑줄 문자 '_' 를 찾아오신 분은 [[_]]항목으로.

2 자바스크립트 라이브러리

[1] 홈페이지

자바스크립트 라이브러리. jQueryHTML문서를 조작하거나 DOM이벤트를 처리할 목적으로 설계됐다면 언더스코어 라이브러리는 자바스크립트를 LISP처럼 사용할 수 있게 만들어주는 라이브러리의 집합이다. 성능 개선판으로 Lo-Dash 라이브러리가 있다. 언더스코어 라이브러리를 대체할 목적으로 만들어졌으며 거의 모든 API가 호환되면서 속도가 빠른 장점이 있다.

자바스크립트라는 언어 기반 위에서 동작하는 라이브러리이기 때문에 자바스크립트의 기본 동작을 바꿔버리는 놈은 아니다. 하지만 이 놈을 사용하려면 기본적으로 프로그래밍 패러다임을 객체 지향적 사고에서 함수형 프로그래밍 개념으로 전환해야 한다. 따라서 자주 사용되는 라이브러리는 아니다.

이 라이브러리는 객체나 리스트를 해석하는 고차 함수를 지원한다. 루프문을 사용하지 않고 LISP같이 리스트 해석 함수를 사용해 데이터를 처리할 수 있다. 물론 라이브러리로 한 겹 더 감싸진 형태라 직접 루프를 돌면서 데이터를 해석하는 것보다는 성능 면에서는 느리다. 하지만 이것의 진가는 해당 라이브러리의 API문서를 보면 알 수 있다.

[2] 여기서 해당 API목록을 예제와 함께 볼 수 있는데(Lo-Dash라이브러리다) 리스트나 객체를 다룰 때 빈번히 사용되는 어떤 패턴들을 일반화한 함수들을 제공하는 것을 볼 수 있다. 바로 실험해볼 수도 있는데 API문서가 보이는 창에는 기본적으로 언더스코어 라이브러리가 로드돼있기 때문에 F12 눌러서 나오는 자바스크립트 콘솔에 해당 명령들을 입력하면 바로 결과를 볼 수 있다.

이게 도대체 무슨 쓸모가 있는지 잘 모르겠다면 아래의 일을 처리할 수 있는 함수를 생각해보자.

어떤 객체의 리스트를 특정 키 값을 기준으로 정렬한 새로운 리스트를 반환

SQL이라면 간단하다. 그냥 아래의 질의 명령을 데이터베이스에 내리면 되니까.

  SELECT * FROM some_table ORDER BY 'key';

하지만 자바스크립트로 짜려면 궁리를 많이 해야 한다. 자바스크립트의 내장 sort메서드는 숫자 리스트에 대해서만 정렬을 수행할 뿐이라 객체에 대해 정렬하려면 정렬 함수를 자기가 또 구현해야 한다. 하지만 언더스코어 라이브러리에서는 이걸로 충분하다.

  // arr 리스트의 객체를 time프로퍼티에 대해서 정렬
_.sortBy(arr, 'time');

그리고 이런 식으로 정렬된 배열에 대해 이진 탐색 을 하려고 하면 어떨까?

  var finder_index = _(arr).pluck('time').indexOf(current_time, true);

-1 부터 1 사이의 부동소숫점 값으로 된 배열의 절댓값을 취해서 다 더하는 건?

  _([-1,0,1]).map(function(n) { return Math.abs(n); }).sum();

더하는 게 아니라 곱하는 거라면? 곱셈은 sum 이딴 거 없는데?

  _([-2,3,4]).map(function(n) { return Math.abs(n); }).reduce(function(acc, n) { return acc * n; }, 1);

위의 답은 -24가 아니라 24다. 절댓값을 곱했으니까.

두 리스트의 차이값으로 된 리스트를 얻고 싶다?

 _.zipWith([1,2,3,4], [5,6,7,8], function(a, b) { return a-b; });

복잡한 예제로, 단어 빈도수 세기 프로그램을 만들어보자.

  var words = {};
_.each(_.words("ade ball cat drama ade ade drama"), function(a) {words[a] = words[a] ? words[a]+1 : 1; });

두 줄이나 돼서 복잡하다. -

또는 변수 따위 없는 순수한 함수형으로 만들고 싶은 경우

_(_.words("ade ball cat drama ade ade drama")).groupBy().pairs().map(function(n) { return [n[0],n[1].length];}).zipObject().value();

위에것 전부 Lo-Dash의 예제다. 하지만 언더스코어도 거의 호환된다.
다른 다양한 예제는 위의 사이트들을 방문해 보자.