1 / 90

Ruby Language 입문 및 소개

Ruby Language 입문 및 소개. 2006. 9. 이 지 행. Ruby. 1990 년대 일본인 Yukihiro Matsumoto (a.k.a matz) 에 의해 만들어짐 . 최근 몇 년 사이 미국에서도 엄청나게 주목을 받고 있음 특징 Interpreted scripting language for quick and easy objected-oriented language Perl 과 같은 편리성과 생산성 Smalltalk 와 같은 여러 OOP 언어에서 영향을 받은 pure OOP

yanka
Download Presentation

Ruby Language 입문 및 소개

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Ruby Language 입문 및 소개 2006. 9. 이 지 행

  2. Ruby • 1990년대 일본인 Yukihiro Matsumoto (a.k.a matz)에 의해 만들어짐. • 최근 몇 년 사이 미국에서도 엄청나게 주목을 받고 있음 • 특징 • Interpreted scripting language for quick and easy objected-oriented language • Perl 과 같은 편리성과 생산성 • Smalltalk 와 같은 여러 OOP언어에서 영향을 받은 pure OOP • 배우기 쉽고, 읽기 쉬운 스타일 • Open Source. 어느 OS에서나, 자유롭게 이용할 수 있음 • 프로그래밍 자체가 매우 재미있음 (fun) • 전체적으로 잘 균형잡힌 이상적인 언어 : elegant, fun and pragmatic • Ruby is a pure object-oriented programming language with a super clean syntax that makes programming elegant and fun. Ruby successfully combines Smalltalk's conceptual elegance, Python's ease of use and learning, and Perl's pragmatism. Ruby originated in Japan in the early 1990s, and has started to become popular worldwide in the past few years as more English language books and documentation have become available.

  3. 참고도서 • Programming Ruby – The Pragmatic Programmers’ Guide, 2nd • Dave Thomas, et.al.. • Ruby Community에서 유명함 : PickAxe • 1판은 인터넷에서 무료로 볼 수 있음 • 기타 참고자료 • 루비 공식 사이트 : http://www.ruby-lang.org • Ruby on Rails : http://www.rubyonrails.org/ • Ruby Cookbook • Agile Web Development with Rails: A Pragmatic Guide • 번역서 아직 하나도 없음

  4. 목 차 • Ruby.new • Ruby.each • Class, Object and Variable, Container, Block and Iterator • Standard Type, Method, Expression, Exception, Modules, I/O • Ruby.inspect • Threads, Tool, Ruby and Web • Duck Typing • Classes and Objects in Ruby • Etc…

  5. Ruby.new

  6. Ruby : 순수 객체지향 언어 • 거의 모든것이 Object. 결과물도 Object. • 심지어 현재 Context 도 Object, 클래스도 Class라는 클래스의 Object • Method 호출 보다는 Message를 Object에 전달한다는 개념이 더 강함 • 함수 호출시 괄호 없어도 됨 • 숫자나 문자열도 Integer, String의 Object • 세미콜론 없어도 됨. Ruby는 Line 단위 파싱이 기본임 song1 = Song.new("Ruby Tuesday") "gin joint".length "Rick".index("c") -1942.abs sam.play(song) number = Math.abs(number) // Java code

  7. 기본 적인 사항들 • 함수 선언 및 사용 • def ~ end • 변수 interpolation : #{ expression } • 함수내에 return이 없으면 맨 마지막 expression을 리턴 • 주의 : 함수 선언에 입력, 출력 변수에 대한 Type 설정 이 없음 def say_goodnight(name) result = "Good night, #{name}“ return result end puts say_goodnight('Pa') def say_goodnight(name) "Good night, #{name}" end puts say_goodnight('Ma')

  8. Array 하나의 Array에 여러 Type의 데이터가 들어갈 수 있음 재미있는 Operator들 많이 있음 Hash Index 대신 key 값이 들어가면 됨 inst_section = { 'cello' => 'string', 'clarinet' => 'woodwind', 'drum' => 'percussion', 'oboe' => 'woodwind', 'trumpet' => 'brass', 'violin' => 'string' } inst_section['oboe'] inst_section['cello'] inst_section['bassoon'] histogram = Hash.new(0) histogram['key1'] -> 0 histogram['key1'] += 1 histogram['key1'] -> 1 a = [ 1, 'cat', 3.14 ] # array with three elements # access the first element a[0] -> 1 # set the third element a[2] = nil # dump out the array a -> [ 1, 'cat', nil ] a = [ 'ant', 'bee', 'cat', 'dog', 'elk' ] a[0]  “ant” a[3] -> “dog” # this is the same: a = %w{ ant bee cat dog elk } a[0]  “ant” a[3] -> “dog”

  9. 변수명 • Convention(관습)이 아니라 interpreter가 변수명을 보고 다르게 처리하는 규칙이다. • 대소문자, @를 정확히 사용해야 함 • nil • C나 Java의 Null Pointer와는 다름 : nil도 하나의 객체임 • C나 perl의 0과도 다름 : 0이 아니라 nil이라는 객체임

  10. while end • 괄호 없어도 됨 while weight < 100 and num_pallets <= 30 pallet = next_pallet() weight += pallet.weight num_pallets += 1 end square = 2 square = square*square while square < 1000 if count > 10 puts "Try again" elsif tries == 3 puts "You lose" else puts "Enter a number" end puts "Danger, Will Robinson" if radiation > 3000 • Control Structure • if elsif else end • Perl 스타일의 modifier 지원 • Regular Expression • Built-in type : 라이브러리가 아님(Perl 과같이 강력함) • 대부분의 Operation 지원 if line =~ /Perl|Python/ puts "Scripting language mentioned: #{line}" end line.sub(/Perl/, 'Ruby') # replace first 'Perl' with 'Ruby' line.gsub(/Python/, 'Ruby') # replace every 'Python' with 'Ruby'

  11. { puts "Hello" } # this is a block do ### club.enroll(person) # and so is this person.socialize # end ### • Blocks and Interators • Block 선언 • Block을 method와 연결시키기 • Function pointer와는 비슷하지만 많이 다르다. • Method와 해당 Block이 연결되며, method에 함수 뿐 아니라, Context가 함께 전달된다. (Closure) • Method 내의 yield 함수에 의해 연결된 Block이 실행된다 def call_block puts "Start of method" yield yield puts "End of method" end call_block { puts "In the block" } Start of method In the block In the block End of method

  12. Block과 변수 주고받기 • Method에서 꺼꾸로 Block에게 | var1 , val2, … | 형태로 변수를 전달할 수 있음 • Method 내에서 여러 차례 Block을 호출  Interator • Iterator 예 animals = %w( ant bee cat dog elk ) # create an array animals.each {|animal| puts animal } # iterate over the contents # within class Array... def each for each element # <-- not valid Ruby yield(element) end end [ 'cat', 'dog', 'horse' ].each {|name| print name, " " } 5.times { print "*" } 3.upto(6) {|i| print i } ('a'..'e').each {|char| print char } cat dog horse *****3456abcde

  13. Ruby.each

  14. Classes, Objects and Variables • Class 선언 및 상속 • initialize : 생성자에 해당됨. 밖에서는 new를 이용하여 호출 • 이미 정의되어 있는 Class에 동적으로 method를 붙이거나 변경시킬 수 있음 class Song def initialize(name, artist, duration) @name = name @artist = artist @duration = duration end end song = Song.new("Bicylops", "Fleck", 260) song.to_s  “#<song:0x1c7ec4>” class Song def to_s "Song: #@name--#@artist (#@duration)" end end song = Song.new("Bicylops", "Fleck", 260) song.to_s  “Song: Bicylops—Fleck (260)”

  15. 상속 • 다중상속 허용안함 • Super함수로 부모의 생성자 호출 • 참고 : 모든 클래스는 Object라는 부모클래스로부터 상속됨 • 참고 : @lyrics는 그 자체로 변수명이며, instance variable을 나타냄. 따로 선언할 필요는 없다 • Attribute • Object 는 내부 State(instance variable)을 가지고 있는데, Ruby에서는 기본적으로 이것을 접근할 수(볼 수도, 쓸 수도) 없다. • 하지만, 외부에서 Object의 어떤 값이나 상태를 요청할 경우 밖에서 볼 수 있도록 Class가 제공하는데, 이를 Attribute라고 한다. • Attribute는 밖에서 볼때는 Variable처럼 보이지만 내부적으로는 method로 구현된다 class KaraokeSong < Song def initialize(name, artist, duration, lyrics) super(name, artist, duration) @lyrics = lyrics end end

  16. Readable attribute 일종의 getter 함수 밖에서 볼때는 변수를 조회하는 것 같음 하지만 이것은 아래와 같이 간단하게 표현할 수 있다. • Readable attribute • 일종의 setter 함수 • 밖에서 볼때는 변수에 대입하는 것 같음 • 하지만 이것은 아래와 같이 간단하게 표현할 수 있다. class Song def name @name end def artist @artist end def duration @duration end end song = Song.new("Bicylops", "Fleck", 260) song.artist  “Fleck” song.name  “Bicylops” song.duration  260 class Song def duration=(new_duration) @duration = new_duration end end song = Song.new("Bicylops", "Fleck", 260) song.duration  260 song.duration = 257 # update song.duration  257 class Song attr_writer :duration end song = Song.new("Bicylops", "Fleck", 260) song.duration = 257 class Song attr_reader :name, :artist, :duration end

  17. class Song def duration_in_minutes @duration/60.0 # force floating point end def duration_in_minutes=(new_duration) @duration = (new_duration*60).to_i end end song = Song.new("Bicylops", "Fleck", 260) song.duration_in_minutes  4.3333333 song.duration_in_minutes = 4.2 song.duration  252 • Virtual attribute • 내부 instance variable을 변환시켜 외부에 보여줄 수 있다. • Method이지만 밖에서 볼때는 하나의 변수처럼 보인다. • Class Variable ( @@변수명) • Class에 속하는 object 들이 공유하는 변수 • 하나의 Class에 유일하게 존재함 • Class Method • 특정한 Object와 관계없이 호출되는 함수 song = Song.new(....) File.delete("doomed.txt")

  18. class SongList MAX_TIME = 5*60 # 5 minutes def SongList.is_too_long(song) return song.duration > MAX_TIME end end song1 = Song.new("Bicylops", "Fleck", 260) SongList.is_too_long(song1) • Class Method 정의 • 크래스명.메소드명 으로 선언함 • Singletons • 한 시스템에 해당 Class에 대한 Object는 오로지 하나만 존재하도록 하는 디자인 패턴의 하나 • new 함수를 private으로 변경시킴 • Object 생성은 따로 제공되는 method를 통해서 이루어짐 • Class Variable에 Object를 유지 class MyLogger private_class_method :new @@logger = nil def MyLogger.create @@logger = new unless @@logger @@logger end end

  19. Access Control • Public method : 누구나 호출할 수 있음 • Protected method : 해당 클래스의 Object와 서브클래스에서만 호출 가능 • Private method : receiver로 전달할 수가 없다. 즉, 자기 자신만 쓸 수 있다. • 참고1 : 다른 언어의 protected, private 과는 약간 다름 • 참고2 : variable에는 access control 자체가 없다. (무조건 private) 대신 attribute 개념이 있음 class MyClass def method1 # default is 'public' #... end protected # subsequent methods will be 'protected' def method2 # will be 'protected' #... end private # subsequent methods will be 'private' def method3 # will be 'private' #... end public # subsequent methods will be 'public' def method4 # and this will be 'public' #... end class MyClass def method1 end # ... and so on public :method1, :method4 protected :method2 private :method3 end

  20. person1 = "Tim" person2 = person1 person1[0] = 'J' person1  “Jim” person2  “Jim” • Variable • Variable은 Object로의 reference이다 person1 = "Tim" person2 = person1.dup person1[0] = "J" person1  “Jim” person2  “Tim” person1 = "Tim" person2 = person1 person1.freeze person2[0] = "J“ 에러

  21. Containers, Blocks, and Iterators • Container : Object의 Reference를 담고 있음 • Array 읽기 a = [ 1, 3, 5, 7, 9 ] a[2]  5 a[-1]  9 a[-2]  7 a[-99]  nil a = [ 1, 3, 5, 7, 9 ] a[1, 3]  [3, 5, 7] a[3, 1]  [7] a[-3, 2]  [5, 7] a = [ 1, 3, 5, 7, 9 ] a[1..3]  [3, 5, 7] a[1...3]  [3, 5] a[3..3]  [7] a[-3..-1]  [5, 7, 9] • 잘못된 index : nil • 음수 : Array 뒤부터 • [시작, 개수] : 시작 index 부터 개수만큼의 Array • [시작..끝] : 시작부터 끝까지의 Array • [시작..끝] : 시작부터 끝 하나 전까지의 Array

  22. Array 쓰기 a = [ 1, 3, 5, 7, 9 ] a[2, 2] = ‘cat’ [1, 3, “cat”, 9] a[2, 0] = ‘dog’ [1, 3, “dog”, “cat”, 9] a[1, 1] = [9, 8, 7]  [1, 9, 8, 7, “dog”, “cat”, 9] a[0..3] = []  [“dog”, “cat”, 9] a[5..6] = 99, 98  [“dog”, “cat”, 9, nil, nil, 99, 98] • Size를 넘어서는 index에 쓰기 • 중간은 nil로 채워짐 • [시작, 개수] • 시작 index 부터 개수 만큼의 Array 부분을 새로운 Array로 끼워넣음 • [시작..끝] • 시작부터 끝까지의 Array 부분을 새로운 Array로 끼워넣음 • [시작...끝] • 시작부터 끝 하나 전까지 …

  23. h = { 'dog' => 'canine', 'cat' => 'feline', 'donkey' => 'asinine' } h.length  3 h['dog']  “canine” h['cow'] = 'bovine‘ h[12] = 'dodecine' h['cat'] = 99 h  { “cow” => “bovine”, “cat” => 99, 12=> “dodecine”, “donkey” => “asinine”, “dog” => “canine” } • Hash • Index 대신 key를 이용하여 조회 • Block and Iterator • Block • 기본적인 다른언어의 Block 개념 뿐 아니라, • Method call에 덧붙여 들어갈 수 있고 그 Block은 context를 유지한 채로 method에 들어가 나중에 실행된다

  24. def three_times yield yield yield end three_times { puts "Hello" } Hello Hello Hello • Block을 이용한 Logic과 Display의 분리 • fib_up_to 함수에는 logic만 들어있다. • Display는 block으로 받아들여 처리한다. • 다른 언어의 유사한 방식 (fuction pointer call-back, STL) 등에 비하여 • 전달 과정 및 수행 과정이 알기쉽고 투명하다 • 전달하려는 Block의 Context 를 전달할 수 있다 def fib_up_to(max) i1, i2 = 1, 1 # parallel assignment (i1 = 1 and i2 = 1) while i1 <= max yield i1 i1, i2 = i2, i1+i2 end end fib_up_to(1000) {|f| print f, " " } 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987

  25. [ 1, 3, 5, 7, 9 ].each {|i| puts i } 1 3 5 7 9 ["H", "A", "L"].collect {|x| x.succ }  [“I”, “B”, “M”] • Block을 이용한 Iterator 수행 예 f = File.open("testfile") f.each do |line| puts line end f.close 첫재쭐… 둘째줄… • [1,3,5,7].inject(0) {|sum, element| sum+element} • 16 • [1,3,5,7].inject(1) {|product, element| product*element} •  105 • 다른 언어의 Iterator와의 차이점 • External Iterator : Java나 C++의 경우 외부의 Iterator가 실제로 Iterate시킬 객체를 control 한다 • Internal Iterator : Ruby는 객체 자신이 Iterate를 시킨다 • 간단하고 투명하다. • Iteration을 자신의 객체에 맞게 만들고 발전시킬 수 있다.

  26. class File def File.open_and_process(*args) f = File.open(*args) yield f f.close() end end File.open_and_process("testfile", "r") do |file| while line = file.gets puts line end end • Block 과 Transaction • Transaction을 표준화 시켜서 만들 수 있다. • 실제 Processing 하는 부분은 파일을 열고 닫기 위해 해야하는 작업을 알 필요가 없다 • 항상 파일이 Close 되는 것을 보장할 수 있다

  27. class File def File.my_open(*args) result = file = File.new(*args) # If there's a block, pass in the file and close # the file when it returns if block_given? result = yield file file.close end return result end end • Block이 주어지지 않았을 때에는 그냥 File 객체를 리턴하도록 할 수도 있다 (Ruby-Style의 구현임)

  28. Closure • Block의 실행 내용과 함께 해당 Block의 Context(참조가능 Method, 변수들, Scope 등등의 모든 사항)가 함께 전달되어 Block을 전달받는 곳과 완전히 연결되는 Programming 언어적 방식 • 일반적인 구현방식 • 상속을 받고, 해당 클래스에 구현한다 • 버튼의 개수 만큼 클래스를 만들어야 할 것이다. class StartButton < Button def initialize super("Start") # invoke Button's initialize end def button_pressed # do start actions... end end start_button = StartButton.new

  29. class JukeboxButton < Button 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 } • Closure를 이용한 방식 • 버튼 생성시 해당 버튼이 동작해야할 내용을 함께 전달한다 • 클래스 내부에서는 songlist라는 객체를 전혀 알 필요 없이 수행된다 (다른언어라면 어떻게 구현할 것인가? Songlist 객체 전달? Void* 전달? Songlist가 아니라 다른 객체에 대한 구현을 할 때에는?) • Subclassing 필요없이, 하나의 클래스만으로 여러가지의 버튼을 만들어낼 수 있다.

  30. Standard Types • Number • 물론 객체이다. • Size제한 같은 것은 없다. • Fixnum, Bignum 등이 내부적으로 있으며 변환은 자동으로 된다. • String • 내부적으로는 결국 8bit sequence 이다. • 일본애들이 만든거라 code문제도 고려되어 있다. • 75개 표준 method가 함께 제공된다 • Regular expression과 함께 쓸 수 있기 때문에 상당히 강력하다

  31. class WordIndex def initialize @index = {} end def add_to_index(obj, *phrases) phrases.each do |phrase| phrase.scan(/\w[-\w']+/) do |word| # extract each word word.downcase! @index[word] = [] if @index[word].nil? @index[word].push(obj) end end end def lookup(word) @index[word.downcase] end end • Regular Expression, Hash 등을 이용해 색인/검색기 구현 • 마치 pseudo-code - 같다. • 짧고 간결하게 표현할 수 있다. • natural한 문장처럼 자연스럽게 쓰고 읽을 수 있다. (Readability와 Writability가 함께 높다)

  32. Range • 범위를 기본적인 자료형으로 가지고 있음 • “..” : 맨 마지막 포함, “…” : 맨 마지막 포함하지 않음 • 다른 언어에서는 찾아볼 수 없는 Type • Sequence, condition, interval 3가지로 사용됨 • Range as Sequence • Range operation으로 sequence 생성 • Range as Condition • 앞의 조건이 만족하는 순간 부터 뒤의 조건이 만족하는 순간 까지 를 의미함 1..10 'a'..'z' (1..10).to_a  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] ('bar'..'bat').to_a  [“bar”, “bas”, “bat”] while line = gets puts line if line =~ /start/ .. line =~ /end/ end

  33. (1..10) === 5  true (1..10) === 15  false (1..10) === 3.14159  true ('a'..'j') === 'c‘ true ('a'..'j') === 'z‘ false • Interval • Case equality “===“ 를 이용하여 값이 범위에 들어가는 지 비교 가능 (in 의 의미) • Regular Expression • 언어에서 기본적으로 제공하는 Type이다 • Perl처럼 강력하게 쓸 수 있고, 객체 형식으로 이용할 수도 있다 • 변수 만들기 a = Regexp.new('^\s*[a-z]') b = /^\s*[a-z]/ c = %r{^\s*[a-z]}

  34. a = "the quick brown fox" a.sub(/[aeiou]/, '*') “th* quick brown fox" a.gsub(/[aeiou]/, '*') “th* q**ck br*wn f*x" a.sub(/\s\S+/, '') “the quick brown” a.gsub(/\s\S+/, '') “the” • 사용 예 (substitution) • 문자열 변환, gsub는 해당하는 모든 패턴 • 문자열 a는 변하지 않고, 새로 변환된 문자열이 리턴되는 것임 (문자열 a를 바꾸려면 sub! , gsub! 호출) • 단순 치환이 아니라 어떤 함수를 적용할 수 있음 • 이럴 경우 바뀔 문자를 리턴하는 Block을 던지면 끝! a = "the quick brown fox" a.sub(/^./) {|match| match.upcase } “The quick brown fox” a.gsub(/[aeiou]/) {|vowel| vowel.upcase }  “thE qUIck brOwn fOx”

  35. Method • Logic의 분리 • 덧셈 또는 곱셈을 1~10까지 수행 print "(t)imes or (p)lus: " times = gets print "number: " number = Integer(gets) if times =~ /^t/ puts((1..10).collect {|n| n*number }.join(", ")) else puts((1..10).collect {|n| n+number }.join(", ")) end Interation은 동일하지만 Logic이 다르다는 이유로 똑같은 Display를 두번하고 있음 print "(t)imes or (p)lus: " times = gets print "number: " number = Integer(gets) if times =~ /^t/ calc = lambda {|n| n*number } else calc = lambda {|n| n+number } end puts((1..10).collect(&calc).join(", ")) Block에 담긴 Logic을 변수에 저장해 전달 Display를 한번만 할 수 있음

  36. Expression • Ruby에서 모든 문장은 Expression이다  Object가 리턴된다. • if문 case 문도 리턴한다 • Return이 없으면 마지만 문장이 리턴된다 song_type = if song.mp3_type == MP3::Jazz if song.written < Date.new(1935, 1, 1) Song::TradJazz else Song::Jazz end else Song::Other end rating = case votes_cast when 0...10 then Rating::SkipThisOne when 10...50 then Rating::CouldDoBetter else Rating::Rave end

  37. (a*b)+c 와 아래문장은 동일!! (a.*(b)).+(c) • 모든 operation은 method다 • 몇 가지 새로운 비교연산자 • “===“ • case의 when 문에 쓰이는 연산자. 속한다 포함된다는 의미이다 • “<=>” • Comparison 연산자 : 작다, 같다, 크다를 -1, 0, 1 로 만들어 리턴하는 연산자 • “eql?” • 값뿐만 아니라 type도 비교한다. • 1==1.0 은 true 하지만 1 eql? 1.0 은 false • “equal?” • Object가 만들어질때는 내부적으로 ID가 부여되는데, 이 ID가 같은지 여부를 알 수 있음

  38. Range 이용 변수 없이 직접 조건을 넣어서 kind = case year when 1850..1889: "Blues" when 1890..1909: "Ragtime" when 1910..1929: "New Orleans Jazz" when 1930..1939: "Swing" when 1940..1950: "Bebop" else "Jazz" end leap = case when year % 400 == 0: true when year % 100 == 0: false else year % 4 == 0 end • Case문 : 자연스러우면서도 강력함 • 내부적으로는 “===“ 연산자로 동작합 String 비교, Regex 비교 등이 자연스러움 case input_line when "debug" dump_debug_info dump_symbols when /p\s+(\w+)/ dump_variable($1) when "quit", "exit" exit else print "Illegal command: #{input_line}" end Class의 경우 “===“는 해당클래스, 또는 부모클래스의 Object인지를 판단한다 case shape when Square, Rectangle # ... when Circle # ... when Triangle # ... else # ... end

  39. for song in songlist song.play end 위 문장은 사실 아래와 같다 songlist.each do |song| song.play end for i in ['fee', 'fi', 'fo', 'fum'] print i, " " end for i in 1..3 print i, " " end • for … in • 다양한 Iterator가 많기 때문에 for문은 Ruby에서 잘 사용되지 않는다 • each만 구현하면 어느 객체던지 for in 을 돌릴 수 있다. • Loop관련 예약어 • break : Loop 탈출 • next : 더 실행 안하고 다음 Loop로 (continue) • redo : 더 실행 안하고, 현재 상태에서 Loop 한번더 • retry : Loop를 완전 rollback해서 처음부터 다시돌림

  40. def do_until(cond) break if cond yield retry end i = 0 do_until(i > 10) do print i, " " i += 1 end • 사용자 정의 Loop • do_until 은 마치 예약어처럼 보인다. • block을 던질 수 있기 때문에(closure), 다른 언어에서는 syntax로 지원해야 하는 많은 기능들이 간단한 함수 정의로 구현된다.  Ruby 스타일, Ruby가 앞으로도 발전/진화할 가능성이 많은 이유

  41. Exceptions • begin ~ end 사이에서 Exception이 발생하면 rescue문으로 해당 Exception 객체와 함께 들어간다 • Java의 try ~ catch와 비슷 • 참고 : Java는 굉장히 엄격하게, method에서 Exception 관련사항을 정의하고, 위에서는 잡아주고 해야하지만 Ruby는 비교적 단순하다 op_file = File.open(opfile_name, "w") begin # Exceptions raised by this code will # be caught by the following rescue clause while data = socket.read(512) op_file.write(data) end rescue SystemCallError $stderr.print "IO failed: " + $! op_file.close File.delete(opfile_name) raise end

  42. f = File.open("testfile") begin # .. process rescue # .. handle error else puts "Congratulations-- no errors!" ensure f.close unless f.nil? end • ensure • begin ~ end 사이에서 반드시 Exception과 관계없이 실행되는 부분. Java의 finally 와 비슷 • else • rescue에 들어가지 않은 경우.. 즉 에러없이 성공적으로 끝냈을 때에만 들어가는 부분 • retry • 중간에 retry 명령을 만나면 begin문 처음부터 다시 시작한다 • 네트웍 에러시 재시도를 한다던지 알 수 있다

  43. Module • Module은 Method, Class, Constant 등을 하나의 그룹으로 묶는 일을 한다 • 모듈은 각각의 namespace를 가진다 • 예를들어 C는 다른 라이브러리를 include하면 함수명이 충돌할 수 있다. (그래서 C에서는 큰 규모의 개발때 Naming 규칙을 정하는 것이 중요하다) • 하지만 Ruby는 Module내에서만 겹치지 않으면 된다 • 모듈을 이용하여 Mixin 을 구현할 수 있다 • Ruby에서는 Mixin이란 개념을 이용하여 Multiple inheritance를 구현한다.

  44. Mixin • 다른 클래스에 Module을 밀어넣는(include) 모듈 • Ruby에서는 다중상속을 금지하지만, Mixin을 이용하여 클래스의 기능을 확장할 수 있다 module Debug def who_am_i? "#{self.class.name} (\##{self.id}): #{self.to_s}" end end class Phonograph include Debug # ... end class EightTrack include Debug # ... end ph = Phonograph.new("West End Blues") et = EightTrack.new("Surrealistic Pillow") ph.who_am_i?  “Phonograph (#945760): West End Blues et.who_am_i?  “EightTrack (#945740): Surrealistic Pillow Debug 모듈을 include 시켜서 두 클래스 모두 디버깅 기능을 가지게 되었음 그렇다고 Debug 클래스를 상속받은 것은 아님

  45. class Song include Comparable def initialize(name, artist, duration) @name = name @artist = artist @duration = duration end def <=>(other) self.duration <=> other.duration end end song1 = Song.new("My Way", "Sinatra", 225) song2 = Song.new("Bicylops", "Fleck", 260) song1 <=> song2  -1 song1 < song2  true song1 == song1  false song1 > song2  false • Comparable Module을 include 시킴 • “<=>” method만 구현하면 나머지 연산은 자동으로 구현됨

  46. class VowelFinder include Enumerable def initialize(string) @string = string end def each @string.scan(/[aeiou]/) do |vowel| yield vowel end end end vf = VowelFinder.new("the quick brown fox jumped") vf.inject {|v,n| v+n }  “euiooue” • Enumerable Module을 include 시킴 • “each” method만 구현하면 나머지 연산은 자동으로 구현됨

  47. Module include와 C언어의 include 가 다른점 • C는 모듈과 관계없이 단순히 physical한 해당 파일을 포함(include)시키는 것이다. 하지만, Ruby의 include는 Logical한 묶음이 포함되는 것이다. • Ruby의 include는 해당 모듈의 기능이 단순히 복사되어서 클래스에 합쳐지는 것이 아니다. 클래스에서 include된 모듈로의 Reference(참조)만 만들어지는 것이다 • Mixin과 Java 의 Interface가 다른점 • Java는 반드시 Abstract 해야 한다 • Mixin되더라도 원래의 클래스의 Type이 변하는 것은 아니다. 예를들어 해당 클래스가 Comparable Type이 되는 것이 아니라, “<=>”, “<“ 와 같은 메세지들을 처리할 수 있는 method를 가지고 있는 함수가 되는 것이다. (뒤쪽의 Duck Typing 참조)

  48. method명이 겹치면? • 실행될 method는 우선순위에 의해 결정된다. 자신 클래스, 자신이 가지고 있는모듈, 상위 클래스, 상위클래스의 모듈 등의 순 • 다른 파일 포함시키기 • built-in 라이브러리가 아닌, 다른 라이브러리에 들어있는 모듈을 사용할 때는 해당 라이브러리를 포함시켜야 한다 • load : 해당 파일을 부를때 마다 다시 포함시킨다. • load ‘filename.rb’ • require : 주로 require를 사용한다. 해당파일을 한번만 포함시킨다. 확장자는 쓰지 않는다. • require ‘filename’

  49. I/O • I/O 관련된 함수들은 Kernel 이란 모듈에 대부분 구현되어있다. • 참고1 : Kernel 모듈은 Object 라는 클래스에 include 되어 있으므로 모든 클래스는 그 기능을 가지고 있다 • 참고2 : runtime 환경도 하나의 Object이다. 따라서, putc, puts 같은 것은 현재 자신(runtime)이 이미 가지고 있는 method인 것이다 File.open("testfile") do |file| file.each_byte {|ch| putc ch; print "." } end File.open("testfile") do |file| file.each_line {|line| puts "Got #{line.dump}" } end

  50. Networking • TCP, UDP, SOCKS, Unix Domain Socket 같은 것 기본으로 지원 • HTTP, SOAP, FTP 관련 라이브러리 다양하게 구비하고 있음 require 'socket' client = TCPSocket.open('127.0.0.1', 'finger') client.send("mysql\n", 0) # 0 means standard packet puts client.readlines client.close require 'net/http' h = Net::HTTP.new('www.pragmaticprogrammer.com', 80) response = h.get('/index.html', nil) if response.message == "OK" puts response.body.scan(/<img src="(.*?)"/m).uniq end

More Related