mm Home

Ruby 기본 문법 본문

기타

Ruby 기본 문법

jess_m 2017. 9. 12. 16:38

사내에서 상당히 많은 레거시 프로젝트가 루비로 개발되어 있다.

최근에는 레거시 프로젝트 이외에는 잘 안쓰이는것 같고, 한창 국내에서 루비가 떠오를때 많이 사용되었던것 같다. 


루비가 간편하고 빠르게 개발할 수 있다는 건 익히 들었지만 실제로 접하기 전까지는 추상적으로만 알고 있었다.

루비온레일즈(RoR)로 짜여진 프로젝트를 맡게 되어서 공부를 하게 되었는데 재미있었다.

확실히 철저한 관습에 따른 편리성이 자바&스프링 개발자인 나에게 큰 매력으로 다가왔다.


음.. 그냥 서론은 그만하고 그때 공부했던 내용을 올린다 ㅎㅎ




Ruby 철학

 

Ruby 뜻 : 마츠모토 유키히로 지인의 탄생석

스트레스가 없는 쉬운 프로그래밍!을 위하여

스크립트 언어.

 

당시 이상적인 프로그래밍 언어는 반드시 이룰 수 있는 것이라고 믿었고, 가능하면 그런 언어를 만드는 디자이너가 되고 싶었습니다. (중략)
나는 행복해지기 위해서 살아간다고 믿습니다. 이런 믿음에 따라, 루비는 프로그래밍을 쉬우면서도 즐거운 일로 만들기 위해 디자인 되었습니다. 루비는 여러분이 프로그래밍의 창조적인 면에만 집중할 수 있도록 해주고, 스트레스를 줄여줄 것입니다.
 
- 마츠모토 유키히로.  Ruby doc 머릿말에서.. (http://ruby-doc.com/docs/ProgrammingRuby/)
by https://namu.wiki/w/Ruby


Ruby 문법
  • 변수
    • String

      var1 = 'test1'             
      var2 = "test2 #{var1}"      # "test1 test2"

      ' 와 " 사용 가능
      " :  #{변수명} 을 통해 변수값을 바로 집어넣을 수 있다 (interpolation)

    • Interger (Float)
      • 정수와 실수형 존재
    • Array

      var1 = ['A', 'B', 'C']
      var[1] = 'C'        #대입
    • Hash

      var1 = {'A'=>1, 'B'=>2}       #hash 안에서의 대입 기호는 =>
      var1['B'] = 3           #대입
    • Symbol
      immutable 문자열

      #mutable
      irb(main):042:0> "test1".object_id
       
      => 70157116771260
       
      irb(main):043:0> "test1".object_id
       
      => 70157116790160
      #### 같은 문자열도 다른 메모리에 위치 -> 서로 다른 메모리 공간 차지
        
        
      #immutable
      irb(main):070:0> :test1.object_id
       
      => 525128
       
      irb(main):071:0> :test1.object_id
       
      => 525128
      #### 같은 문자열 같은 메모리에 위치
  • Scope
    • ### 변수의 앞 기호를 통해 Scope 구분
      var1            # local_variable
      $var2           # global_variable
      @var            # instance_variable
      @@var           # class_variable (static variable)
  • 반복문
    • loop do      (무한루프)

      i = 0
      loop do
          i += 1
          puts i
          next if i < 3            #next = continue
          break if i  > 4      #break = break
      end
    • for (2가지 방법)

      for i in 1..3
         puts i
      end
      for OBJ in OBJLIST
         #process
      end
       
       
      # or
       
       
      OBJLIST.each do |OBJ|
         #process
      end
    •  times 메소드 이용 (정수는 기본적으로 times 메소드 지원)

      3.times do
          puts "hello"
      end
  •  조건문
    • if & unless
      if  true일 경우 내부 구문 실행, unless false일 경우 내부 구문 실행 

      if false
          puts 1
      elsif false
          puts 2
      elsif true
          puts 3
      else
          puts 4
      end
       
       
      ## OR
       
       
      unless not true
          puts 'false'
      end
        
      #조건문 간결화
      puts 'true' if true
      puts 'false' if false
    •  case
      break 필요 없음

      case OBJ
         when condition1 
            ....
         when condition2
            ....
         when condition3 
            ....
         else
            ....
      end
  •  Method
    • return을 이용하지 않은 경우에는 마지막 수행된 구문 반환

      def function_name 
         ...
      end
       
      ## or
       
      def function_name(arg1, arg2, ...)
         ...
         return ...
      end
  •  Proc (익명 함수)

    #Proc (Procedure) 익명 함수 생성 (do end 는 {} 로 변경 가능)
      
    callName = Proc.new do |name|
      puts 'Hello, #{name}'
    end
      
    callName.call("jess.lee")
      
    #js 혹은 함수형언어에서의 closure 와 같다. 
    #closure를 지원하는 언어의 관점에서 볼때, 위의 메소드 사용은 callName.call()("jess.lee") 과 같다
      
    #Kernel#proc 메서드를 통해 Proc.new 를 proc 으로 사용할 수 있다
    p = proc { puts 'Hello World!' }
    p.call()
      
    #lambda   (Proc 객체 생성하는 다른 방법)
    l = lambda { puts 'Hello World!' }
    l.class         #class 는 Proc
    l.call()
      
    #lambda 와 proc의 차이점은 매개변수의 갯수 검사
    def args(code)
      one, two = 1, 2
      code.call(one, two)
    end
    args(Proc.new{|a, b, c| puts "Give me a #{a} and a #{b} and a #{c.class}"})
    args(lambda{|a, b, c| puts "Give me a #{a} and a #{b} and a #{c.class}"})
      
    #lambda 에서는 에러 발생. proc에서는 nil 로 들어감
    #proc은 절차만 저장된 객체. lambda는 함수. 따라서 proc에서는 에러가 발생하지 않음. 
  •  Block
    do - end  사이의 코드를 의미함. ({} 동일)
    parameter 앞에 &를 붙이면 method block으로 인식하게 한다.


    Proc 은 사용하다보면 거의 일회성으로 사용. (일반적으로 익명함수에 대한 재사용성은 적다)
    Proc 키워드가 너무 자주 보인다. (.call() 호출 포함)
    Proc 에 대한 구분이 필요하다.
    Proc이 파라미터로 들어왔다고 가정하고 파라미터를 생략한다. (yield)

    #### Block 탄생 배경?
      
    #Proc을 사용하는 경우
    code = proc do |name|
      puts "hello, #{name}"
    end
    code.call("Avdi")
      
      
    #일회성이기 때문에 보통 변수할당을 하지 않음
    def open(filename, mode, block)
      # ...
    end
      
    open("myfile", "w", :while_open_do => proc do
      # ...
    end)
      
      
    #불필요한 Proc 키워드
    def open(filename, mode, &block)
      # ...
    end
    open "myfile", "w" do
      # ...
    end
      
    #Proc 파라미터를 선언하지 않아도 들어왔을 것이다..   (yield 키워드로 블록 선언을 했는데 사용할때 블록을 넣어주지 않는다면 Error)
    def open(filename, mode)
      puts "filename : #{filename}, mode : #{mode}"
      yield
      puts "end"
    end
      
    open "myfile", "w" do
      puts "in progress"
    end



  • Class
    class 키워드로 시작, end 로 끝
    initialize 메소드는 자바에서 생성자와 비슷

    class Song
        def initialize(name, artist, duration)
            @name = name
            @artist = artist
            @duration = duration
        end
    end

     

    • 객체 생성

      song = Song.new("I do", "Rain", 240)

      new 메소드는 객체를 메모리 공간에 할당하고, 매개변수를 이용해 객체의 initialize 메소드를 호출

    • 상속
      < 기호를 통해 상속을 표현 (extends 와 동일)

      class KaraokeSong < Song
          def initialize(name, artist, duration, lyrics)
              super(name, artist, duration)
              @lyrics = lyrics
          end
      end
    • 접근 제어
      private, protected, public
      기본은 public (예외 : initialize 는 항상 private) 
  • module
    클래스, 메소드, 상수를 묶은 기능 (class 와 비슷)
    모듈을 통해 객체 생성은 불가능.
    mixin을 통해 다중 상속이 가능 
    재사용성 가능한 요소를 묶는데 유용 (1. 재사용하는 코드인데, 클래스로 구분짓기가 싫을 때가 있다 : 클래스는 객체를 생성해서 메서드 호출하던지, static 메서드를 호출해야 하니까..    2. 다중 상속이 가능  ) 

    module Debug
      def whoAmI?
        "#{self.type.name} (\##{self.id}): #{self.to_s}"
      end
    end
    class Phonograph
      include Debug // module include
      # ...
    end
    class EightTrack
      include Debug // module include
      # ...
    end
    ph = Phonograph.new("West End Blues")
    et = EightTrack.new("Surrealistic Pillow")
      
    결과 : ph.whoAmI? »   "Phonograph (#537766170): West End Blues"
    결과 : et.whoAmI? »   "EightTrack (#537765860): Surrealistic Pillow"


    require 를 통해 모듈을 불러들어와 사용할 수 있다.
    include, extend를 통해 클래스, 객체 내에서 mixin 하여 사용하는 방법이 있다.

    *module을 사용하는 키워드 include, exclude 차이
    include : 슈퍼클래스의 메소드를, 인스턴스 메소드로 상속 받는다.
    extend : 슈퍼클래스의 메소드를, 클래스 메소드로 상속 받는다. (static)
    객체를 생성할때, include를 사용한 모듈에 대해서는 객체 생성 시점에 콜백으로 호출되는 self.included 메소드로 인하여  instance method로 사용할 수 있게 된다.



  •  예외처리
    begin - rescue (begin으로 시작하면 예외가 발생할때, rescue 코드쪽으로 넘어가게 된다)

    def first_line( filename )
      begin
        file = open("some_file")
        info = file.gets
        file.close
        info  # Last thing evaluated is the return value
      rescue
        nil   # Can't read the file? then don't return a string
      end
    end





참고했던 페이지들이 좀 있었는데... 써놓질 않아가지고.. 담에는 참고했던 페이지를 잘 정리해야겠다


'기타' 카테고리의 다른 글

Rails 기본  (0) 2017.09.12
Comments