2007년 5월 7일 월요일

4장 컨테이너,블록,반복자

  배열(Array)
Array 클래스는 객체 참조를 콜렉션(Collection)으로 저장합니다. 배열의 기본 특징은 다음과 같습니다.
  • []를 사용하여 위치를 지정합니다.
  • 위치는 정수로 지정을 합니다.
  • 인덱스는 0부터 시작합니다.
  • 정수로 지정하면 해당 위치의 객체를 반환하고, 없는 경우에는 nil을 리턴합니다.
  • 음수로 지정하는 경우에는 뒤에서부터 찾습니다.
  • 배열 인덱스를 [start, count]를 사용하여 새로운 배열을 반환할 수 있습니다.
    a = [1,2,3,4,5]
    a[1,4]  -> [2,3,4,5]
  • 또한 범위(.. ...)를 사용하여서 새로운 배열을 반환할 수 있습니다.
    a = [1,2,3,4,5]
    a[1..3]  ->  [2,3,4]   # ..는 마지막 위치를 포함합니다.
    a[1...3]  ->  [2,3]    # ...는 마지막 위치를 포함하지 않습니다.
  해시(Hash)
배열과 흡사합니다. 배열의 인덱스는 정수이나, 해시의 인덱스는 어떠한 종류의 객체도 사용할 수 있습니다. 키 => 값의 쌍을 중괄호 사이에 써서 해시를 정의합니다. 해시에는 원소에 순서가 없기 때문에, 스택이나 큐로는 쓰기 어렵습니다.
 
   h = {'dong' =>'canine', 'cat' =>'filine', 'donkey'=>'asinine'}

  SongList 컨테이너 구현하기
class SongList
   def initialize
      @songs = Array.new
   end
   def [](index)
      @songs[index]
   end
end

  블록과 반복자
class SongList
   def with_title(title)
      @songs.find{|song| title == song.name}    # title이 song(songs의 element)의 name과 같은지 비교
   end
end
블록은 메소드 호출 바로 뒤에만 나타납니다.
블록 안의 코드는 나타나자마자 실행되지 않으며, 블록이 나타날 때의 문맥을 기억하고 메소드로 들어갑니다.
def three_times
   yield "A"
   yield "B"
   yield "C"
end
three_times {|name| puts name}
또한, 위의 코드처럼 매개변수를 넘기고 이를 넘겨 받을 수도 있습니다.
블록은 {}로도 정의할 수 있으나, do...end를 사용하여 정의할 수 있습니다. 이 경우에는 {}보다 우선순위가 더 낮습니다.

inject 메소드는 컬렉션의 원소를 하나씩 반복하며 모아서 새로운 값을 만듭니다.
   [1,3,5,7].inject(0) {|sum,element| sum + element}   -> 16

inject 메소드에서 sum의 값은 0이 됩니다.(매개변수가 됩니다.) element의 경우에는 [1,3,5,7] 배열의 첫 번째인자가 됩니다. 두 번째 실행될 때는 바로 전에 실행된 블록의 반환 값이 sum이 됩니다.
매개변수가 없는 경우에는 [1,3,5,7] 배열의 첫 번째 값이 인자가 됩니다.

  트랜잭션을 위한 블록
class File
   # *args: 실제로 메소드에서 넘겨받은 매개변수를 모아서 배열로 만들고 args로 이름을 붙인다.
   def File.open_and_process(*args)
      # ["test", "r"]을 배열로 받아서 File.open으로 넘긴 다음에 블록을 실행합니다.
      f = File.open(*args)
      yield f
      f.close()
   end
end

File.open_and_process("test","r") do|file|
   while line = file.gets
      puts line
   end
end

  블록은 클로저이기도 하다.
Button을 상속받아 새로운 Button을 만드는 경우, 새로운 버튼을 만들기 위해서 많은 수의 하위클래스가 필요해지고, 실제 버튼을 눌렀을 때 동작하는 부분은 버튼이 아니라 버튼에 의해서 실행되는 코드가 책임을 가지고 있다.

songlist = SongList.new
class JukeboxButton < Button
   # &를 붙일 경우, 코드 블록이 있는지 살펴본 다음에 결합된 코드는 Proc 클래스 인스턴스로 변환되어
   # 형식인수에 할당됩니다.
   def initialize(label, &action)
      super(label)
      @action = &action
   end
   def button_pressed
      @action.call(self)
   end
end
start_button = JukeboxButton.new("Start") { songList.start }
pause_button = JukeboxButton.new("Pause") { songList.pause }

Proc객체를 만들어 얻는 것은, Proc이 정의된 시점에서의 모든 문맥 정보를 함께 갖게 된다는 점입니다. self값과 범위내의 메소드, 변수, 상수를 포함하게 됩니다.(closure)

def n_times(thing)
   return lamda {|n| thing *n}   # 블록을 Proc객체로 변환시켜 줍니다.
end
p1 = n_imes(23)
p1.call(3)

2007년 5월 3일 목요일

[Script.aculo.us] dragdrop.js

  dragdrop.js
script.aculo.us에서 Drag&Drop 기능을 제공해주는 라이브러리입니다.

  Droppables
드래그 대상이 되는 Draggable객체들을 Drop할 수 있는 element들을 관리하는 클래스입니다.
사용자 삽입 이미지

  Attribute
Droppables.drops: Array - Droppable 객체(실제로는 add()의 options 전체 항목이 저장됩니다.)들을 저장하는 배열입니다.

  Method
1. Droppables.add(element, options) - Droppable 객체를 추가합니다. options로 다음 사항을 받을 수 있습니다.
options 항목들
  • accept - Droppable에서 받아들일 Draggable 객체의 클래스 스트링들을 설정합니다.
  • containment - Droppable에서 받아들일 Draggable객체의 element나 id를 설정합니다.
  • hoverclass:boolean - 받아들이기로 한 Draggable객체가 Droppable의 위에 있을 때 css를 설정하는 class를 설정합니다.
  • overlap - 'horizontal' 또는 'vertical'을 인자로 받습니다. 수직/수평 방향으로 이동할 때 동작이 발생하도록 합니다.
  • greedy:boolean - true로 설정된 경우 hover와 관련된 처리를 수행하지 않습니다.
options 항목들 중 내부사용 프로퍼티
  • tree - tree에서 사용하기 위한 코드로 보임
  • _continaers - options.containment객체들이 저장됩니다.
  • element - 실제 Droppable element가 저장됩니다.
options 항목의 callback들
  • onHover(dragElement, dropElement, position) - 받아들이기로 한 Draggable 객체가 Droppable의 위에 있에 있을 때 메소드를 onHover 인자로 받은 function을 호출합니다.
  • onDrop(dragElement, dropElement, event) - 받아들이기로 한 Drggable 객체가 Droppable의 위에서 릴리즈되었을 때 onDrop 인자로 받은 function을 호출합니다.
2. Droppables.remove(element) - Droppable 객체를 삭제합니다.

3.
Droppables.findDeepestChild(drops)
- drops 루프를 돌면서 drops에서 가장 먼저 등록한 Droppable 객체들 중에서 가장 상위에 있는 Droppable 객체를 찾는 메소드입니다. (의도는?)

4.
Droppables.isContained(element, drop)
- 인자로 받는 element의 부모노드가 drop의 containment(받아들이기로 한 element) 목록에 있는 지 여부를 리턴합니다.

5. Droppables.isAffected(point, element, drop)
- 인자로 받는 element가 인자로 받는 drop(Droppable)에 Drop이 된 것인지의 여부를 체크하는 메소드입니다.
  1. drop.element와 달라야하고,
  2. drop._containers가 있는 경우 여기에 속해야하고,
  3. drop.accept가 있는 경우 element의 className중 하나가 해당해야하고,
  4. drop.element의 안에 인자로 받는 point의 위치가 속해야 합니다.
6. Droppables.activate(drop) [Droppables.deactivate(drop)]
- active[deactive]가 된 경우, drop.hoverclass가 있다면 drop.element에 hoverclass를 설정[제거]하고 last_activate 값을 설정[null로 설정]합니다.

※ show, fire, reset 메소드의 경우 Draggable에서 호출되는 메소드입니다.
7. Droppables.show(point, element)
- element의 Drop에 해당하는 Droppable이 있으면 hover 이펙트를 발생시킵니다.
  1. 인자로 받은 element가 Drop되었는지를 체크(isAffected())하여 affected에 담습니다.
  2. affected된 Droppable 중에서 가장 상위의 element(findDeepestChild()를 사용하여)를 찾습니다.
  3. 해당하는 Droppable을 activate시킵니다.
8. Droppables.fire(event, element) - onDrop 옵션을 가지고 있는 경우 onDrop 이벤트를 실행시킵니다.
9. Droppables.reset() - 초기화(deactivate) 시킵니다.

  Draggables
Draggables객체들을 관리하는 클래스입니다.
사용자 삽입 이미지

  Attribute
Draggables.drags: Array - draggable을 저장합니다.
Draggables.observers: Array -
activeDraggable - 현재 활성화되어 있는 Draggable을 가르키는 변수입니다.

  Method
1. Draggables.register(draggable)
- draggable을 인자로 받아서 drags에 추가합니다.
- drggable이 처음 등록되는 경우 document의 mouseup/mousemove/keypress 이벤트 핸들러로 eventMoueUp/eventMouseMove/eventKeypress 메소드를 등록합니다.

2. Draggables.unregister(draggable) -
- 인자로 받는 draggable을 drags에서 삭제합니다.
- 모든 draggable이 삭제되는 경우, document의 mouseup/mousemove/keypress 이벤트에 등록된 핸들러들을 모두 삭제합니다.

3. Draggables.activate(draggable)
- Draggable에서 호출되며, (delay 옵션이 있는 경우 dealy 옵션 뒤에) activeDraggable을 설정합니다.

4. Draggables.deactivate() - activeDraggable을 삭제합니다.(null처리)

※ 2에서 등록하였던 mouseup/mousemove/keypress 이벤트에 따라서, (activeDraggable이 있는 경우)activeDraggable에 해당하는 이벤트를 전달하는 역할을 합니다.
5. Draggables.updateDrag(event)
6. Draggables.endDrag(event)
7. Draggables.keyPress(event

※ 8, 9, 10, 11은 Draggables.observers와 관련된 메소드들로 Draggable에서 onStart/End/Drag 이벤트가 발생됬을 때, 해당하는 이벤트를 듣기 위한 구조입니다.
8.
Draggables.addObserver(observer)
9. Draggables.removeObserver(element)
10. Draggables.notify(eventName, draggable, event)
- notify는 Draggable에서 호출되는 메소드로 onStart/onEnd/onDrag 이벤트가 발생한경우 observer에서 해당하는 이벤트를 관차하는 observer가 있는 경우 observer의 callback을 호출한 후 draggable의 등록된 callback을 호출합니다.
11. Draggables._cacheObserverCallbacks()

  Draggable
Drag되는 (Draggable)객체 입니다.
사용자 삽입 이미지
Creation
new Draggable('id_of_element', [options]);
options항목은 다음과 같습니다.
  • handle - v1.0에서는 draggable할 element의 레퍼런스와 id를 인자로 받습니다. v1.5에서는 css 클래스 스트링으로 사용됩니다.
  • revert :boolean - true인 경우, 시작점으로 돌아갑니다. function이 들오올 수 있습니다.(since v1.5) 디폴트 값은 false입니다.
  • snap - true인 경우, snapping(달려들어 무는)이 발생합니다. 디폴트 값은 false입니다.
  • zindex - draggable할 item의 zindex를 정의합니다.
  • constraint - 'horizontal' 또는 'vertical'이 설정되는 경우, 수평/수직으로만 이동하도록 설정됩니다.
  • ghosting :boolean - Drag~Drop이 진행되는 동안 자신의 위치에 clone object를 남겨둡니다.
  • starteffect - Drag가 시작될 때, 적용할 이펙트를 정의합니다. 디폴트로 투명 이펙트(Opacity)를 실행합니다.
  • reverteffect - Drag를 하다 되돌아가는 경우(Droppable영역이 아닌 지역에서 릴리즈했을 때)에 적용할 이펙트를 정의합니다. 디폴트 값으로는 시작점 포인트로 직선 이동하는 이펙트(Move)를 실행합니다.
  • endeffect - Drag가 종료될 때, 적용할 이펙트를 정의합니다. 디폴트로 투명 이펙트(Opacity)를 실행합니다.
options에 설정되는 callback function입니다.
  • change - Drag로 인하여 Draggable의 위치가 변경된 경우 발생합니다.
  Attribute
Draggable.drags: Array - draggable을 저장합니다.
Draggable.observers: Array - observer할 object들을 저장합니다.
activeDraggable - 현재 활성화되어 있는 Draggable을 가르키는 변수입니다.
dragging: boolean - dragging이 진행 중인지를 저장하는 변수입니다.

  Method
1. destroy()
2. currentDelta() - Draggable element의 left/top 위치를 리턴합니다.
3. initDrag(event)
- Draggable에 mousedown 이벤트가 발생한 경우 호출됩니다.
- draggable에 포함되는치, form element인지를 체크한 후, 현재의 마우스 위치와 실제 화면상의 위치 값을 저장한 후 Draggables.activate를 호출합니다.

4.
startDrag(event)
- Draggable.updateDrag에서 호출됩니다.
  1. dragging 값을 true로 설정합니다.
  2. zindex, ghosting, scroll과 관련된 option이 있는 경우 해당 option과 관련된 작업을 수행합니다.
  3. Draggables에 onStart이벤트가 발생했음을 알립니다.
  4. options에 starteffect가 있는 경우 starteffect를 수행합니다.
5. updateDrag(event, pointer)
- Draggables.updateDrag에서 document의 mousemove 이벤트에 등록된 updateDrag에 의해서 호출됩니다.
  1. this.dragging이 설정되어 있지 않은 경우 startDrag를 호출합니다.
  2. Droppables.show를 호출하여 현재 해당하는 Droppable이 있는 경우에 대한 처리를 수행합니다.
  3. Draggable을 이동시킵니다.
  4. options.scroll과 관련된 항목을 처리합니다.
6. finishDrag(event, success)
- mouseup 또는 esc키가 눌린 경우 호출됩니다.
  1. this.dragging을 false로 설정합니다.
  2. mouseup인 경우, Droppables.fire를 호출하여 Drop 이벤트에 대한 처리를 수행하게 합니다.
  3. Draggables.notify를 호출해서 onEnd이벤트가 발생했음을 알립니다.
  4. revert인 경우, startDrag시 저장하였던 시작점으로 복귀시킵니다.
  5. drag가 완료되었으므로 zindex를 복원시킵니다.
  6. endeffect설정이 되어있으면 이를 호출해줍니다.
  7. Draggables.deactivate를 호출하여서 활성중인 Draggable이 없음을 설정합니다.
7. keyProcess(event) - esc키가 눌린 경우, finishDrag를 호출합니다.
8. endDrag(event) - mouseup이벤트가 발생한 경우, stopScrolling()과 finishDrag를 호출합니다.
9. draw(point)  - mouse 이동에 따른 draggable의 이동 처리를 수행합니다. (repaint코드라고 보시면 될 듯)
10. stopScrolling()
11. startScrolling(speed)
12. scroll()
13. _getWindowScroll(w)

※ scrolling의 경우 제가 정확하게 파악하지 못해서 생략했습니다. ^^;;


관련링크
  Script.aculo.us - Draggable, Draggables, Droppables

Read/Write Web에 소개된 Dapper요약

출처:
  Read/Write web의 "Dapper: the Quest To Unlock Web Data(Legally)"
  Dapper.net

사용자 삽입 이미지

  Dapper는 어떤 서비스인가?
HTML을 읽어들여서 변환과정을 거쳐서 XML을 생성해내는 서비스입니다.
  1. Unstructured information from HTML
  2. - clean, transform and re-emit it -
  3. structured XML
크게보면 외부의 웹 사이트를 Dapper 서비를 통해서 Data를 생성해낸다고도 볼 수 있습니다.
Web site => (Dapper) => Data Service
  Dapper Applications의 특징
  1. 외부 링크를 사용할 수 있다. (외부 서비스의 HTML을 읽어올 수 있습니다. 통???)
  2. RSS, E-mail 그리고 HTML과 같은 다양한 포멧으로 결과물을 새성할 수 있다.
   Business and Legal questions
Dapper의 핵심기능인 '컨텐츠 스크랩 후 재사용'은 명백히 저작권(Copyright)에 위반된다는 문제점을 가지고 있습니다. Dapper는 어떠한 역할을 하려고 하는걸까요? 단순하게 컨텐츠를 Data로 생성하는 역할은 아닐 겁니다. 그렇다면?
 컨텐츠 소유자와 소유자의 컨텐츠를 사용하고 싶어하는 (want to remix the content) 회사를 연결시켜주는 역할(marketplace)입니다..

극복해야할 문제점은 1. 쉬운 사용법과 2. Yahoo!의 Pipes나 Teqlo, kapow와 같은 업체들과의 치열한 경쟁이다.

P.S Dapper를 사용해서 블로그의 컨텐츠를 RSS로 생성해보려고 했습니다만, -_-;;;  자바스크립트 에러가 나더군요. 그리고, 쉬운 사용법도 중요한 이슈가 될 것 같습니다.

2007년 5월 2일 수요일

Silverlight

Silverlight

Silverlight의 특징들
  • cross-browser, cross-platform을 지원(Win XP의 Firefox에서는 제대로 동작하지 않는다. -_-)
    Firefox에서 정상 동작이 가능합니다만, 제대로 보기 위해서는 html페이지에서 html 태그의 xmlns 삭제, DOCTYPE선언 부분을 삭제하셔야지만 볼 수 있습니다. 출처: Silverlight, Firefox, and Inline Xaml: A Solution to the Problem
  • very small download(4.2M)
  • streams video and audio,  HD 720p video quality.
  • refresh하는 경우 전체 페이지를 refresh하지 않는다.
  • WPF and XAML
  • Extensions to JavaScript : XAML의 control처리 시 javascript가 사용된다.
Silverlight Platform
Core Presentation Framework와 .NET Framework, Installer and Updater 세가지로 구성된다.

사용자 삽입 이미지

Core

.NET Framework for Silverlight
  • WPF - Rich controls that extend the features of standard Web browser controls 제공
  • Data - LINQ(Language intergrated Query) 제공
  • BCL(Base Class Library) - String, Regular Expressions, Input and output, Reflection, Collections and Globalizatoin지원
  • Networking - Remote services and data에 접근하는 기능을 제공한다.
  • CLR(Common Language Runtime) - Memory management, Garbage Collection, Type checking, Exception handling
  • DLR(Dynamic Language Runtime) - Dynamic compilation and execution of scripting languages(JavaScript & IronPython) 제공
그 외의 프로그램의 특징들
  • Isolated storage - local storage와 data의 caching지원
  • asynchronous programming - a background worker thread carries out programming tasks
  • File managment - 파일 업로드를 위한 File Open dialog box지원
  • HTML : managed code interaction - .NET 프레임 웍 프로그래머들이 웹페이지의 HTML DOM에서 직접 UI elements들을 생성해낼 수 있게 한다.
  • JSON
  • POX services
  • XML libraries - XMLReader and XMLWriter제공

출처: Microsoft의 Silverlight
 
관련자료:
Netflix, Silverlight의 HD급 스트리밍 기능을 이용한 데모관련 영상 from Webware
태요님의 Silverlight강좌 - S2 innovation day에서 처음 태요님의 세미나를 들었는데... 재미있더군요. 그리고, 말의 속도가 너무 빨라서 ... ^^

2007년 5월 1일 화요일

포천 워크샵 때 찍은 사진입니다.

U100이로 찍은 사진입니다.
사람이 없다는게 특징이라고나 할까요? ^^

사용자 삽입 이미지사용자 삽입 이미지
포천에 있는 허브 아일랜드 사진입니다. 허브 식물원보다는 상품과 식당만으로도 관광지를 만들 수 있다는 주요 사례중 하나가 아닐까 하는 생각이(-_-;;; - 제가 좀 삐딱하죠.. ㅋ)

사용자 삽입 이미지사용자 삽입 이미지사용자 삽입 이미지

해질녘 쯤의 산책나갈 때 찍은 사진입니다. 햇빛이 좋더군요.
사용자 삽입 이미지

워크샵에 갔던 팬션에서 찍은 노을입니다. 봄이네요 ^^

사용자 삽입 이미지

3장 클래스,객체,변수

  클래스
클래스 정의는 다음의 양식을 띕니다. (Object에서 상속)
class ClassName
    # 생성자
        def initialize(param)
            @name = name     #인스턴스 변수 앞에는 @를 사용한다.
            ....
        end

    # 기본제공, 객체의 ID와 인스턴스 변수를 출력
    def inspect
       ...
    end

    # obj를 나타내는 string을 리턴
    def to_s
       ...
    end
end

  상속과 메시지
상속은 < 기호를 사용합니다.
class SubClassName < SuperClassName
    def initialize(param)
       # 부모 초기화
       super(param)
       ...
    end
   
    # super의 사용 예
    def to_s
      super + ""
    end
end

- SubClass에서 메소드가 없는 경우 부모를 따라가며 해당하는 메소드를 찾습니다.
- 메소드 내에서 super 키워드를 매개변수 없이 호출하면, 현재 객체의 부모의 메소드 중 동일한 이름의 메소드를 호출하도록 요청한다. 때로는 현재 메소드 호출에 전달된 매개변수를 호출하도록 요청합니다.
- 루비 객체의 최상위 부모는 Object이다. Object에는 to_s를 비롯한 몇 개의 메소드를 정의하고 있습니다.

 객체와 속성
외부에서 객체의 상태에 접근하고 이를 다루는 메소드를 속성(attribute)라고 부릅니다.
Song 클래스의 name 접근 메소드를 정의한다면 다음과 같이 정의할 수 있습니다.
class Song
   def name
      @name
   end
end

song = Song.new()
puts song.name

접근 메소드를 attr_reader를 사용하여 쉽게 정의할 수 있습니다. 사용법은 위의 접근 메소드와 동일합니다.
class Song
   attr_reader :name
end

  쓰기 가능한 속성
쓰기 가능한 속성의 정의는 다음과 같습니다.
class Song
   def duration=(new_duration)
      @duration = new_duration
   end
end

song = Song.new()
song.duration = 300

attr_reader처럼 attr_writer를 사용해서도 쉽게 정의할 수 있습니다.
class Song
   attr_writer :duration
end

  가상의 속성
속성이 꼭 인스턴스 변수로 존재할 필요는 없습니다. 가상으로 정의가 가능합니다.
class Song
   def duration_in_minutes
      @duration/60.0
   end
   def duration_in_minutes=(new_duration)
      @duration = (new_duration*60).to_i
   end
위의 코드 정의를 보면 song.duration_in_minutes라는 변수를 사용할 수 있지만, 실제로는 변수가 정의되어 있지는 않습니다.

  클래스 변수와 클래스 메서드
클래스 변수(@@name처럼 @두 개를 사용하여 정의)는 그 클래스의 모든 객체가 공유하며, 클래스 메서드에 의해서만 접근할 수 있습니다.

class MyLogger
   private_class_method : new

   # 클래스 변수는 사용하기 전에 반드시 초기화되어야 합니다.
   @@logger = nil

   # 클래스 메서드의 정의는 클래스이름.메소드이름으로 정의합니다.
   def MyLogger.create
      @@logger = new unless @@logger
      @@logger
   end
end
위의 코드대로 정의하는 경우 new를 사용하여 클래스를 생성할 수 없고, MyLogger.create를 사용해서만 클래스를 생성할 수 있게 됩니다.(싱글턴 패턴)

  접근제어
접근에 대해서 설정할 수 있는 속성은 세가지가 있습니다.
  • Public 메소드 - 아무런 접근 제어를 하지 않습니다.
  • Protected 메소드 - 그 객체를 정의한 클래스와 그 하위 클래스에서만 접근할 수 있습니다.
  • Private 메소드 - private 메소드는 오직 현재 객체에서만 접근 가능합니다. 같은 클래스의 다른 객체에서도 접근이 불가능합니다.
class MyClass
   def method1     #기본값은 public입니다.
   end
protected      #이하 정의되는 메소드는 protected 접근을 가집니다.
   def method2
   end
   ...
private     #이하 정의되는 메소드는 private 접근을 가집니다.
   ...
public
   ...
end

또는 다음과 같이 정의할 수 있습니다.
class MyClass
   ...
   public :method1, :method2
   protected :method3
   private :method4
end

변수는 값을 저장하는게 아니라 레퍼런스(참조)를 저장하고 있다. (Java와 동일)

2장 Ruby.new 정리

  루비 설치, 맥에서 빌드하기
맥에서 루비 설치할 때 사용했던 관련 포스트(Building and installing Ruby 1.8.6 on Mac OS X Tiger)
RDT에 RDoc과 ri명령어를 넣어주기 위해서는 따로 설치가 필요
./configure --enable-install-doc --with-readline-dir=/usr/local --enable-pthread
make
make test
sudo make install
make check

  루비 기초 문법

루비는 객체지향 언어다.
클래스/메서드/ 인스턴스/생성자 - new 메서드로 호출
객체는 고유하다. 객체 아이디(Object identifier), 인스턴스 변수(Instance variables), 인스턴스 메서드(Instance method, 클래스 내부적으로 호출되는 메소드)를 갖는다.
루비에서 메소드 호출 형태 : Receiver.methodName()
자바와 달리 루비에서는 숫자 객체 자체에 절대값을 구하는 기능을 포함하고 있다.
  Math.abs(number) <-> number.abs
루비는 한 줄에 하나의 표현식만 쓴다면 세미콜론을 넣을 필요가 없다.
주석은 #을 사용하면 줄 끝까지 적용된다.

메소드를 정의하려면 def키워드가 필요하다.
메소드  다음에는 괄호로 싸인 메서드 형식인수를 쓴다.  def method(param)
중괄호로 구분하지 않는다.
키워드 end를 써준다.

변수는 대입을 하려 할 때, 자동으로 만들어진다.

문자열을 만드는 방법 - 문자열 리터럴을 사용한다. ''""를 붙여서 문자열 리터럴을 만든다.
 - 작은 따옴표는 루비에서 사소한 작업시 사용하며
 - 큰 따옴표는 더많은 작업을 한다. 대표적인 것으로 \n에 대한 개행 처리를 수행한다.
표현식을 삽입한다. #{expression}과 같은 형태가 있으면 이는 expression의 값으로 표현된다.
전역변수($name)나 인스턴스 변수(@name)도 다음과 같이 "#$greeting #@name"형태로 사용이 가능하다.
메소드에서는 마지막으로 실행된 표현식의 결과값이 리턴된다.

  Naming Rule
지역변수, 메서드형식인수, 메서드이름은 모두 소문자나 밑줄(_)로 시작되어야 한다.
전역변수는 $
인스턴스 변수는 @
클래스 변수는 @@
클래스 이름, 모듈 이름, 상수는 대문자로 시작된다.
인스턴스 변수는 단어 사이에 밑줄을 넣어서 구분하고, 클래스 이름의 경우에는 대문자로 시작한다.

  배열과 해시
Array는 []로 정의 하며, 스트링으로 구성된 배열은 %w{}를 사용하여 쉽게 정의할 수 있다.
Hash는 {}로 정의하며, {key => value} 형태로 정의한다. 객체가 없는 경우는 nil을 리턴한다.

  제어문
if/elsif/else/end 와 같이 정의할 수 있다. 종료는 end로 끝난다.
while 조건문
 내용
end

내용이 한 줄인 경우, 구문 변경자(statement modifier)를 사용하여 한 줄로 표시할 수 있다.
if radiation >3000
  puts "위험합니다."
end
 => puts "위험합니다." if radiation >3000

  정규표현식
if line ~= /Perl|Python/
  puts "스크립트 언어에 대한 언급: #{line}"
end
~= 특정 문자열이 정규표현식과 매치되는지 검사하는데 사용할 수 있다.

  블록과 반복자
코드블록은 중괄호do...end로 묶인 코드다.
{puts "Hello"}
do
  puts "Hello"
end
블록을 메소드에서 다시 호출하기 위해서는 yield를 사용해서 호출할 수 있다.
블록에 매개변수를 전달하려면 |를 사용한다. call_block {|param| ...}

  읽기와 쓰기
puts는 개행문자를 문자열의 끝 부분에 더해서 출력을 해준다.
print는 개행문자 없이 문자열만을 출력해준다.
둘 다(puts/print) 어떤 I/O 객체에든 사용할 수 있다.
printf(C나 perl)과 동일하다.
입력, gets 메소드를 사용하면 스트림에서 문자열 한 줄을 읽어들인다.