'Technical Stubs'에 해당되는 글 49건

  1. 2014.11.12 JavaScript Quiz
  2. 2014.11.12 JavaScript 비교 연산에 대한 정리
  3. 2014.10.14 Spotlight에서 검색된 파일을 파인더에서 보기
  4. 2014.10.14 contextify 설치 시 node-gyp rebuild error 발생
  5. 2014.09.18 함수 호출 문법에서 missing arguments labels가 나올 때
  6. 2014.09.03 티스토리 블로그에 소스코드 넣기 #1 Syntax Highlighter
  7. 2014.08.27 IBM IoT Cloud Raspberry Pi Node JS를 이용한 Test
  8. 2014.08.27 Raspberry Pi에 Node-JS 설치하기 (2)
  9. 2014.08.26 라즈베리 파이 모니터 없이 쓰기
  10. 2014.08.12 Swift - Closures
2014.11.12 23:27

JavaScript Quiz


Quiz 1
var name = "javarouka";
var introduce = function() {
    var intro = "My name is ";
    if(!name) {
        var name = "unknown"
    }
    return intro += name;
}
document.write(introduce());
  • "My name is undefined"
  • "My name is null"
  • "My name is javarouka"
  • "My name is unknown”
    : function scope에 선언된 variable name은 introduce 함수 실행 시 hoisting 되어 undefined로 초기화 된 상태가 되므로 if(!name) 구문 내부로 진입이 가능하게 된다.
    또한, local variable로 선언된 name이 “unknown”값으로 할당을 받으면  global scope에 선언된 name은 shadow 되므로 “javarouka”가 아닌 “unknown”이 최종 값이 된다


Quiz 2

document.write(myName() + " / ");
var myName = "javarouka";
function myName() {
    return "rouxrouka";
}
delete myName;
document.write(myName);
  • 실행 오류
  • "rouxrouka / javarouka”
    :  myName과 같은 Named Function은 script loading과 동시에 AST에 구성되어 Hoisting과 더불어 선언이 완료된다. 따라서, 초기 myName을 호출해도 정상 동작하게 되어 “rouxrouka”값을 얻게 된다.
    이후 var로 myName을 재선언 하게 되면 myName은 함수가 아닌 문자열 object로 인식하게 된다. 이후 delete를 호출하여 myName을 삭제 하려하고 있으나 var로 선언된 myName은 삭제 불가 속성이므로 삭제되지 않고 “javarouka” 값을 유지하게 된다.
  • "undefined / javarouka"
  • "undefined / undefined"


Quiz 3

(function(doc) {
    document.write(new doc() === doc());
    document.write(new doc() === document);
    document.write(doc() === document);
})
(function arg() {
    return document;
})
  • 실행 오류
  • "falsefalsefalse"
  • "falsefalsetrue"
  • "falsetruetrue"
  • “truetruetrue” 
    : 위의 구조는 IIFE 방식으로 arg() 함수가 doc으로 넘겨지는 구조를 가진다. JavaScript에서는 new 키워드를 하여 함수를 constructor로 인식 object를 생성 할 수 있다.
    new operation을 실행하면 먼저 메모리 공간에 empty object를 생성하고 이 object의 constructor property를 constructor 함수의 저장 영역을 가리키게 한 후 constructor 함수를 호출하면서 context를 새로 생성된 object로 bind하게 된다. constructor 함수의 실행이 종료되면 생성된 object (this) 를 return하게 되는데, 만약 constructor 함수가 임의의 object를 명시적으로 return 하는 경우 새로 생성한 object 대신 명시된 object를 return 하게 된다.

    JavaScript의 이러한 특징에 의해 예제의 new doc()과 doc()을 실행하여 얻는 object는 document로 identical 조건을 만족한다. 만약, return값이 object가 아닌 string과 같은 literal일 경우는 해당되지 않으므로 결과 값은 falsefalsetrue가 된다.

    참고로, 이러한 constructor 함수의 특징을 이용하여 private function 을 구현 하기도 한다.
  • "truefalsefalse"
  • "truetruefalse"


Quiz 4

function setter(aryUnits) {
    for(var i=0; i < aryUnits.length; i++) {
        var id = i + 1;
        aryUnits[i] = new Object();
        aryUnits[i].getId = function() {
            return id;
        }
    }
}
var ary = new Array(5);
setter(ary);
document.write(ary[3].getId());
  • 실행 오류
  • undefined
  • 4
  • 5
    : setter 함수의 for loop 에서 var 로 선언된 id는 hoisting되어 setter 함수의 진입 시 undefined 값을 가지게 된다.
    aryUnits element에 할당하는 getId 정보는 단지 Function Literal로 for loop을 통해 함수 자체가 실행되는 것이 아니며, 이후 getId()를 호출 하는 시점에 scope이 형성된다. 이 함수의 내부에서 사용되는 id는 setter 함수 scope에 bind된 id로서 reference만 유지하게 된다.

    이 예제에서는 for loop이 진행되면서 id는 1에서 5까지 변하게 되지만 array별로 할당받은 getId 함수를 호출할 때는 결국 같은 object인 id를 참고하게 된다. 따라서, id의 최종 id 값인 5를 얻게 된다.

    각 array element 별로 값을 얻기 위해선 id를 얻는 function을 closure로 생성하여 scope을 확보 후 넘겨 주어야 한다.
    getId = (function(id) {
        return function() {
            return id;
        }
    })(id);


Quiz 5

function args() {
    return (typeof arguments) && (arguments instanceof Array);
}
document.write(args());
  • 실행 오류
  • "object"
  • true
  • false
    : typeof arguments는 object이나 arguments는 Array Like Object이므로 Array Instance가 아니다


Quiz 6

var c;
document.write(typeof typeof c);
  • "undefined"
  • "object"
  • 실행 오류
  • “string” 
    : typeof c는 “object”라는 string literal 값을 가지므로 typeof “object”는 “string”이 된다.


Quiz 7

var privacy = {
    secret: "I did not study last night.",
    getSecret : function() {
        return this.secret;
    }
};
var what = privacy.getSecret;
document.write(what());
  • 실행 오류
  • "I did not study last night."
  • undefined
    : privacy.getSecret 함수를 global variable인 what에 할당을 한 경우이므로, 실제 함수가 실행 될 때 this는 what이 속해 있는 window object를 context로 인식하게 된다. window에는 secret이 정의 되어 있지 않았으므로 undefined 값을 얻게 된다. 만약, var secret = “100”으로 global variable을 설정한 경우라면 당연히 return 되는 값은 “100”을 얻게 된다. 또한, what()이 아닌 privacy.getSecret()을 실행하면 this는 privacy object가 되므로 “I did ~~ night.” 값을 얻게 된다.

    JavaScript의 Function에서 기본적으로 제공하는 기능 중에 call이나 apply의 경우 이러한 context를 다르게 줄 수 있는 기능을 제공한다. 예를 들어 what.call(privacy)라고 호출 했다면, 비록 what이라는 함수를 실행한다해도 context가 privacy이므로 “I did ~~ night”를 호출하게 된다.
  • "function() { return this.secret; }"


Quiz 8

function func1( ) { return func1; }
if(new func1() === func1()) {
    document.write("same!");
}
else {
    document.write("different!");
}
  • 실행 오류
  • "same!”
    : 앞서 Quiz3번과 유사한 문제로 초기 AST(Abstract Syntax Tree)구성 시 f
    unc1이 Named Function으로 등록된다. 그 상태에서 new func1()을 실행하면 return 값으로 func1 함수 object을 return하고 func1()을 실행 할 때도 마찬가지로 동일한 func1을 얻게 된다.
  • "different!"


Quiz 9

(function(){
    Object.prototype.scope = "prototype";
    (function(f) {
        var scope = "local";
        alert(f());
    })(function checkScope() { return scope; });
})();
  • 실행 오류
  • "local"
  • “prototype” 
    : Object.prototype.scope에 값을 assign하는 경우 모든 Object에 scope이라는 property key를 갖게 된다. IIFE 함수의 argument로서 넘겨받은 checkScope 함수를 실행하면 IIFE의 context에 bind되므로 scope == window.scope을 의미하게 된다. 따라서, global로 scope이 정의되어 있지 않아 undefined가 될 것 같은 모습이지만, 앞서 Object의 prototype에 scope이라는 property를 추가 해 주었기 때문에 prototype chain을 따라 그 값은 “prototype”이 된다. 

     만약,
    var scope 대신 scope = “local” 또는 this.scope = “local” 이라고 선언 했다면, 명시적으로 window.scope에 값이 할당된 것이므로 prototype 값이 아닌 window object에 할당된 메모리 영역을 접근하여 “local” 값을 얻게 된다.
  • "undefined"


Quiz 10

var strZero = "0";
var numZero = 0;
var notNumer = NaN;
var strEmpty = '';
var tab = '\t';
var undef;
var nll = null;
if(strZero == true) {
    document.write("1");
}
if(notNumer == false) {
    document.write("2");
}
if(undef == nll) {
    document.write("3");
}
if(tab == 0) {
    document.write("4");
}
if(tab == true) {
    document.write("5");
}
if(strEmpty == numZero) {
    document.write("6");
}
if(false == 'false') {
    document.write("7");
}
if(strEmpty == false) {
    document.write("8");
}
  • ""
  • "78"
  • “3468” :
    1: 문자열 “0”과 boolean의 비교 이므로 strZero는 0 true은 1로 비교하므로 false
    2: NaN은 어떤 값과 비교해도 false
    3: undefined와 null은 abstract equality comparison에서 같은 것으로 인식하므로 true
    4: 문자열 number 비교로 문자열 tab을 숫자 0으로 변환되므로 true

    5: 문자열 boolean 비교로 문자열 tab을 숫자 0으로 변환되고, true는 1로 변환되므로 false
    6: 문자열 number 비교로 strEmpty는 숫자 0으로 변환되므로 true
    7: 문자열 boolean 비교로 false는 +0으로 변환되고 ‘false’는 numeric literal이 아니므로 변환되지 않으므로 false
    8: 문자열 boolean 비교로 false는 +0으로 변환되고 strEmpty는 숫자 0으로 변환되므로 true

    JavaScript 비교 연산에 대한 정리는 JavaScript Equality Operator 에 대한 글을 참고하기 바란다.
  • "34568"
  • "2567"


'Technical Stubs > JavaScript' 카테고리의 다른 글

JavaScript Quiz  (0) 2014.11.12
JavaScript 비교 연산에 대한 정리  (0) 2014.11.12
Trackback 0 Comment 0
2014.11.12 23:04

JavaScript 비교 연산에 대한 정리

JavaScript 비교 연산에 대한 정리

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators 에 정리된 글을 참고하였음.


요약 정보

  • 글자에 대한 시퀀스, 길이 및 각 위치에 대해 동일한 문자가 있는 경우 같은 문자열로 본다.
  • 숫자의 값이 동일할 때 두 숫자는 같은 것으로 본다.
    NaN (Not a Number)는 NaN을 포함하여 어떤 것과도 같지 않다.
    양의 0과 음의 0은 서로 같은 것으로 본다. 
  • 두 개의 boolean 대상이 둘 다 true 거나 false인 경우만 서로 같은 것으로 본다
  • 두 개의 구분되는 object는 strict 또는 abstract 비교 시 절대 같지 않아야 한다
  • Object를 비교하는 expression은 서로 참고하는 object가 같은 경우에만 true이다.
  • Null과 Undefined 타입은 strict 비교시는 Null은 Null과 Undefined는 Undefined 만 서로 같을 수 있으나,
    abstract 비교시에는 Null과 Undefined는 서로 같을 수 있다. 

Equality (==)

  • equality operator는 서로의 타입이 다를 경우 타입을 자동으로 변환 후 strict 비교를 한다
  • 대상이 number 또는 boolean 타입 중 하나일 경우 모든 대상을 number 로 변환 후 비교한다. (단, 변환이 가능 할 경우에만)
  • 대상이 string 일 경우라면 숫자형로 변환이 가능할 경우 number로 변환 후 비교한다.
  • 대상이 둘 다 object 라면 각 object가 참고하는 내부 메모리 공간이 동일한지 비교한다.

Identity (===)

  • identity operator는 타입과 상관 없이 strict 비교를 한다.

Comparison Algorithm


Abstract Equality Comparison에서 Type 변경이 발생하는 경우 다음과 같은 규칙을 따른다.

  • number와 string을 비교시, string은 number 값으로 변환된다.
    JavaScript는 string numeric literal을 Number 타입 값으로 변환을 시도하게 된다.
    먼저, 수학적인 값이 string numeric literal 로 부터 얻어지게 되고, Number 값에 가장 가까운 값으로 반올림 또는 버림된다.
  • 만약 대상 중 하나가 Boolean 인 경우, 이 Boolean이 true 몇 1 false면 +0 값으로 변환된다.
  • 만약 object가 number나 string으로 비교되는 경우, JavaScript는 object의 기본 값을 return 하는지 시도하게 된다. object의 valueOf나 toString 메소드를 이용해서 Number 값이나 String과 같은 primitive 값으로 변환을 시도를 한다. 만약, object 변환에 실패하면 runtime error를 생성한다.
  • Object가 primitive 값으로 변환되는 경우는 그 비교 대상이 오직 primitive 타입일 경우에만 변환되며, 대상이 둘 다 object 일 경우는 각각의 object가 같은 memory를 참고하는지에 대한 비교만 하게된다.

Abstract Equality Comparison 예제

  • 1 == ‘1’
    true : number - string 비교이며 string ‘1’이 number 1로 변환 후 비교
  • 1 == true
    true : boolean 비교이므로 true는 1로 변환 후 비교
  • ‘1’ == true
    true : boolean 비교이므로 true는 1로 변환되며 string ‘1’은 number 1로 변환되어 비교
  • ‘2’ == true
    false : boolean 비교이므로 true는 1로 변환되나 string ‘2’는 number 2로 변환되어 비교 
  • new Number(0) && new Boolean(false)
    true : new Number(0)는 number 0에 대한 object이므로 number 0과는 다름.
    Equality 를 비교를 위해서는 다음과 같이 풀어서 사용해야 함
    new Number(0) == true && new Boolean(false) == true
  • ‘ ‘ == 0
    true : number - string 비교이므로 string ‘ ‘이 number 0으로 변환 후 비교
  • NaN == NaN
    false : NaN은 그 어떤 것과 비교해도 false
  • null == undefined
    true : null은 undefined와 비교 시 같은 것으로 취급된다.
  • null == 0
    false : null은 undefined나 null과의 비교에서만 true가 된다.

if 문에서 true 조건

  • if statement condition은 해당 값이 0, false, null, undefined, NaN이 아닌 경우 true로 인식한다.


'Technical Stubs > JavaScript' 카테고리의 다른 글

JavaScript Quiz  (0) 2014.11.12
JavaScript 비교 연산에 대한 정리  (0) 2014.11.12
Trackback 0 Comment 0
2014.10.14 23:53

Spotlight에서 검색된 파일을 파인더에서 보기

OSX는 내장 검색 엔진으로 Spotlight라는 것을 지원한다.


오른쪽 구석에 이렇게 생긴  돋보기 아이콘을 선택하거나 단축키를 누르면 다음과 같이 Spotlight 화면이 나타난다.



원하는 키워드로 검색하면 파일 이름이나 내용을 파악한 Spotlight가 적당한 기준에 맞춰 파일을 나열한다.



사실 파일이 몇 개 없는 경우나 폴더형태로 찾기 쉽게 저장해 놓는 경우가 아니라면 원하는 파일을 찾기가 꽤 귀찮을 수 있다. 이럴 때 Spotlight을 이용하면 미리 index 되어 있는 정보를 기반으로 내용 검색까지 되므로 빠른 검색이 가능하다.


그런데 그렇게 검색된 파일들이 이름이 똑같은데 다른 곳에 있다던지 아니면 정확하게 해당 파일이 뭔지 어디에 있는지 궁금한 경우가 있는데 이럴 때는 다음과 같이 원하는 파일에 마우스 커서를 놓고 Command + Enter 키를 누르면 파인더에서 해당 파일을 선택해서 보여주므로 이 기능을 이용하면 된다.






Trackback 0 Comment 0
2014.10.14 15:30

contextify 설치 시 node-gyp rebuild error 발생

npm을 이용하여 contextify package를 설치하는 경우 오류가 발생하면서 정상 설치가 안되는 경우가 있다




좀 더 자세한 오류 확인을 위해 npm-debug.log 파일을 열어 봤더니



contextify 를 설치하다가 node-gyp rebuild가 안된다면서 contextify 개발자한테 연락하라는 메시지도 볼 수 있다.


에러 메시지를 자세히 확인해 보면 node-gyp rebuild를 실행 했더니 Exit status 1 이라고 표시되어 있다.

node-gyp 파일이 없어 그냥 에러가 난 것으로 볼수도 있으므로 확인을 해 보니 node-gyp가 설치되어 있지 않아 발생 했었던 경우였다.


node-gyp는 node JS에서 native build를 위한 addon tool로서 OSX의 경우 Xcode를 이용하여 native code를 빌드한다. -g option을 주어 global 로 설치되어야 하므로 다음과 같이 설치한다.



이렇게 node-gyp를 설치했음에도 불구하고 에러가 나는 경우가 있는데 이 때도 마찬가지로 에러 메시지를 다시 확인 해 봐야 한다. 나의 경우는 Xcode에 대한 path가 맞지 않아 다음과 같은 오류 메시지가 출력되었다




이 때는 xcode-select 명령을 이용하여 path 정보를 reset 해 주면 자동으로 Xcode의 기본 경로를 인식한다.




이제 다시 contextify를 설치 해보면 정상 설치가 되는 것을 확인 할 수 있다.



'Technical Stubs > Node.js' 카테고리의 다른 글

contextify 설치 시 node-gyp rebuild error 발생  (0) 2014.10.14
Trackback 0 Comment 0
2014.09.18 16:48

함수 호출 문법에서 missing arguments labels가 나올 때

Swift Programming을 하다보면 XCode의 문법 자동 확인 기능을 이용하게 된다. 특히, 함수 호출에 있어서는 더욱 많이 사용하게 되는데 간혹 다음과 같은 메시지를 보여주면서 문법이 잘못되었다는 표시가 되는 경우가 있다.


[그림] Missing argument labels



Xcode에서 제공하는 오류 자동 수정 기능으로, greet 함수를 호출 할 때 day라는 라벨을 붙지지 않고 있는게 이슈가 되므로 day:를 붙여 넣으라는 내용이다. 클릭하면 자동으로 day: 를 붙여 준다. 


[그림] 수정된 greet 함수 호출



그런데, 이 greet이라는 함수를 선언한 곳을 보면 다음과 같다.


[그림] greet 함수 선언



이 함수는 A Swift Tour에 나오는 예제인데, 함수 호출 시 별도 argument name 없이 사용할 수 있음을 보여준다.


[그림] Functions and Closures



이 문서에는 argument label을 붙이지 않은 그대로 greet("Bob", "Tuesday")와 같이 호출하고 있다. 그런데, 왜 XCode에서는 문법이 잘못 되었다고 표시가 되었을까?


Swift Tour의 예제가 Playground에서만 동작하고 App을 만들 때 사용하는 Project Code에서는 안되는 걸까?

아니면 argument label을 호출할 때 첫 번째 argument는 생략해도 되는 걸 보면 기존 Objective-C 코드를 재활용할 때는 못쓰는걸까?



사실 여기에는 함수(Function)에 대한 함정(?)이 숨어 있는데 앞서 호출하는 greet은 엄밀하게 이야기하면 함수(function)가 아닌 메소드(method)이다.


Swift Language Spec 문서에 의하면 메소드는 type이 관여된 것으로 함수지만, class에 속해 있는 경우 parameter의 노출에 대한 기본 정의가 여느 함수 정의에서와 달리 다르다고 한다.


Local and External Parameter Names for Methods

Function parameters can have both a local name (for use within the function’s body) and an external name (for use when calling the function), as described in External Parameter NamesThe same is true for method parameters, because methods are just functions that are associated with a type. However, the default behavior of local names and external names is different for functions and methods. 


...


Specifically, Swift gives the first parameter name in a method a local parameter name by default, and gives the second and subsequent parameter names both local and external parameter names by default.


[출처] Apple Swift Programming Language - Methods


스펙을 더 자세히 들여다 보면, 메소드는 첫번째 local parameter로 그리고 두 번째 부터는 local과 external 둘다 제공하는것을 기본으로 한다. 따라서, 앞서 greet 함수 아니 greet 메소드는 다음과 같이 첫 번째 parameter인 name은 local로 그리고 두 번째 parameter인 day는 #을 추가하여 external로 사용될 수 있는 모습이 된다.

[그림] greet method



그렇다면, 메소드를 여느 함수와 같이 external로 제공하지 않으려면 어떻게 할까? greet 함수의 경우에서처럼 day: 라는 별도 label을 없이 호출하고 싶은 경우 말이다.


Swift 함수 spec에서는 external parameter를 명시적으로 제공하고 싶지 않는 경우는 underscore 문자인 '_' 를 앞에 붙여서 선언한다. 따라서, method에서도 마찬가지로 명시적으로 '_'를 day 앞에 추가하면 argument 이름없이 호출이 가능하다.



[그림] Underscore 문자 '_' 를 사용한 external parameter 감추기


정리를 하자면 parameter 이름 노출에 있어서 함수는 기본 동작으로 underscore '_' 로 인식하고 메소드는 기본 동작으로 sharp '#'으로 인식한다.


여담으로 그냥 Playground에서도 일반적인 함수가 아닌 Class를 생성 후 method로 호출하면 Project에서와 동일한 동작을 하며, Class를 선언하는 Swift 파일에서도 Class 선언부 바깥에 함수를 선언하는 경우는 method가 아닌 함수로 선언되므로 사용에 주의 하기 바라니다.

'Technical Stubs > Apple Swift' 카테고리의 다른 글

함수 호출 문법에서 missing arguments labels가 나올 때  (0) 2014.09.18
Swift - Closures  (0) 2014.08.12
Swift - Function  (0) 2014.08.11
Swift - Control Flow  (0) 2014.08.11
Swift - Data Type #Collections  (0) 2014.08.08
Swift - String  (0) 2014.08.08
Trackback 0 Comment 0
2014.09.03 10:43

티스토리 블로그에 소스코드 넣기 #1 Syntax Highlighter

티스토리 블로그를 사용하다 보면 소스 코드를 올려야 할 경우가 종종 발생한다. 코드야 첨부 파일로 업로드 하는 경우도 있지만, 블로그 내용에 포함 시키려면 어지간하지 귀찮아진다.

간략하게는 Courier 계열의 Font만 사용하기도 하지만 이쁘게 보이지도 않고, 결국에는 별도 Editor 화면을 캡쳐해서 첨부하기도 하는데 그것도 이미지로 첨부하는 거라 꽤 귀찮은 일이다.


다른 블로그에서는 어떻게 제공하는가 봤더니 꽤 다양한 방법을 제시하고 있었고 그 중 다음 두 가지로 압축되었다.


1. HightlightJS - https://highlightjs.org

- 장점 : 깔끔한 UI, CDN 배포, Apple Swift 지원

- 단점 : Line Number 표시하려면 별도 Branch에서 받아야 함


2. Syntax Highlighter - http://alexgorbatchev.com/SyntaxHighlighter

- 장점 : Line Number 표시, 다양한 설정

- 단점 : 기본 Theme 구림, CDN 없음 (홈페이지에서 배포하고 있으나 PoC용임)


일단, 사용법은 둘 다 비슷하지만, 일단은 Syntax Highligter를 먼저 선택해 보았다.


<link href="http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css" rel="stylesheet" type="text/css" />

<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js" type="text/javascript"></script>

<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shAutoloader.js" type="text/javascript"></script>


그리고 body의 제일 마지막 부분에 다음과 같은 코드를 추가한다.


<script type="text/javascript">

SyntaxHighlighter.defaults.toolbar = false;

SyntaxHighlighter.all()

</script>


다음은 필요한 Hightlight를 할 Brush를 추가해야하는데 현재 버젼 (3.0.83)에서 지원하는 Brush 종류는 꽤 다양하다. 일단은 JavaScript만 먼저 테스트를 해 보자.


JavaScript에 대한 Brush는 shBrushJScript.js 이므로 다음과 같이 추가한다.

<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js" type="text/javascript"></script> 


다른 언어에 대한 Brush는 다음 링크를 참고 한다.


http://alexgorbatchev.com/SyntaxHighlighter/manual/brushes/


Sample Code는 <pre><code>로 담으면 자동으로 언어를 인식한다. 만약 제대로 동작하지 않는다면 <code> 태그에 class attribute로 해당 코드의 언어 이름을 넣어준다. 예를 들면 다음과 같다.


<pre class="brush: js;">

var a = 100;

function test() {

   return 'Hello, World'

}

</pre>


그러면 아래와 같이 라인 번호와 함께 나온다.

참고로, 3.0.83 버젼에는 swift에 대한 Brush가 빠져 있다. 


다음 글을 참고하여 Brush를 하나 마련해 보자.


http://wordpress.org/plugins/syntaxhighlighter-evolved-swift-brush/


기본적인 작성 방법은 다른 Brush 처럼 해당 언어에서 사용하는 주석이나 keyword에 대한 부분을 별도로 묶고 해당 부분을 어떤 색으로 보여줄 지에 대한 구성으로 되어 있다. Swift의 경우 Language Spec에 각종 정보들이 들어 있으며 다음과 같이 Brush에서 사용할 keyword 들을 정리했다.


1. datatypes

Character Bool Double Float

Int Int8 Int16 Int32 Int64

UInt UInt8 UInt16 UInt32 UInt64

AnyObject String Void


2. keywords

IBAction IBOutlet true false nil

super self Self copy

as break case class

continue convenience dynamic final private

default get set willSet didSet

else enum if is in infix internal for fallthrough func import inout

let lazy mutable

naked namespace new noinline noreturn nothrow NSCopying NSManaged mutating objc override operator optional prefix protocol

private public required return

static struct switch

T typealias UnsafePointer var

unowned weak where while


3. functions

advance enumerate find filter join

min map max print println sizeof sort init


shBrushSwift.js

Trackback 0 Comment 0
2014.08.27 04:55

IBM IoT Cloud Raspberry Pi Node JS를 이용한 Test

IBM IoT Cloud 는 Device recipe라는 형태의 일종의 패키지를 제공하여 다양한 종류/환경의 단말이 IBM IoT Service를 이용하도록 하고 있다.


물론 라즈베리파이에 대한 Device recipe도 있으며 다음 ( https://developer.ibm.com/iot/recipes/raspberry-pi )에서 좀 더 자세한 기능을 확인 해 볼 수 있다.


IBM에서 공식적으로 제공하는 라즈베리 파이용 Device Recipe 는 Rasbian용 debian binary package 형태로 되어 있기에 Cross Compiler를 이용한 Build 환경을 갖춰야만 IBM IoT 통신 프로토콜(MQTT)을 사용하는 Client App를 개발해야 하는데, Intel Galileo용 Device recipe는 Node.js로 구성되어 있어 이를 활용해 보고자 한다.


0. 사전 준비

좀 더 시간이 지나면 Node.js용으로 필요한 부분만 사용 할 수 있도록 정리하겠지만

일단, Node.js용으로 IBM IoT 환경을 구성한다 하더라도 라즈베리 파이용 device recipe 가 선행되어야 한다.


특히 IBM PaaS Platform인 Bluemix 등록 및 IoT Foundation 환경 구성을 비롯한 단말 정보 등록 과정들은 반드시 사전에 진행되어야 한다.



1. Node JS 설치

라즈베리 파이에 Node JS는 [ Raspberry Pi에 Node-JS 설치하기 ]를 참고


2. Node JS용 Quick Start 가져오기

앞서 이야기 했듯이 Intel Galileo용으로 제공하는 Device Recipe https://developer.ibm.com/iot/recipes/intel-galileo )인데 Node.js 실행환경이라면 사용에 별 문제가 없다.


다만, Intel Galileo의 모든 Quick Start (ibm-iot-quickstart.zip)를 다 가져올 필요는 없고 우리가 필요한 JavaScript 파일과 json 파일만 가져오도록 한다.


라즈베리용 Device Recipe에서 생성한 device.cfg와 같은 폴더에 다음과 같이 파일을 다운로드 받는다.


sudo wget -O /etc/iotsample-raspberrypi/ibm-iot-quickstart.js https://github.com/ibm-messaging/iot-galileo/raw/master/samples/nodejs/package.json/ibm-iot.js

sudo wget -O /etc/iotsample-raspberrypi/package.json https://github.com/ibm-messaging/iot-galileo/raw/master/samples/nodejs/package.json



그리고 다운로드 받은 ibm-iot.js 를 보면 deviceType이 default로 iotsample-galilieo로 되어 있다. 

이 값은 device.cfg에 정의되어 있는 경우 override 되긴 하지만 라즈베리를 위한 기본 값으로 iotsample-raspberrypi로 변경하여 저장한다.


그리고 node ibm-iot.js로 JavaScript를 실행 해 보면 MQTT 모듈이 설치되어 있지 않아 오류를 발생하게 된다.


<그림>


Quick Start에 필요한 node module은 package.json에 정의되어 있으므로 아래와 같이 npm을 이용한 node module을 설치한다.


sudo npm install


자 이제 다음과 같이 quick start를 실행 해 보면 binary로 실행되는 것처럼 메시지가 정상 동작하는 것을 확인 할 수 있다.


node ibm-iot.js -v

Trackback 0 Comment 0
2014.08.27 04:10

Raspberry Pi에 Node-JS 설치하기

라즈베리 파이에 리눅스 계열인 RASPBIAN을 설치한 경우 이를 위한 Node JS가 준비되어 있으므로 다음 몇 가지 단계를 거치면 손쉽게 Node JS 를 사용할 수 있다.

1. RASPBIAN Package 정보 업데이트


RASPBIAN은 Debian 계열의 패키지 관리 정보를 사용한다. 다음과 같이 apt-get 명령을 이용하여 해당 정보를 업데이트를 한다.

그림 <sudo apt-get upgrade>


그림 <sudo apt-get update>


2. 라즈베리파이용 NodeJS 설치


Package 정보를 업데이트 했다면 node-arm 프로젝트 홈페이지 (http://node-arm.herokuapp.com)로부터 NodeJS deb 패키지를 받아 설치한다. 현재 (2014-8-27) NodeJS 최신 공식 버전인 v0.10.31, 30, 29를 제공하므로 필요에 따라 선택한다.


다음 명령어를 이용하면 최신 버젼의 NodeJS 설치 파일을 받을 수 있다.


sudo wget http://node-arm.herokuapp.com/node_latest_armhf.deb


그리고 dpkg를 이용하여 nodejs를 설치한다.


$ sudo dpkg -i node_lasted_armhf.deb 



참고로 NodeJS 홈페이지에서도 라즈베리 파이용 패키지를 제공하고 있으나 v0.10.29 부터 v0.10.31까지는 배포되지 않고 있다.


v0.10.28 을 다음 명령어로 다운로드한다.


$ sudo wget http://nodejs.org/dist/v0.10.28/node-v0.10.28-linux-arm-pi.tar.gz


그리고 파일의 압축을 해제한다.

tar -xzvf node-v0.10.28-linux-arm-pi.tar.gz


다운로드 받은 node를 실행해 보면 현재 버젼을 확인해 볼 수 있다.

node-v0.10.28-linux-arm-pi/bin/node -v


데비안 패키지와 달리 실행 파일만 설치된 것이므로 환경 설정을 해 주어야 한다.


home 디렉토리 (/home/pi) 의 .bash_profile에 다음과 같이 NODE_JS_HOME을 설정한다.


NODE_JS_HOME=/home/pi/node-v0.10.28-linux-arm-pi

PATH=$PATH:$NODE_JS_HOME/bin



Trackback 0 Comment 2
2014.08.26 13:53

라즈베리 파이 모니터 없이 쓰기

라즈베리 파이는 학교에서 기초 컴퓨터 과학 교육 증진을 위해 만든 단일 보드 컴퓨터다.

PC와 달리 ARM 기반의 프로세서를 사용하지만 HDMI와 USB 그리고 인터넷을 위한 커넥터를 제공한다.

2014년 발표한 B+ 보드의 경우 국내에서 5만원 정도면 구할 수 있는데 달랑 보드 하나만 들어 있다.

전원을 케이블도 없고, 하드 디스크 역할을 하는 SDCard Media도 없다.


전원은 Android 충전기 연결하고 SDCard는 마트나 인터넷에서 8GB~32GB 정도로 구매하면된다.

참고로 Raspberry Pi B형의 SDCard 타입이고 B+형은 Micro SDCard 타입이다.


OS는 홈페이지에서 무료로 제공하는데 당연히 Open Source OS의 대명사인 Linux를 기반으로 되어 있다.


http://www.raspberrypi.org/downloads/


값싸게 PC 교육을 위한 장비로서 설계된 라즈베리 파이기에 기본적으로 모니터 키보드, 마우스와 같은 주변 장비를 붙일 수 있도록 외부 I/O를 제공하며, Video는 HDMI, 인터넷은 RJ45규격의 LAN 포트, 그리고 USB 포트가 구성되어 있다.


아무리 PC 교육용이라 하더라도, 이거 하나 쓰려고 일반 PC컴퓨터에서 본체 빼고 다 있어야 한다는게 좀 불편하다는 생각이 들었는데 라즈베리 파이는 다양한 OS를 제공하고 그 중 눈에 띈 Debian 계열의 ARM Linux인 RASPBIAN 의 경우 Linux 장비이므로 GUI 사용 여부를 선택 할 수 있게 되어 있다.또한, 설치 용량도 800MB 정도로 완전 기본 패키지만 제공하므로 적은 용량의 SD Card를 사용해도 부담이 덜하다.


SDCard에 설치할 이미지는 홈페이지나 토렌트를 이용하여 받을 수 있는데, 개인적으로는 토렌트를 추천한다. HTTP로 그냥 받으면 느리기도 하고 데이터가 깨지는 경우도 있는지 Binary 가 달라서 설치 오류가 나기도 했다.


1. RASPBIAN 이미지 설치


이미지에 대한 기본적인 설치 방법은 공식 홈페이지에 자세히 나와 있다.


http://www.raspberrypi.org/documentation/installation/installing-images/README.md


토렌트에서 다운로드 받은 image 파일이 2014-06-20-wheezy-raspbian.img 인데 맥북에서 dd 명령을 이용하는 방법으로 이미지를 설치했다.


근데, 정말 오래 걸린다. 명령어를 입력하면 별다른 메시지가 없이 그냥 대기한다. 

dd 명령을 실행 중에 얼만큼 진행되었는지 상태를 보려면 [Ctrl+T]를 눌러 확인이 가능한데 마지막에 출력된 메시지를 보니 2134초 즉 36분 정도 걸렸다.


그림 <dd 명령을 이용한 RASPBIAN 이미지 설치>


아니면 NOOB에서 Raspbian을 설치 할 수 있는 방법도 있으니 이를 이용해도 된다.


https://www.raspberrypi.org/help/noobs-setup/



2. 라즈베리 접속하기


RASPBIAN이 정상 설치된 SDCard를 라즈 베리파이에 꽂은 후 전원 케이블을 연결하면 보드에 불이 들어오고 초록색 불이 깜빡거리면서 뭔가 시작하는 모습을 보인다. 만약, USB 키보드와 HDMI로 연결된 모니터가 있다면 리눅스 부팅 화면과 함께 로그인 화면을 볼 수 있다. 아무것도 안보이거나 처음 전원을 넣었을 때 초록색 불빛이 깜빡거리지 않는다면 뭔가 잘못된 거라고 볼 수 있으니 다시 설치해야 한다.


그림 <라즈베리 파이 정상 동작 화면>


RASPBIAN의 기본적인 로그인 정보는 ID: pi, 비밀번호: raspberry 를 입력하면 라즈베리 파이에 정상 로그인 되는 것을 볼 수 있다.



3. 라즈베리에 모니터 없이 접속하기


만약 라즈베리 파이를 모니터 없이 사용하려면 어떻게 할까?


라즈베리 파이는 GPIO를 제공하고 RASPBIAN은 GPIO의 UART 통신 포트를 console 접속을 할 수 있도록 구성되어 있다.


그림 <라즈베리 파이 모델 A, B의 GPIO Pinout>



그림 <라즈베리 파이 모델 B+, 2의 GPIO Pinout>


라즈베리 파이 A,B의 경우 B+ 보다 PIN이 적지만 기능상으로 PIN14번 15번이 각각 TX(수신), RX(송신)로 매핑되어 있는 것은 동일하다.

약간 혼동이 올 수 있는게 물리적인 Pinout이 아닌 GPIO의 번호라는 것을 참고 하기 바란다.


그림 <라즈베리 파이 물리적 Pinout>


http://pi.gadgetoid.com/pinout 에 각 Pin별 기능을 interactive GUI로 확인 해 볼 수 있다.



어쨌든, 라즈베리 파이와 PC는 Serial 포트로 연결해야 하는데 라즈베리 파이의 경우 3.3V CMOS 레벨 Serial을 사용하고 있으므로 다음과 같이 몇 가지 단계를 거쳐서 PC와 연결한다.


Raspberry PI GPIO Port <==> Level Converter <==> PC용 UART USB (또는 RS232C 시리얼 포트) 


위 연결 케이블을 직접 만들 수도 있겠으나 그냥 라즈베리 파이용 USB Debugging Cable을 사는게 정신 건강에 좋다.


http://neoze.co.kr/detail.php?docu_idx=10041&mdl_code=004&sml_code=002


그림 <라즈베리 파이 USB-Seria Debugging Cable>


이 제품은 PL-2303 계열 Controller를 사용한 제품인데 Windows에서 사용하려면 별도 드라이버를 설치해야 한다.


대부분의 제품이 이 Chip을 사용하는 것으로 알고 있으며, 제조사 홈페이지에서 받을 수 있다.


이 라즈베리 파이 디버깅 케이블은 총 4개의 선이 나와 있는데 그 내용은 다음과 같다.


빨간색: VCC(5V), 검은색: Ground, 흰색: RX(수신), 녹색: TX(송신)


각 케이블은 PC 입장에서 의미 이므로 라즈베리 파이의 TX에 흰색 케이블(RX)를, 라즈베리 파이 RX에 녹색 케이블(TX)을 연결한다.

그리고, 검정색은 Ground로 빨간색은 5V 전원을 공급 포트에 연결한다.


그림 <라즈베리 파이 Serial 연결 예시>


케이블 연결에 주의할 점이 있는데, 반드시 기존 USB 전원을 제거하고 디버깅 케이블의 전원을 연결해야 전원 충돌이 발생하지 않는다.

기존 전원을 그대로 사용하고 싶다면 USB 전원인 빨간 케이블을 라즈베리파이에서 빼 놓아야 한다.


참고로, 일부 USB Serial 연결 Board의 경우 기존 USB 전원을 사용하도록 switch로 옵션을 제공하는 경우도 있다.


http://www.eleparts.co.kr/EPX8N7KL


케이블 연결을 완료하면 Baudrate 115200으로 연결하면 정상적인 시리얼 통신을 할 수 있다.



4. MacOS에서 라즈베리에 Serial 접속하기


MacOS의 경우 내장 Terminal에서 명령어인 screen으로 접속이 가능하다.

USB Serial 케이블을 연결하면 케이블에 할당된 device의 driver를 확인해야 한다.

$ ls /dev/tty.* 명령으로 확인 해 볼 수 있는데 /dev/tty.usbserial 또는 /dev/tty.usbserial-XXXXX 와 같이 로딩된 driver 가 표시된다.


케이블을 연결 전후 내용을 확인하여 driver 이름을 확인 할 수 있다. 

만약 /dev/tty.usbserial 이란 이름으로 driver가 로딩 된 경우라면 다음과 같은 명령을 입력한다.


$ screen /dev/tty.usbserial 115200



그림 <MacOS screen 화면>


screen 화면을 연결을 끊으려면 control + A + K를 누른 후 y를 입력한다. screen 명령에 대한 자세한 설명은 다음 링크를 참고 한다.


http://ss64.com/osx/screen.html



Windows의 경우 PuTTY를 이용하면 된다.


http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html


그림 <Windows 7 장치 관리자 COM 포트 할당 화면>



그림 <PuTTY 설정 화면>



그림 <PuTTY 접속 화면>



4. 라즈베리 파이 SSH 접속하기


GPIO 시리얼 통신이 아닌 경우 SSH를 이용해도 라즈베리 접속 할 수 있다. 단, IP를 알아야 하는데 시리얼로 로그인 후 다음 명령으로 확인 해볼 수 있다.


ifconfig


라즈베리 파이에게 할당된 IP가 192.168.0.6이라면 다음과 같이 SSH를 이용하여 로그인을 해 볼 수 있다.


그림 <SSH를 이용한 라즈베리 파이 정상 로그인 화면>


윈도우즈 환경의 경우 PuTTY를 설치하면 라즈베리 파이로 SSH 접속을 할 수 있다.


Trackback 0 Comment 0
2014.08.12 11:21

Swift - Closures


Closures

클로져는 사용자 코드에서 다른 코드나 함수로 전달 될 수도 있고, 또 그 자체가 사용되어 질 수 있는 기능에 대한 자립적인 블럭을 말한다.

또한, 클로저에는 클로저가 정의된 곳의 context로 부터 상수나 변수에 대한 reference를 수집(capture)하거나 저장(store) 가능한데 이를 두고 변수나 상수를 closing한다라는 표현을 사용하기에 closures라는 이름으로 불린다.


reference capturing 에 대한 부분은 별도로 설명하고 있으나 간략하게 정리하면, 클로저가 해당 변수나 상수를 지속적으로 참고하고 있으며, 변수일 경우 해당 정보의 변경에 대한 정보를 지속적으로 얻을 수 있는 것을 말한다.


Global 함수와 nested 함수가 closure에 대한 특별한 모습이라 할 수 있으며, 클로져는 다음 세 가지 중 하나의 모습을 갖게 된다.

  • Global 함수는 이름을 갖고 어떠한 값도 수집하지 않는 클로져이다
  • Nested 함수는 이름을 가지고 해당 함수를 포함하는 함수의 값을 수집 할 수 있는 클로져이다
  • 클로져 expression은 이름이 없는 클로져로, 해당 클로져를 포함하는 context의 값을 수집 할 수 있도록 간략한 형태이다

Closures Expressions

Closure Expressions은 syntax를 중점으로 inline closure를 간략하게 작성하는 방법을 말한다.
Closure Expressions은 명료함과 의도에 대한 손실 없이 클로저를 가장 단순화 할 수 있는 몇몇의 최적화 syntax를 제공한다.

Closure Expression을 잘 설명하기 위해 sorted 함수를 먼저 소개를 한다.
  • The Sorted Function
    • Swift 표준 라이브러리에는 sorted라는 이름의 함수를 제공한다
    • 이는 프로그래머가 제공한 클로저 함수의 결과를 기준으로 주어진 타입의 Array의 값을 정렬 해 주는 함수이다.
    • 호출이 완료되면 sorted 함수는 기존 입력했던 Array와 동일한 타입과 크기의 정렬된 array를 생성하며 원본은 변하지 않는다.
    • sorted 함수는 다음 두 가지 정보를 argument로 입력 받는다
      • 알고 있는 타입 값의 Array
      • Array 에 담고 있는 값의 타입과 동일한 타입 두 개를 argument로 그리고 리턴 타입으로 앞서 입력 받은 타입을 비교하여 그 결과에 대해 true 또는 false를 리터하는 클로저 타입
    • 예를 들어 문자열 Arrary라면 다음과 같다
      • let names = ["Hello", "World", "Swift", "Programming"]
    • 이럴 경우 클로져 타입은 (String, String) -> Bool 이 되고
      • func backwards(s1: String, s2: String) -> Bool {
      •   return s1 > s2
      • }
      • var reversed = sorted(names, backwards)

이제 Closure Expression 에 대해 자세히 설명하겠다
  • Closure Expression Syntax
    • Closure Expression Syntax는 다음과 같다
    • { ( 파라메터 ) -> 리턴타입 in
    •     내용
    • }
    • Closure Expression에서는 Parameter로 상수, 변수, inout을 사용 할 수 있다. 그러나, default 값은 사용 할 수 없으며 Variadic 타입의 경우 이름을 붙여 Parameter의 제일 마지막 부분에만 사용하는 경우만 사용이 가능하다
    • 앞서 sorted 함수에서 사용했던 backwards 함수를 Closure Expression으로 표현하면 다음과 같다.
      • var reversed = sorted(names, {
      •   (s1: String, s2: String) -> Bool in
      •   return s1 > s2
      • }
    • 이 inline closure의 파라메터와 리턴타입 선언부는 backwards 함수의 것과 동일하지만 함수와 달리 괄호 문자로 ('{') 둘러 싸여 있다는 차이가 있다.
    • inline closure는 in 이라는 키워드를 기준으로 in 이전에는 파라메터 및 리턴타입을, 이후에는 본문을 구분된다
    • 본문 내용이 그리 길지 않은 경우 다음과 같이 한 줄로 줄여서 사용 할 수도 있다
      • var reversed = sorted(names, {(s1: String, s2:String) -> Bool in return s1 > s2 })
  • Inferring Type From Context
    • sorted 함수의 경우 Closure로 넘기는 parameter의 타입으로 부터 closure의 타입을 짐작할 수 있다.
    • 앞의 예제의 경우 String Array 를 전달하게되므로 Closure 타입은 (String, String) -> Bool 이며 이를 closure expression에서는 궂이 지정할 필요는 없다
      • var reversed = sorted(names, {(s1, s2) in return s1 > s2})
  • Implicit Returns from Single-Expression Closures
    • Single-Expression Closures는 return 키워드를 생략해도 그 실행 결과가 return을 의미한다고 본다
      • var reversed = sorted(names, {(s1, s2) in s1 > s2})
    • 위의 경우는 하나의 expression ( single-expression )은 s1 > s2 이며 그 결과가 Bool 이므로 명확하게 return 값으로 처리하게 된다
  • Shorthand Argument Names
    • Swift는 inline closure에 대해 별도의 명시가 없는 경우 그 순서에 따라 $0, $1 와 같이 자동으로 shorthand argument 이름을 제공한다. 따라서, 별도의 argument를 지정하지 않는다 해도 이를 이용해서 closure를 구성 할 수 있다.
      • var reversed = sorted(names, { $0 > $1 })
      • 여기서 $0은 closure의 첫 번째 String 타입 parameter, $1는 두 번째 String 타입 parameter를 의미한다
  • Operator Functions
    • Swift에서는 앞서 예제를 가장 짧게 줄일 수 있는 방법을 제공하는데 바로 Operator Function 이다.
    • Swift는 두 개의 String 타입 Parameter와 Bool 타입의 리턴타입을 가지는 함수로 greater-than operator ( > )에 대한 구현을 정의 해 놓고 있다
    • 이는 위의 sorted 함수의 예제에 사용된 closure 타입과 정확하게 일치하므로 그냥 단순하게 greater-than operator를 closure 자리에 대치 할 수도 있다
      • var reversed = sorted(names, > )
    • 자세한 내용은 별도의 Operator Functions 항목에 자세히 설명되어 있음

Trailing Closures Expressions

closure expression을 함수의 마지막 argument로 전달하고 그 expression이 길어질 때 trailing closure라는 방식으로 작성하면 유용할 수 있다.
Training closure는 이를 지원하는 함수의 괄호 ('()') 바깥쪽 (그리고 바로 직후)에 쓰는 closure expression이다.
  • 다음과 같이 closure를 입력 받는 함수를 정의한다면
    • func test(closure:()->()) {
    •   // 본문
    • }
  • trailing closure를 사용하지 않는 호출하는 경우는 다음과 같고
    • test({
    •   // closure 본문
    • })
  • trailing closure를 사용하면 다음과 같이 호출 함수의 괄호 바깥에 놓을 수 있다
    • test() {
    •   // closure 본문
    • }
  • sorted의 예제 중 shorthanded argument를 적용해 보면 다음과 같이 줄여서 사용이 가능하다
    • var reversed = sorted(name) { $0 > $1 }

trailing closure는 single-line으로 표현하기 어려운 긴 closure를 표현할 때 가장 유용하다. Array의 map과 같은 method는 argument로 하나의 closure를 입력받는데, 해당 closure에 Array Item을 하나씩 넘겨주고, closure에서 mapping 된 새로운 정보를 리턴받는다. 이 때 기존 Array와 동일한 순서를 갖지만 새롭게 mapping된 값을 갖는 새로운 Array가 생성된다. 

  • let numstr = [1, 2, 3].map {
  •   (var num) -> String in  String(num)
  • }


    'Technical Stubs > Apple Swift' 카테고리의 다른 글

    함수 호출 문법에서 missing arguments labels가 나올 때  (0) 2014.09.18
    Swift - Closures  (0) 2014.08.12
    Swift - Function  (0) 2014.08.11
    Swift - Control Flow  (0) 2014.08.11
    Swift - Data Type #Collections  (0) 2014.08.08
    Swift - String  (0) 2014.08.08
    Trackback 0 Comment 0