2016년 11월 13일 일요일

[누구나 쉽게 배우는 클로저] [함수(function)] study 9

클로저 함수 정의하기

조금 더 함수를 정의하는 것에 대해 공부하다. 이번에는 인자의 개수와 무관하게 일을 처리하도록 만들 수 있다. 예를 들자면 전에 보았던 이런 것을 말한다.
(+ 1 2 3 4 5 6 6  23 4 2 3 4 2 34 23 4 235 23 42 35 23 42 34 2342 34 23 4 23 42 3)
=> 3031
이렇게 하는 것
(defn check
  [student]
  (str student " check!"))

(defn attendance-check
  [& students]
  (map check students))

(attendance-check "Kim" "Nam" "Park")
이러면 여러개의 일을 할 수 있다. 간단하지 않은가?

2016년 11월 10일 목요일

[누구나 쉽게 배우는 클로저] [함수(function)] 스터디 8

함수 호출, 매크로 호출, 특수 형식

앞에서 함수 호출하는 법을 보았다(함수 식을 연산자로 하는 식). 이와 다른 두 가지 형태로는 매크로 호출(macro call)특수 형식(special form)이 있다. 일단 다른 이야기보다 함수에 대해 더 다뤄보자.

(defn no-params
  []
  "I take no parameters!")

(defn one-param
  [x]
  (str "I take one paramter: " x))

(defn two-params
  [x y]
  (str "Two parameters! That's nothing! Pah! I will smooth them "
       "together to spite you! " x y))
매개변수가 0인 것, 1개인 것, 2개인 것을 나열했다. 클로저의 함수는 개수 덧쓰기(arity overloading)를 지원한다. 즉, 인자 개수에 따라 서로 다른 함수 몸체가 실행되는 함수를 만들 수 있다는 것이다.
(defn multi-arity
  ;; 3개의 인자와 함수 몸체
  ([first-arg second-arg third-arg]
    (do-things first-arg second-arg third-arg))
  ;; 2개
  ([first-arg second-arg]
    (do-things first-arg second-arg))
  ;; 1
  ([first-arg]
    (do-things first-arg)))
한번 만들어보자.
(defn slap ([name sound]
    (str  name "에게 뺨을 때렸더니? " sound "! 소리가 났다."))
  ([name]
    (str name "에게 뺨을 딱!")))

> (slap "you")
"you에게 뺨을 딱!"
> (slap "you" "BBAK!")
"you에게 뺨을 때렸더니? BBAK!! 소리가 났다."
느낌이 오는가?? 그냥 오버로딩 한다 생각하고 괄호로 만들면 된다.

[누구나 쉽게 배우는 클로저] [함수(function)] 스터디 7


((or + -) 1 2 3)
(or + -)가 +를 반환하기 때문에 이 식의 답은 6이 된다. 다른 예도 보자.
((and (= 1 1) +) 1 2 3)

((first [+ 0]) 1 2 3)
정말 신기 하지 않은가???
(1 2 3 4)

("test" 1 2 3)
java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn
이 에러는 함수가 아닌 것을 함수처럼 쓰려고 할 때 나오는 문장이다. 함수를 인자로 취하거나 함수를 반환하는 함수를 고차원함수(higher-order function)라고 부른다.
고차원 함수 기능이 있는 프로그래밍 언어는 일등급 함수(first-class function)를 지원한다고 하는데, 숫자/벡터 같이 익숙한 자료 유형을 다루는 것처럼 함수를 값으로 취급하기 때문이다.< br />
예를들어보자.
(inc 1.1)

(map inc [0 1 2 3])
map함수는 집합의 각원소([0 1 2 3])에 주어진 함수(inc)를 적용하여 새로운 목록을 만든다. 클로저가 일등급 함수를 지원하기 때문에 이를 지원하지 않는 다른 언어에 비해 훨씬 강력한 추상화가 가능하다(고 한다...).

2016년 11월 9일 수요일

[누구나 쉽게 배우는 클로저] [집합(set)] 스터디 6


#{:a :b :c}

이것이 집합인데 집합은 좀 특이하다. 집합은 고유한 값의 모임이다. 클로저는 해시 집합과 정렬된 집합을 갖고 있다고 하는데 여기서는 해시집합을 보도록하자.

(hash-set 1 2)
=> #{1 2}

(conj #{1 2} 2)
=> #{1 2}

고유한 값이기 때문에 더해도 안 더해진다.

(set [3 3 4 2 3])
=> #{2 3 4}

다른 함수들도 알아보자

(contains? #{:a :b} :a)
=> true

(contains? #{:a :b} 3)
=> false

(contains? #{nil} nil)
=> true

또는

(:a #{:a :b})
=> :a


(get #{:a :b} :a)
=> :a




[누구나 쉽게 배우는 클로저] [목록(list)] 스터디 5


'(1 2 3 4)

=> (1 2 3 4)

리스트는 벡터와 다르게 get함수로 얻어올 수 없다. 대신 nth를 쓴다.

(nth '(:a :b :c) 0)
=> :a


그리고 요소를 더할 때는?

(conj '(1 2 3) 4)
=> (4 1 2 3)

여기서 벡터랑 다른 점이 있다. 추가한 4가 맨 처음에 추가 된다는 점이다.

[누구나 쉽게 배우는 클로저] [벡터]스터디 4


[3 2 1]

끝. 이게 벡터다

(get [3 2 1] 0)
=> 3

이것이 무엇을 뜻하는 것 같은가. 그렇다. get 함수로 0번째 위치를 뱉어낸다. [] 이게 싫다면 이렇게 써도 된다.
(vector 3 2 1)
=> [3 2 1]

하지만 결국 [] 안에 들어간다.

(conj [1 2 3] 4)
=> [1 2 3 4]

딱 보아도 conj가 무엇인지 알 수 있지 않은가? 이게 벡터다. 

[javascript patterns][설정 객체 패턴] 스터디 13


설정 객체 패턴

설정 객체 패턴은 좀 더 깨끗한 API를 제공하는 방법이다. 라이브러리나 다른 프로그램에서 사용할 코드를 만들 때 특히 유용하다. 소프트웨어를 개발하고 유지보수하는 과정에서 요구사항이 변경되는 것은 어쩔수 없는 현실이다. 변화하는 요구사항에 우리는 어떻게 코드로 대처해야 할까. addPerson()이라는 함수를 가정해보자. 처음에는 이름과 성만 만들어 사람을 추가하라고 요구를 했다.
function addPerson(first, last) {/*...*/}
갑자기 생일, 성별, 주소 도 저장해야 한다고 한다.(게다가 선택적으로) 선택적으로 저장하는 것을 모르겠고 일단 매개변수를 추가해보자.
function addPerson(first, last, dob, gender, address) {/*...*/} //선택적인 매개변수는 일부러 뒤에 적었다.
함수가 좀 길어졌다. 그런데 username은 필수로 저장해야 한다고 전화가 왔다. 이제 함수를 호출할 때는 필수로 써야 하는 것, 선택적인 매개변수, 그리고 매개변수의 순서... 점점 많아지고 복잡해진다.
addPerson("Younghwan", "Nam", new Date(), null, null, "myID");
많은 수의 매개변수는 참 불편하다. 모든 매개변수를 하나의 객체로 만들어 전달하는 것이 더 낫다. 이 객체를 설정(configuration)을 뜻하는 conf라고 해보자.
var conf = { username: "myID", first: "Bruce", last: "Wayne" };
addPerson(conf);
이 패턴은 함수가 DOM 엘리먼트를 생성할 때, 엘리먼트의 CSS스타일을 지정할 때 유용하다. 엘리먼트와 스타일은 많은 수의 어트리뷰트와 프로퍼티를 가지며 대부분은 선택적인 값이기 때문이다.

2016년 11월 5일 토요일

[Mathematics for Computer Science] 스터디 06

Logical Deductions

Logical Deductions는 논리적 추론이라고 할 수 있는데 여기 중요한 기호들이 나온다.
One fundamental inference rule is modus ponens. This rule says that if P is true and P ⇒ Q is true, then Q is also true. Inference rules are sometimes written in a funny notation.
P
P ⇒ Q
---------------
Q
점선은 원래 실선으로 되어 있어야 한다. 풀어보자면 P가 true이고 P ⇒ Q가 true이면 Q도 true라는 뜻이다. 이것을 modus ponens(논리 긍정식)이라 한다.
Modus ponens is closely related to the proposition (P ∧(P ⇒ Q)) ⇒ Q. Both in some sense say, "if P and P ⇒ Q are true, then Q is true". This proposition is an example of tautology, because it is true for eery setting of P and Q. The difference is that this tautology is a single proposition, whereas modus ponens is an inference rule that allows us to deduce new propositions from old ones. However, if we accept modus ponens then a eneral theorem of logic says that for each tautological implication there is an associated inference rule.
예를들어 ((P ⇒ Q) ∧ (Q ⇒ R)) ⇒ (P ⇒ R) and ((P ⇒ Q) ∧ ¬Q) ⇒ ¬P 둘다 tautologies(동어반복, 항진식)이다. 말로 풀어쓰면 P가 Q이고, Q가 R이라면, P는 R이다. P가 Q이고 Q가 R이 아니라면(false라면) P는 R이 아니다(false다)라는 말과 동일하다.

여기서 ¬이것은 not을 나타낸다.

2016년 11월 4일 금요일

중간리뷰

  공부한 모든 내용을 이곳에 다 적지는 않았지만 나는 지금도 수학공부를 짬내서 하고 있다. 현재 공부 하고 있는 내용은 Number Theory이며 합동(Congruence)에 대해서 공부를 하는 중이다. 이 모든 내용을 적지 못하는 것은 나의 게으름이며, 나의 부족함이다. 하지만 이렇게 부족한 나도 계속 배우려 하고 있는 점을 여러분들을 기억해주기 바란다. 당신들도 공부를 놓지 않기를 바란다.
  사실 요즘 NodeJS를 깨작깨작 가지고 노는 중이다. 자바와 다르게 아직 서툴러서 어떤 생각을 해도 제대로 글이(코딩이) 써지질 않는다. 하지만 역시 자바로 코딩하나 자바스크립트로 코딩을 하나 내가 무엇인가를 구현하려 할 때, 그 방식은 똑같다. 그저 문법만 다를 뿐. 그 근본을 바꾸려면 역시 기본을 바꿔야 하고 틀을 바꿔야 한다고 믿는다.

  사실 수학 공부가 정말 쓸모 없다고 생각이 들기도 하나, 내가 입사하면서 느꼈던 수치를 생각하면서 나는 오늘도 공부를 하려 한다. 항상 할 수 있는 것은 아니지만 그렇다고 아예 손을 놓을 수는 없기에 일주일에 한시간이라도 절대 놓지는 않을 것이다.

[여인의 초상]을 읽고

제임스 헨리의 [여인의 초상]은 한 여인 이사벨 아처의 삶을 그려내었다. 말그대로, 이 장편소설은 한 여인에 대해 적은 것이 아니라, 그리려고 노력하였다. 장면 하나하나를 엮으려 노력하기보다는 한 장면 장면이 그림처럼 수놓아지기를 바라지 않았나 싶다. 처음 이사벨이 나타나서 다른 신사들의 마음을 휘어잡고 있을 때, 신사들을 어디로 튈지 모르는 이사벨의 발걸음과 마음을 잡으려고 그녀의 뒤를 쫓았다. 하지만 이사벨을 자유를 원했고 신사들의 청혼을 거절했다.
  이사벨은 그 시대의 미국인 여인의 초상인 듯 하다. 자유분방함을 원하고 결혼을 구속이라 원하며 결혼으로 인한 신분상승만이 여인의 답이라 생각하지 않으며 항상 생기넘치는 기운을 풍기는 사람. 하지만 이사벨은 결국 결혼을 한다. 정략결혼? 아니다. 아이러니한 것이 자신이 간절히 원하여 결혼을 하게 된다. 그녀를 정말 사랑했던 사람들, 자신들이 사회에 주어진 일들을 충실히 하는 사람들을 거절하고 그녀가 상속받은 돈을 사랑한 사람과 결혼한다. 아주 행복하게...
  그녀는 후회하고 후회한다. 그녀는 이미 족쇄를 찼고, 신사들은 그녀를 보며 더이상 행복한 마음을 가지지 않는다. 왜냐하면 그녀의 생기는 갇혀서 퍼지지 못하고 그녀 자신도 더 이상 행복하지 않기 때문이다. 자유? 그런 것들을 생각할 겨를도 없는 듯 하다.
  그녀를 끝까지 도와준 렐프. 아 정말 가여운 렐프. 이사벨에게 큰 돈을 안겨주고 떠나간 렐프. 그는 어쩌면 자신이 안겨준 큰 돈 때문에 이사벨에게 이런 비극이 왔다고 생각하기까지 한다. 그리고 몇 년지 죽는 렐프를 보며 이사벨은 렐프를 보고, 다시 살기위해 이혼을 한다.
.
.
.
이 글을 한 장, 한 줄거리로 다 표현할 수는 없다. 이 책은 줄거리보다도 그들의 독백, 가끔씩 하는 말 한마디가 어쩌면 책을 전부 표현하기도 한다. 하지만 우리가 알아야 하는 점은 자신을 너무 믿지 말라는 점. 그러기 위해서는 더욱 배워야 한다는 점. 이사벨은 참으로 당돌하고 매력이 넘쳤지만 많이 부족했다. 자신의 논리를 더욱 믿지 말았어야 했지만... 그녀는 자신을 너무 믿었고, 자신을 사랑하는 사람들을 너무 믿지 않았다. 자신은 당연히 사랑받아 마땅했다고 생각했었을까? 그 사랑이 다 없어져서야 슬퍼하는 삶이란...

[javascript patterns][메모이제이션(Memoization) 패턴] 스터디 12


함수프로퍼티 - 메모이제이션(Memoization)패턴

함수는 객체이기 때문에 프로퍼티를 가질 수 있다. 사실 함수는 생성될 때부터 프로퍼티와 메서드를 가지고 있다. 그 예가 length다. length는 함수가 받는 인자의 개수를 값으로 가진다.
function func(a, b, c) {}
console.log(func.length); // 3
언제들지 함수에 사용자 정의 프로퍼티를 추가할 수 있다. 함수에 프로퍼티를 추가하여 결과(반환 값)을 캐시하면 다음 호출 시섲ㅁ에 복잡한 연산을 반복하지 않을 수 있다. 이런 방법을 메모이제이션 패턴이라고 한다.
var myFunc = function(param) {
  if (!myFunc.cache[param]) {
    var result = {};
    //... 비용이 많이 드는 수행 ...
    myFunc.cache[param] = result;
  }
  return myFunc.cache[param];
};

//캐시 저장공간
cache 프로퍼티는 함수로 전달된 param 매개변수를 키로 사용하고 계산의 결과를 값으로 가지는 객체(해시)다. 위 코드의 문제는 myFunc함수가 단 하나의 매개변수를 받는다고 가정하고 있다. 게다가 이 매개변수는 문자열과 같은 원시 데이터 타입이라고 가정한다.
더 많은 매개변수와 복잡한 타입을 갖는다면 어떻게 해야 할까? (직렬화하여 해결한다.)
var myFunc = function() {
  var cachekey = JSON.stringify( Array.prototype.slice.call(arguments)),
      result;

  if (!myunc.cache[cachekey]) {
    result = {};
    //비용이 많이 드는 수행...
    myFunc.cache[cachekey] = result;
  }
};

// 캐시 저장공간
myFunc.cache = {};
직렬화하면 객체를 식별할 수 없게 되는 것을 주의하라. 만약 같은 프로퍼티를 가지는 두 개의 다른 객체를 직렬화하면, 이 두 객체는 같은 캐시 항목을 공유하게 될 것이다.
이 함수를 작성하는 다른 방법으로는 하드코딩 대신 arguments.callee를 사용해 함수를 참조할 수 있다. (하지만 곧 사라질 운명이다. 쓰지 않는 것이 낫다. 명심)
var myFunc = function (param) {
  var f = arguments.callee,
      result;

  if (!f.cache[param]) {
    result = {};
    //...비용이 많이 드는 수행...
    f.cache[param] = result;
  }
  return f.cache[param];
};

// 캐시 저장공간
myFunc.cache = {};
};

[javascript patterns] 스터디 11


즉시 객체 초기화

코드부터 보자.
({
  //여기에 설정 값들을 정의한다.
  maxwidth: 600,
  maxheight: 400,

  //메서드도 정의할 수 있다.
  gimmeMax: function() {
    return this.maxwidth + 'x' + this.maxheight;
  },

  // 초기화
  init: function() {
    console.log(this.gimmeMax());
    //초기화작업실시...
  }
}).init();

초기화 시점의 분기

초기화 시점 분기(로드타임 분기)는 최적화 패턴이다. 브라우저 탐지(또는 기능 탐지)가 전형적인 예다.
//변경 이전
var utils = {
  addListener: function(el, type, fn) {
    if (typeof window.addEventListener === 'function') {
      el.addEventListener(type, fn, false);
    } else if (typeof document.attachEvent === 'function') {
      el.attachEvent('on' + type, fn);
    } else { // 구형의 브라우저
      el['on' + type] = fn;
    }
  },
  removeListener: function(el, type, fn) {
      // 거의 동일한 코드
  }
};
이 코드는 약간 비효율적이다. utils.addListener()나 utils.removeListener()를 호출할 때마다 똑같은 확인 작업을 반복해서 실행한다.
// 변경 이후

// 인터페이스
var utils = { addListener: null, removeListener: null};

// 구현
if (typeof window.addEventListener === 'function') {
  utils.addListener = function(el, type, fn) {
    el.addEventListener(type, fn, false);
  };
  utils.removeListener = function(el, type, fn) {
    el.removeEventListener(type, fn, false);
  };
else if (typeof document.attachEvent === 'function') { // IE
  utils.removeListener = function (el, type, fn) {
    el.detachEvent('on'+type, fn);
  };
} else { // 구형브라우저
  utils.addListener = function (el, type, fn) {
    el['on' + type] = fn;
  };
  utils.removeListener = function (el, type, fn) {
    el['on' + type] = null;
  };
}

[javascript patterns] 스터디 10


즉시 실행 함수의 반환 값

var result = (function () {
  return '리턴';
}());
이렇게 사용하면 된다. 그럼 즉시실행하지 않는 함수와는 무슨 차이일까?
var result = function () {
  return '리턴';
};
이 문법이 더 간단하다. 차이점이라면 result(); 로 해야 값이 나온다는 점. 하지만 혹여 함수가 아니라 '리턴'이라는 값이 나올 것이라는 오해를 할 수도 있다. 그래서 '()'이걸 뒤에 붙이지 않는다면?? 값은 나오지 않는다.
var getResult = {
  message : (function () {
    var who = 'me',
        what = 'call';
    return what + ' ' + who;
  }()),
  getMsg : function () {
    return this.message;
  }
};

o.getMsg();
o.message;
이 둘을 보면서 message와 getMsg의 사용법의 차이를 생각해보자.
즉시 실행 함수 패턴은 폭넓게 사용된다. 전역 변수를 남기지 않고 많은 작업을 할 수 있게 해줄 것이다. 서적에 의하면 이 패턴은 북마클릿(bookmarklet)에서 많이 쓰인단다. 어떤 페이지에서도 실행되고 전역 네임스페이스를 깨끗하게 유지하는 것이 중요하기 때문이란다.
개별 기능을 독자적인 모듈로 감쌀 때도 유용하다.
개별 기능을 독자적인 모듈로 감쌀 수도 있따. 이걸로 기능을 단위별로 정의하는 거다. 이것을 module1이라고 하자
// module1.js에서 정의한 module1
(function () {
  // 모든 module1 코드 ....
}());
이 템플릿을 따라 또 다른 모듈로 코딩할 수 있다. 긜고 실제 사이트에 코드를 올릴 때, 어떤 기능이 사용도리 준비가 되었는지 결정하고 빌드 스크립트를 사용해 해당하는 파일들을 병합하면 된다.