blogspot 으로 이사갑니다. 안녕하십니다


이쪽으로 이사갑니다.
자꾸 이글루스가 코드를 깨먹어서 짜증이 나는군요.

일부 글을 이전했고 여기는 그대로 남겨놓습니다.

requery 를 피하는 법 수련

객체를 생성 후 생성한 객체를 다시 참조하는 패턴으로

$('div#mainContext').append('<div class="header"/>');
$('div.header').click(function() {
  // do something
});

이런 식으로 흔히들 쓰는데 $('div.header') 를 도는 비용이 많이 드니

$('<div class="header"/>').appendTo('div#mainContext').click(function() {
  // do something
});

으로 순서를 바꿔서 객체를 chaining으로 활용하자.



object-literal을 이용한 패턴 수련

Object-literal은 아래처럼 new Object() 대신

var car = new Object();
car.goes = "far";

심플하게 JSON인

var car = {goes: "far"};
를 사용하는 패턴인데

$().ready(function() {
  $('#submit').click(function() {
    $('.container').slideUp(function() {
      // do something
    });
  });
  $('#navBar').bind('swipeleft', function() {
     // do something
  });
});

무기명 함수를 사용할 경우 흔히 발생하는 콜백 패크맨 형태를 정리하는데 사용할 수 있다.
사용 방법은 간단하다.
var app = {
  onReady: function() {
    $('#submit').click(app.onSubmit);
    $('#navBar').bind('swipeleft', app.onSwipeLeft);
  },
  onSubmit: function() {
    $('.container').slideUp(app.afterSlideUp);
  },
  afterSlideUp: function() {
    // do something
  },
  onSwipeLeft: function() {
    // do something
  }
};
$().ready(app.onReady);

콘솔 테스트나 유닛 테스트를 하기에도 편하고 가독성도 낫다.

고종석의 언어학 카페 말들의 모험 연재 버닝!!

언어학 카페 말들의 모험 연재. 후우..

[고종석의 언어학 카페 말들의 모험] <1> 연재를 시작하며
http://news.hankooki.com/ArticleView/ArticleView.php?url=culture/200909/h2009092721310584330.htm&ver=v002

[고종석의 언어학 카페 말들의 모험] <2> 랑그의 언어학과 파롤의 언어학
http://news.hankooki.com/ArticleView/ArticleView.php?url=culture/200910/h2009100421142986330.htm&ver=v002

[고종석의 언어학 카페 말들의 모험] <3> 번역이라는 고역(苦役) (上)
http://news.hankooki.com/ArticleView/ArticleView.php?url=culture/200910/h2009101121405384330.htm&ver=v002

[고종석의 언어학 카페 말들의 모험] <4> 번역이라는 고역 <中>
http://news.hankooki.com/ArticleView/ArticleView.php?url=culture/200910/h2009101821382986330.htm&ver=v002

[고종석의 언어학 카페 말들의 모험] <5> 번역이라는 고역 <下>
http://news.hankooki.com/ArticleView/ArticleView.php?url=culture/200910/h2009102521340086330.htm&ver=v002

[고종석의 언어학 카페 말들의 모험] <6> 랑그는 형식이지 실체가 아니다
http://news.hankooki.com/ArticleView/ArticleView.php?url=culture/200911/h2009110121451086330.htm&ver=v002

[고종석의 언어학 카페 말들의 모험] <7> 촘스키 혁명
http://news.hankooki.com/ArticleView/ArticleView.php?url=culture/200911/h2009110822312686330.htm&ver=v002

[고종석의 언어학 카페 말들의 모험] <8> 연재를 마치며
http://news.hankooki.com/ArticleView/ArticleView.php?url=culture/200911/h2009111522491486330.htm&ver=v002

한국일보 '다윈은 미래다' 기사 모음 버닝!!

'다윈은 미래다' 기사 모음. 아무리 찾아도 목차를 못찾겠다. 무슨 생각으로 사이트를 만들었냐 한국일보!

[다윈은 미래다] 1부 <1> 다위니즘 - 선택과 적응
http://news.hankooki.com/lpage/it_tech/200902/h2009021102413823760.htm

[다윈은 미래다] 1부 <2>인간, 영장의 지위를 잃다
http://news.hankooki.com/ArticleView/ArticleView.php?url=it_tech/200902/h2009021802584823760.htm&ver=v002

[다윈은 미래다] 1부 <3> 다윈 이후의 진화론
http://news.hankooki.com/ArticleView/ArticleView.php?url=it_tech/200902/h2009022503010723760.htm&ver=v002

[다윈은 미래다] 2부 <1> 문화는 진화의 산물인가
http://news.hankooki.com/ArticleView/ArticleView.php?url=it_tech/200903/h2009030403335923760.htm&ver=v002

[다윈은 미래다] 2부 <2> 진화의 동력은 무엇인가
http://news.hankooki.com/ArticleView/ArticleView.php?url=it_tech/200903/h2009031102521023760.htm&ver=v002

[다윈은 미래다] 2부 <3> 동성애는 왜 존재하는가 
http://news.hankooki.com/ArticleView/ArticleView.php?url=it_tech/200903/h2009031803144923760.htm&ver=v002

[다윈은 미래다] 2부 <4> 경제위기는 왜 반복되는가 
http://news.hankooki.com/ArticleView/ArticleView.php?url=it_tech/200903/h2009032503173723760.htm&ver=v002

[다윈은 미래다] 2부 <5> 생물의 뿌리는 하나인가 
http://news.hankooki.com/ArticleView/ArticleView.php?url=it_tech/200904/h2009040102523823760.htm&ver=v002

[다윈은 미래다] 2부 <6> 남녀의 차이는 타고나는가 
http://news.hankooki.com/ArticleView/ArticleView.php?url=it_tech/200904/h2009040802361323760.htm&ver=v002

[다윈은 미래다] 2부 <7> 생명의 블랙박스는 무엇인가 
http://news.hankooki.com/ArticleView/ArticleView.php?url=it_tech/200904/h2009041503021423760.htm&ver=v002

[다윈은 미래다] 2부 <8> 인간은 어디에서 왔는가 
http://news.hankooki.com/ArticleView/ArticleView.php?url=it_tech/200904/h2009042203182323760.htm&ver=v002

[다윈은 미래다] 3부 <1> 갈라파고스의 산 증인 그랜트 부부 
http://news.hankooki.com/ArticleView/ArticleView.php?url=it_tech/200905/h2009050602500423760.htm&ver=v002

[다윈은 미래다] 3부 <2> 진화심리학의 거목 스티븐 핑커 
http://news.hankooki.com/ArticleView/ArticleView.php?url=it_tech/200905/h2009051302561523760.htm&ver=v002

[다윈은 미래다] 3부 <3> 진화론 논쟁의 核 리처드 도킨스 
http://news.hankooki.com/ArticleView/ArticleView.php?url=it_tech/200905/h2009052002522223760.htm&ver=v002

[다윈은 미래다] 3부 <4> 인간의식의 철학자 다니엘 데넷 
http://news.hankooki.com/ArticleView/ArticleView.php?url=it_tech/200905/h2009052703171823760.htm&ver=v002

[다윈은 미래다] 3부 <5> 사회생물학의 대부 에드워드 윌슨 
http://news.hankooki.com/ArticleView/ArticleView.php?url=it_tech/200906/h2009060303354023760.htm&ver=v002

Dijkstra's algorithm을 이용한 최단 경로 찾기를 javascript 로 구현해보았다. 수련

http://en.wikipedia.org/wiki/Dijkstra's_algorithm
여기가 위키.
언제나처럼 소스는 h-tp://jsbin.com/acatav/3/edit#javas-ript
"최단경로 그까이꺼 대충 트리로 펼친 담에 올 합산한 비용이 젤 적은 놈 뽑아내면 되는거 아니야?"
라고 생각했다가 역시 검색이 최고. 나보다 멍청한 놈은 좀처럼 없다는 것이 진리.
알고리즘은 심플하다.
'자신과 인접한 노드와 이제까지 탐색한 노드 중 가까운 놈만 남기고 다 지운다.'의 반복.
node 에서 해보려면 맨 마지막 $('p')부분을 지워주시면 되겠다.
사용예는 다음과 같다.
computePath(vertices, vertices[0]);
vertices 중 0번째부터 출발하는 최단 경로를 계산해서 각 vertex별 previous 와 minDistance를 넣어준다.
node.js 에서 바로 돌려볼 수 있는 소스는 다음과 같다.
var vertex = function(param){
  var name = '';
  var edge = [];
  var minDistance = 99999;
  var previous = null;
  name = name || param.name;
  edge = edge || param.edge;
  minDistance = minDistance || param.minDistance;
  previous = previous || param.previous;
  return {
    "name" : name,
    "edge" : edge,
    "minDistance" : minDistance,
    "previous" : previous
  };
};
var vertices = [];
vertices.push(new vertex({"name" : 'Harrisburg'})); // Baltimore,Allentown
vertices.push(new vertex({"name" : 'Baltimore'})); // Harrisburg
vertices.push(new vertex({"name" : 'Washington'})); // Baltimore
vertices.push(new vertex({"name" : 'Philadelphia'})); // Baltimore,Allentown,New York
vertices.push(new vertex({"name" : 'Binghamton'})); // Allentown
vertices.push(new vertex({"name" : 'Allentown'})); // Harrisburg,Philadelphia,Binghamton,New York
vertices.push(new vertex({"name" : 'New York'})); // Philadelphia,Allentown
vertices[0].edge = [{
      "id" : vertices[1],
      "distance" : 79.83
    },{
      "id" : vertices[5],
      "distance" : 81.15
    }];
vertices[1].edge = [{
      "id" : vertices[0],
      "distance" : 79.75
    },{
      "id" : vertices[2],
      "distance" : 39.42
    },{
      "id" : vertices[3],
      "distance" : 103.00
    }];
vertices[2].edge = [{
      "id" : vertices[1],
      "distance" : 38.65
    }];
vertices[3].edge = [{
      "id" : vertices[1],
      "distance" : 102.53
    },{
      "id" : vertices[5],
      "distance" : 61.44
    },{
      "id" : vertices[6],
      "distance" : 96.79
    }];
vertices[4].edge = [{
      "id" : vertices[5],
      "distance" : 133.04
    }];
vertices[5].edge = [{
      "id" : vertices[0],
      "distance" : 102.53
    },{
      "id" : vertices[3],
      "distance" : 62.05
    },{
      "id" : vertices[4],
      "distance" : 134.47
    },{
      "id" : vertices[6],
      "distance" : 91.63
    }];
vertices[6].edge = [{
      "id" : vertices[3],
      "distance" : 97.24
    },{
      "id" : vertices[5],
      "distance" : 87.94
    }];
var computePath=function(vertices, source) {
  source.minDistance = 0;
  var vertexQueue = [source];
  while (vertexQueue.length) {
    var u = vertexQueue.shift(0);
    console.log('-----');
    console.log(u.name);
    u.edge.forEach(function(v,k) {
      var distanceThroughU = u.minDistance + v.distance;
      console.log('    ', v.id.name + ':'+distanceThroughU+'<'+v.id.minDistance + 
                  (distanceThroughU < v.id.minDistance ? '' : '(out)' ));
      if(distanceThroughU < v.id.minDistance) {
        v.id.minDistance = distanceThroughU;
        v.id.previous = u;
        vertexQueue.push(v.id);
      }
    });
  }
};
computePath(vertices, vertices[0]);
vertices.forEach(function(v) {
  var path = [];
  var current = v.previous;
  while(!!current) {
    path.push(current);
    current = current.previous;
  }
  var result = v.name+':'+path.map(function(w) {
    return w.name;
  }).reverse().join('->')+'=>'+v.name+'('+v.minDistance+')';
  console.log(result);
});

크롬에서 편집하면 소스에도 반영! chrome-devtools-autosave 소개 버닝!!

http://addyosmani.com/blog/autosave-changes-chrome-dev-tools/
링크를 보고 '그래 이거야!' 싶어서 따라해봄.

먼저 클라이언트 사이드 준비

주소창에 chrome://flags/ 를 쳐서 

실험실 확장 프로그램 API
실험실 확장 프로그램 API를 사용합니다. 확장 프로그램 갤러리에서는 실험실 API를 사용하는 확장 프로그램을 업로드할 수 없습니다.

를 찾아 '사용'을 체크하거나
인자값에 --enable-experimental-extension-apis 를 추가한다.

Windows 에선
단축아이콘을 만들고  대상 항목 뒤에 --enable-experimental-extension-apis 를 추가

OSX 에선
open -b com.google.chrome --enable-experimental-extension-apis 로 실행
하면 되겠다.

실험실 확장 프로그램 API 사용을 위해 크롬을 재시작하고
Download 를 설치한다.

클라이언트 준비는 이걸로 끝.

그다음 서버쪽 설치인데

npm install -g autosave
하고 
$ autosave 
를 실행하면 끝

이러면 일단 file:// 형식에 대해선 오케이.

그런데 실제 웹사이트일을 하고 있을땐 file:// 타입을 사용하는 경우는 드물다.

그럴땐 설정 파일을 만들고
https://github.com/NV/chrome-devtools-autosave/issues/7#issuecomment-3182946
처럼 적용하면 된다.

내 경우는 http://localhost/~유저명/ 형식을 사용하고 OSX 웹공유 기능을 쓰고 있어서
routes.js
exports.routes = [{
    from: /^http:\/\/localhost\/~([^\/]*)/,
    to: '/Users/$1/Sites/'
}];

이렇게 설정하고
autosave --config routes.js
해서 쓴다.
chrome://settings/extensions 에 들어가서
DevTools autosave1.0
를 찾아서 옵션 찍고 Resource 를 ^file:// 에서 ^http://localhost/
따위로 바꿔준다.

그나저나 onResourceContentCommitted 라는 이벤트가 있구나. 크롬 이 무서운 놈들;;




jQuery vs Native 잔대가리

http://sharedfil.es/js-48hIfQE4XK.html 내용.
맘에 들어서 퍼옴.
포인트는 querySelector 같은게 IE 에서 되면 뭐다러 jQuery selector를 쓰냐
forEach가 먹으면 뭐하러 귀찮게 $.each를 쓰냐.
이게 다 IE 때문이다. 그래서 jQuery 를 쓴다.
jQueryJavaScript
$(document).ready(function() {  // code…});
document.addEventListener("DOMContentLoaded", function() {  // code…});
var divs = $("div");
var divs = document.querySelectorAll("div");
var newDiv = $("<div/>");
var newDiv = document.createElement("div");
newDiv.addClass("foo");
newDiv.classList.add("foo");
newDiv.toggleClass("foo");
newDiv.classList.toggle("foo");
$("a").click(function() {  // code…})
[].forEach.call(document.querySelectorAll("a"), function(el) {  el.addEventListener("click", function() {    // code…  });});
$("body").append($("<p/>"));
document.body.appendChild(document.createElement("p"));
$("img").filter(":first").attr("alt", "My image");
document.querySelector("img").setAttribute("alt", "My image");
var parent = $("#about").parent();
var parent = document.getElementById("about").parentNode;
var clonedElement = $("#about").clone();
var clonedElement = document.getElementById("about").cloneNode(true);
$("#wrap").empty();
var wrap = document.getElementById("wrap");while(wrap.firstChild) wrap.removeChild(wrap.firstChild);
if($("#wrap").is(":empty"))
if(!document.getElementById("wrap").hasChildNodes())
var nextElement = $("#wrap").next();
var nextElement = document.getElementById("wrap").nextSibling;

글로 배우는 Dubstep 수련

일렉트로닉 음악엔 일단 크게 두개의 카테고리가 있다.

Broken Beat 계열과
Steady Beat 계열.
이름만 들어도 눈치 딱 까야함.

이걸 흑인음악/백인음악 이분법으로 나누는 쪽도 있는데 뭐 좋으실대로.

Steady Beat은 말그대로 매 마디마다 4분음으로 킥을 치는 패턴
쿵.쿵.쿵.쿵/쿵.쿵.쿵.쿵  감사 합나 다. 감사 합니 다 영어 로떙 큐 
House, Trance, Techno, 그리고 좀 느리게 하면 Dub 등등이 있겠다.

Broken Beat는 이 법칙을 따르지 않는 다고 보면 된다.
킥을 세번은 치지만 네번 치진 않고 불규칙하게 친다.

쿵 쿵 딱 따쿵 딱 / 쿵 쿵 딱 따카 딱.따 쿵 - 이런 비트라고 보면 된다.

여기에 한가지 속성이 더 들어가는데
그것은 바로 Tempo.

만일 90bpm 아래의 느린 Broken beat 계열이라면
Hip hop, Trip hop, DanceHall 류가 있다.

Hip hop은 쿵 쿵 딱 따쿵 딱 | 쿵 쿵 딱 치카치카쿵 딱
DanceHall은 붐스 붐스 칵 붐스 붐스 칵
정도 되겠다.

만일 같은 비트로 130bpm 정도 속도를 높이면
Breaks, Breakbeat 정도가 되겠다. Hip hop x 1.5 정도면 무난

여기서 더 빨리 180bpm 정도 높이면
Drum and Bass 가 된다. Hip hop x 2 정도

Breakbeat 를 좀 더 자세히 살펴보자
BPM은 130~140정도 (90bpm의 Broken Beat류에 x 1.5)
1. 시퀀사나 드럼머신류를 사용
2. 당연히 퀀타이즈한다. 즉 칼박
3. 16분 음표 단위
4. 퀀타이즈 하지만 셔플을 사용하기도 한다.

BreakBeat 중 셔플을 사용하여 재즈같은 느낌을 부각하는 대표적인 장르로는 TwoStep을 들 수 있다.
마치 R&B를 BreakBeat 속도로 플레이 하는 것이다.

정리하면 
Hip Hop x 1.5 = BreakBeat
R&B x 1.5 = TwoStep
이라고 보면 된다.

R&B 나 TwoStep 을 축으로 사운드 소스를 바꾸면 DubStep 이 된다.
DubStep 은 BreakBeat 를 두배로 늘려주면 되는데

쿵 쿵 딱 따쿵 딱  ---> 쿵스 쿵스 딱 칫칫칫 따쿵슷스 딱 닥 닷 닥

같은 패턴이 되겠다.
보통 많이 사용하는 패턴으로는 딜레이를 사용해서

쿵궁웅웅딱칫칫칫짓치쿵웅딱닥닥닥

하거나 Wobble bass 를 사용해서

쿵와와왕딱치키치키칰쿵왕와오아ㅗ아ㅗㅇ 

하기도 한다.

http://www.youtube.com/watch?v=h-XITe_SzCM
1분 8초부터 들어보자.

끝으로 3줄 요약.
1. 느리고 더러운 Hiphop
2. 템포는 Breakbeat
3. BreakBeatx2 패턴으로 무거운 느낌.

한줄요약
1. 덥스텝은 통상 힙합인데 템포 두배 패턴 두배

callback pattern - queue 와 recursion 을 이용한 직렬화 버닝!!

지금은 이미 async 의 시대라고 해도 좋을만큼 비동기가 대세지만
게으른 올드비들은 자기가 모른다는 이유만으로 별의별 이유를 들어 까대거나 
배우는 걸 회피하고자 해서
패턴별 파해법이 시급한 실정이다.
생각나는 대로 하나씩 올려볼셈.
대표적인게 다음과 같은 오징어 외계인 패턴이라고 할 수 있는데

var doQuery=function(query,callback) {
  console.log(query); // do something
  callback();
};

doQuery('insert a', function() {
  doQuery('insert b', function() {
    doQuery('insert c', function() {
      console.log('all done'); // end of transaction
    });
  });
});

실제로 database 를 다룰때 많이 부딪히는 패턴이다.
transactioin 에 올려놓고 한방에 commit 하면 되지 않냐라고 할꺼라면 나가줘(...)

(function serialize(query) {
  if(query.length) {
    doQuery(query.shift(0), function(result) {
      serialize(query);
    });
  } else {
    console.log('all done'); // end of transaction
  }
})(['insert a', 'insert b', 'insert c']);

파라메터를 큐에 넣고 하나씩 shift 로 빼면서 재귀.
꼭 javascript 가 아니라도 일반적으로 재귀와 배열이 가능한 어떤 언어라도 마찬가지.
더 좋은 패턴이 있으면 또 써볼란다.


1 2 3 4 5 6 7 8 9 10 다음