보통 다른 언어에서는 숫자 자료형이 세분화되어 있다. C++의 예를 들면 byte, short, int, long, float, double 등등 정수냐 실수냐에 따라 또는 표현 범위에 따라 숫자 자료형이 세분화 되어 있으며 JAVA, C# 같은 언어도 마찬가지이다. 반면 루아에서는 그냥 숫자형(number로 표기된다) 하나이고 내부적으로 모든 숫자를 double 형 데이터로 처리한다.


print( type(1) )
print( type(1.1) )
print( type(1.1e34) )
실행결과
number
number
number


print()함수는 표준출력(보통은 화면)을 하는 내부함수이고 type()은 넘겨진 자료의 자료형 반환하는 내부함수이다. 따라서 print( type(x) ) 는 x의 자료형을 출력하는 명령이다. 위에서 정수 1도 number, 실수 1.1도 number, 1.1e34(지수적 표기법으로 1.1x1034을 나타낸다.)도 number이다. 모두 다 동일한 숫자형(number)라는 것을 알 수 있다.

 똑 같은 일을 변수를 이용하여 작성해 보면 다음과 같다.


a = 1 -- 변수 a에 정수 1을 대입
b = 1.1 -- 변수 b에 실수 1.1을 대입
c = 1.1e34 -- 변수 c에 정수 1.1 x 1034 을 대입
print(type(a)) -- ‘number’ 가 출력된다.
print(type(b)) -- ‘number’ 가 출력된다.
print(type(c)) -- ‘number’ 가 출력된다.


이 예에서 보면 a=1 이라고 하면 변수 a에 1을 대입하라는 것이고 b=1.1은 변수 b에 1.1.을, c=1.1e24는 변수 c에 1.1x1034을 대입하라는 것이다. 변수명은 이전 포스트에서 설명한 식별자 규칙에 의해서 만들어져야 한다. print( type(a) )는 변수 a에 담겨진 데이터의 자료형을 출력하라는 명령이 된다. 변수 a에는 1이 들어가 있으므로 number 가 화면에 출력된다.

 이와 같이 루아에서는 숫자 자료형은 하나밖에 없다. 루아는 내부적으로 정수도 double형이고 실수도 double형으로 처리된다. 일견은 메모리 낭비같이 여겨지기도 하지만 현대의 컴퓨팅 환경에서는 크게 중요한 문제는 아니고 이를 통해서 데이터 처리의 단순함을 얻을 수 있다.



Posted by 살레시오
,

 식별자(identifier)는 변수명이나 함수명 등을 만들때 사용된다. 루아의 식별자를 만드는 규칙은 다음과 같다. (C/C++과 동일하다.)


  1. 영어 대소문자(a~z, A~Z), 숫자(0~9), 언더바(_)로만 조합한다.

  2. 숫자로 시작하거나 공백문자를 포함할 수 없다.

  3. 미리 정의된 예약어(keyword)는 사용하면 안된다.


다른 언어에서와 마찬가지로 식별자는 대소문자를 구별한다. 즉, 대문자 A와 소문자 a는 서로 다른 것으로 구별된다. 식별자는 에를 들면 다음과 같은 것들이다.


x, vla, number, _hello, abc, id123, ch_4_5, name_of_that, _image, __sound


루아의 예약어는 프로그램에서 의미를 갖는 단어로서 다음과 같은 것들이 있다.


and, break, do, else, elseif, end, false, for, function, if, in local, nil, not, or, repeat, return, then, true, until, while


또한 예약어 외에 전역 함수(혹은 객체)에 사용되는 식별자도 사용하면 안되며 다음과 같은 것들이 있다.


_G, _VERSION, getmetatable, tostring, assert, io, rawlen, string, load, bit32, pairs, rawset, select, coroutine, tonumber, next, type, table, xpcall, error, utf8, debug, collectgarbage, math, rawget, os, pcall, ipairs, rawequal, print, setmetatable


이러한 규칙에 따라서 식별자를 만들어야 한다.



Posted by 살레시오
,

1.1 windows에서 설치하는 방법   c{ipy03}

먼저 윈도우 커맨드창을 반드시 '관리자 모드'로 실행시켜야 한다. (설치과정에서 시스템의 임시폴더를 접근하므로) 이것을 위해서 c:\windows\system32\cmd.exe 를 찾아서 마우스 우클릭후 '관리자모드로 실행'을 선택하여 커맨드창을 연다


그 다음 파이썬과 pip 모듈이 설치되었다고 가정하고 다음과 같이 명령을 내린다.


easy_install ipython[all]

혹은


python -m pip ipython[all]

이렇게 하면 ipython을 실행하기 위해서 필요한 모듈들이 모두 설치된다. 설치하는 데 조금 시간이 걸린다. 이제 다음과 같은 명령을 내리면 ipython이 실행된다.


python -m IPython

여기서 IPython의 첫 두 글자 'I'와 'P' 가 대문자이므로 유의해야 한다.



Posted by 살레시오
,

 클래스의 메서드는 일반 함수를 정의하는 것과 동일한데 한 가지 첫 번째 인자는 반드시 self가 되어야 한다는 점이 다르다.  관례적으로 메서드 정의들 사이에는  한 줄 공백을 준다.


class Robot:

   def __init__(self, name='dummy'):
       self.name = name

   def talk(self):
       print('Hi. I am %s.'% self.name)


self라는 변수를 클래스 함수의 첫번째 인자로 받아야 하는 것은 파이썬만의 (불필요해 보이는) 특징이다. 문법이 이렇게 규정되어 있으니 사용자는 거기에 맞추어 작성해 주어야만 한다. 메서드 내에서는 이 self 변수를 통해서 기정의된 필드를 접근할 수 있으며 또 한 새로운 필드를 생성하는 것도 가능하다. talk() 메서드 내부에서 name 이라는 필드를 self를 통해서 (즉, slef.name 와 같이) 사용했음을 알 수 있다. 객체의 필드는 이와 같이 메서드 내에서 반드시 self 변수를 통해서만 접근할 수 있다.


 객체의 필드와 메서드 목록을 확인하고 싶으면 내장함수 dir()를 이용하면 된다.


>>> asimo=Robot(‘asimo’)
>>> dir(asimo)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name', 'talk']


위에서 보면 매직 메서드들 다음에 name, talk 등 필드와 메서드의 이름을 모두 확인할 수 있다.


   이제 asimo라는 Robot 클래스 객체를 통해서 메서드를 호출할 수 있다. 객체명 뒤에 점(.)을 찍고 함수명을 명시하면 된다.


>>> asimo.talk()
Hi. I am asimo.


메서드를 호출하는 쪽에서는 정의부의 self인자는 무시하고 (없는 것으로 간주하고) 인자를 주면 된다. 따라서 asimo.talk() 메서드는 아무런 인자를 주면 안된다. __init__() 메서드와 마찬가지로 self 인자 뒤에 일반인자를 줄 수 도 있다.


class Robot:

   def __init__(self, name = 'dummy'):
       self.name = name

   def talk(self):
       print('Hi. I am %s.'% self.name)

   def walk(self, step):
       print('Sorry. No legs.')

   def run(self, dist, speed = 10):
       print('Must go %dm at %dm/s speed.'%(dist, speed))
       print('Sorry. No legs.')


이렇게 정의하면 walk()함수는 하나의 일반 인자를 주고 호출해야 하며 run()은 하나 혹은 두 개의 일반 인자를 주어야 한다.


>>> asimo.walk(5)
Sorry. No legs.
>>> asimo.run(100, 50)
Must go 100m at 50m/s speed.
Sorry. No legs.
>>> asimo.run(100)
Must go 100m at 10m/s speed.
Sorry. No legs.


이와 같이 메서도는 첫 번째 인자가 self 라는 점만 제외하면 일반 함수와 정의와 호출하는 방법이 동일하다.



Posted by 살레시오
,

 자바스크립트(ECMAScript 5) 객체의 공용 멤버와 공용 메소드는 다음과 같이 만드는 것이 일반적인 것 같다.


var A = function(name) {
   console.log("constructor A.");
   this.name = name; //공용 멤버
}
A.prototype = {
   who: function() { //공용 메소드
       console.log("I'm "+this.name);
   },
};


즉 공용 멤버는 생성자 함수 안에서 this 키워드로 만들어지고 공용 메소드는 prototype 객체 안에 정의한다.


 이제 이렇게 생성된 객체 A를 상속해서 새로운 객체 B를 정의하는 방법을 알아보자. 상속이란 기존 객체의 모든 공용 멤버를 복사하여 그대로 사용하면서 거기에 새로운 멤버나 메소드를 추가하는 방식으로 객체를 재사용하는 방법이다. 여러 방법 중에서 ECMAScript5 에서 도입된 Object.create() 함수를 사용하는 일반적인 방법은 다음과 같다.


var B = function(name, age) {
   console.log("constructor B.");
   A.call(this, name); // (1)공용멤버를 상속(복사)한다.
   this.age = age; // 새로운 멤버 추가
}
B.prototype = Object.create(A.prototype); //(2)공용메소드를 상속(복사)
B.prototype.constructor = B; //(3)생성자를 복원한다.
B.prototype.who2 = function() { // 새로운 메소드 추가
   console.log("I'm "+this.age+" years old.");
}


위에서 보면 세 가지 단계가 필수적이다.


(1) 공용 멤버를 상속(복사)하기 위해서 생성자 함수 내부에서 A.call() 함수나 A.apply()함수를 호출하여 공용 멤버들을 복사하는 단계

(2) 공용 메소드들을 복사하기 위해서 Object.create() 함수를 호출하는 단계

(3) 생성자를 복원하는 단계


만약 상속받는 객체의 생성자 함수의 인자들과 원 객체의 생성자 함수 인자들이 동일하다면 A.apply() 함수를 이용하여 인자 전체를 넘긴다.


A.apply(this, arguments);


그렇지 않고 일부만 선택적으로 사용한다면 예제와 같이 A.call()함수를 사용할 수 있다.





Posted by 살레시오
,

 자바스크립트에서 불리언 결과가 false로 판명되는 것들은 다음과 같다.


  • undefined, null

  • NaN

  • 0 (숫자 리터럴) , -0

  • “” (빈 문자열)

  • false


주의할 점은 빈 문자열은 false 이지만 빈 배열, 빈 객체는 true라는 것이다.


> Boolean("")
false
> Boolean([])
true
> Boolean({})
true


그리고 NaN은 그 자신과 같지 않은 유일한 자료형이다.


> undefined == undefined
true
> null == null
true
> NaN == NaN
false


논리 or (||) 연산자를 이용하여 자바스크립트에는 지원하지 않는 default parameter 를 구현할 수 있다.


function func(a) {
  if (a == undefined) a = 1; //(*)
  ...
}


위와 같이 하면 func(0)이라고 호출하면 변수 a는 사용자가 지정한 대로 0값을 가지지만 func() 라고 호출해도 내부 변수 a는 1값을 가지게 된다.


 루아 프로그래머는 위의 (*)를 다음과 같이 더 간단하게 할 수 있지 않느냐고 생각할 지 모른다.


a = a || 1


하지만 func(0) 으로 호출하면 a는 내부적으로 1로 바뀌어 버린다. 0은 false로 간주하기 때문이다. (루아에서는 숫자 0은 true이다.) 주의해야 한다.




Posted by 살레시오
,

 자바스크립트 파일을 컴파일하여 (단일) 실행 파일을 생성하려면 enclose 를 이용한다.



설치는 다음과 같이 한다.


npm install -g enclose


기본적으로 -o 옵션으로 출력파일을 지정해 줄 수 있다.


enclose -o 출력파일 소스파일


그리고 --loglevel 옵션으로 정보 출력 단계를 조절할 수 있다.


한 줄짜리 간단한 js프로그램도 이것으로 실행 파일을 만들어보면 10M 가까운 용량을 차지한다. 외부 라이브러리가 사용되었다면 그것까지 포함되기 때문에 용량을 더 늘어난다. 하지만 js파일을 간단하게 윈도 실행 파일로 변환할 수 있다.

Posted by 살레시오
,

github에 저장한 (예를 들어서) javascript 파일의 raw 파일 주소를 CDN 파일 주소로 제공해주는 유용한 사이트가 rawgit.com 이다.



사용법도 엄청 간단한데 서비스 받고자하는 github의 raw 파일 주소를 붙여넣기만 하면 바로 CDN 주소를 생성해 준다. 이 주소를 이용하면 된다. 좌측의 주소와 우측의 주소는 조금 성질이 다른데 git push 를 실시간으로 반영하려면 좌측의 주소를 사용해야 한다. 우측의 주소는 처음 등록된 스탭샷을 캐싱해서 그것을 사용하는 대신 속도는 빠르다고 한다.


 위 예는 github에서 관리하는 pixion.js 라는 자바스크립트 모듈을 가지고 실험한 것인데 생성된 주소는 jsfiddle.net 의 리소스 주소로 바로 사용할 수 있다.



만약 좌측의 주소를 사용한다면 파일의 변경점이 실시간으로 반영되기 때문에 개발 중인 모듈을 간단하게 다른 사용자들에게 공급할 수 있어서 아주 유용하다. 단 트래픽이 많이 발생할 경우 병목현상이 있을 수 있다고 한다.



Posted by 살레시오
,

 Koding에서 node.js 를 이용하여 http서버를 실행시킬 수 있으며 외부에서 접속도 가능하다. 다음과 같이 작성한 후 적당한 이름(test002.js)로 저장한다.


var http = require('http');

var server = http.createServer(function (req, res) {
 res.writeHead(200, { 'Content-Type' : 'text/plain' });
 res.end('Hello nodejs');
});

server.listen(8000);


이제 터미털에서 다음과 같이 실행한다.


$node test002.js


그러면 http 서버가 동작하기 시작한다. 외부에서 접속하려면 브라우저에서 다음과 같은 주소를 입력하면 된다.


http://hostname.koding.io:8000


자신의 hostname은 터미널에서 hostname 명령어로 알 수 있다.



만약 arduinoharp라면 다음과 같이 주소를 입력한다.


http://arduinoharp.koding.io:8000


그러면 ‘Hello node.js’라는 문자열이 브라우저에 표시될 것이다.





Posted by 살레시오
,

 C#으로 chart 컨트롤을 사용하는 기본적인 방법에 대해서 이전 포스트에서 알아보았는데 여기에서는 여러 개의 그래프를 하나의 창에 도시하는 방법과 축의 분리에 대해서 알아보도록 하겠다.


 Chart 객체는 여러 개의 Series 그리고 한 개 이상의 ChartArea 객체를 콜렉션 멤버로 가지고 있으며 chart1.Series 와 chart1.ChartArea 같이 접근할 수 있다.


  • Series 객체는 도시할 그래프를 구성하는 점의 집합

  • ChartArea 객체는 그래프를 보여줄 영역


ChartArea는 초기에 한 개가 미리 생성되어 있고 chart1.ChartArea[0] 혹은 chart1.ChartArea[“ChartArea1”]와 같이 인덱스나 이름(문자열)로 접근할 수 있다. Series 객체도 초기에 하나가 생성되어 있으며 ChartArea[0]에 연결되어 있다. 그리고 사용자가 새로 생성되는 Series 객체는 이 default ChartArea와 자동으로 연결이 된다.


private void Form1_Load(object sender, EventArgs e)
{
   chart1.Series.Clear(); //default series를 삭제한다.
   Series series1 = chart1.Series.Add("graph1");
   series1.ChartType = SeriesChartType.Line;
   for (double k=0;k<2*Math.PI;k+=0.1)
   {
       series1.Points.AddXY(k, Math.Sin(k));
   }

   Series series2 = chart1.Series.Add("graph2");
   series2.ChartType = SeriesChartType.Line;
   for (double k = 0; k < 2 * Math.PI; k += 0.1)
   {
       series2.Points.AddXY(k, Math.Cos(k) - 2.0);
   }
}


위와 같이 생성된 Series객체 두 개 모두 ChartArea[0]로 (자동으로) 연결되며 이전 포스트에서 보여준 바와 같이 x축과 y축이 모두 공유된다.


 그런데 같은 영역의 두 그래프의 축을 분리할 수도 있다. 예를 들어 y축 스케일이 다른 두 개의 그래프를 하나의 영역에 겹쳐서 도시하고 싶다면 다음과 같이 하면 된다.


series2.YAxisType = AxisType.Secondary;


이렇게 하면 두 개의 그래프의 x축은 공통이고 분리된 y축의 스케일이 그래프 우측에 표시된다.



이 결과를 보면 그래프영역 우측의 y축에 secondary 축의 단위가 표시됨을 알 수 있다. Series.XAxisType 이나 Seires.YAxisType 프로퍼티는 별도로 지정하지 않으면 AxisType.Primary 로 자동 지정된다.


여기서 한 가지 알아두어야 할 것은 series1과 series2는 y축만 분리되었고 x축은 공통이기 때문에 다음과 같이 x축의 범위를 변경하면 둘 다 영향을 받는다는 점이다.


chart1.ChartAreas[0].AxisX.Minimum = 2.0;
chart1.ChartAreas[0].AxisX.Maximum = 4.0;



하지만 AxisY의 범위를 조절하면 series1만 영향을 받는다.


chart1.ChartAreas[0].AxisY.Minimum = -0.5;
chart1.ChartAreas[0].AxisY.Maximum = 0.5;



series2의 y축 범위를 조절하려면 다음과 같이 하면 된다.


chart1.ChartAreas[0].AxisY2.Minimum = -2.5;
chart1.ChartAreas[0].AxisY2.Maximum = -1.5;



이번에는 series2의 y축 범위만 조정되었음을 알 수 있다.


이와 같이 하나의 ChartArea에 여러 개의 Series 들을 도시할 수 있는데 각 Series의 축을 분리할 수 있으며 x축만 분리할 수도 있고 y축만 분리할 수도 있으며 둘 다 분리할 수도 있다.





Posted by 살레시오
,