ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Programming Ruby (14) 표현식 - 1
    Ruby 2016. 10. 31. 23:37
    [출처] Programming Ruby 

    (본 게시물은 저작권의 문제 발생시 출판사의 요청에 의해 삭제될 수 있습니다.)





    표현식


    루비가 다른 언어들과 다른 특징 중 하나는 값을 반환할 수 있어 보이는 모든 곳에서 값을 반환한다는 것이다. 따라서 거의 모든 것이 표현식이 된다. 이것이 실제로 의미하는 바는 무엇일까?


    이러한 특징을 통해 구문을 연속해서 쓸 수 있다는(chain statements) 점은 쉽게 유추할 수 있다.


    a = b = c = 0                    # => 0

    [3, 1, 7, 0].sort.revers      # => [7, 3, 1, 0] 



    C나 자바에서의 일반적인 구문이 루비에서는 표현식이다. 예를들어 if 와 case 구문ㅇ느 둘 다 마지막에 평가된 표현식의 값을 반환한다. 





    연산자 표현식 


    루비는 기본적인 연산자(+, -, *, / 등)와 함께 몇 가지 놀랄 만한 기능을 제공한다. 루비의 많은 연산자는 실제로 메서드 호출로 구현되어 있다. a*b+c라고 입력하면 실제로는 a가 참조하는 객체에게 b를 매개 변수로하여, '*' 메서드를 실행하라고 요청하는 것이다. 그리고 그 계산 결과로 반환된 개게에게 c를 매개 변수로 하여 '+' 메서드를 실행하라고 요청한다. 


    a, b, c = 1, 2, 3 

    a * b + c      # => 5

    (a . *(b)) . +(c) #= > 5


    루비에서 모든 것은 객체이고 인스턴스 메서드를 재정의하는 것도 가능하기 때문에 기본적으로 정의된 연산 결과가 마음에 들지 않는다면 기본 연산을 재정의 할 수도 있다. 


    class Fixnum

         alias old_plus +          # 기존의 '+' 연산자에 'old_plus'라는 별칭을 붙여준다.


         def + (other)               # Fixnum 클래스의 + 연산자를 재정의한다. 별로 좋은 생각은 아니다!

              old_plus(other).succ

         end

    end


    1 + 2  #=> 4

    a = 3

    a += 4 #=> 8

    a + a + a #= 26 



    우리가 작성한 클래스를 마치 내장 객체인 것처럼 연산자 포현식의 일부로 쓸 수 있다는 것이다. 왼쪽 시프트 연산자인 <<는 수신자 끝에 요소를 더한다는 의미로 많이 사용된다. 


    a = [ 1, 2, 3 ]

    a << 4                # => [1, 2, 3, 4]


    이 연산자를 자신의 정의한 클래서에서 사용할 수 있다.


    class ScoreKeeper

         def initialize

              @total_score = @count = 0

         end

         

         def <<(score)

              @total_score += score

              @count += 1

              self

         end

         

         def average

              fail "No score" if @count?zero?

              Float(@total_score) / @count

         end

    end


    score = ScoreKeeper.new

    scores << 10 << 20 << 40

    puts "Average = #{scores.average}"



    Average = 23.33333333333333333332 


    << 메서드가 명시적으로 self를 반환하는 이유는 연쇄적으로(<< 10 << 20 << 30) 메서드를 사용하기 위해서이다. +, *, << 와 같이 용도가 명확한 연산자뿐 아니라 대괄호를 사용한 인덱스 구현도 메서드 호출을 통해 구현되어 있다. some_obj[1,2,3]


    some_obj 객체에 [ ]이름을 가진 메서드를 호출하면서 세 개의 변수를 넘기는 것과 같다.


    class SomeCalss

         def [ ](p1, p2, p3)

              # ...

         end

    end     



    요소 대입은 [ ]= 메서드를 통해 정의된다. 인덱스로 넘겨진 맨 마지막 매개변수를 값으로 하고 나머지 매개 변수들을 인덱스로 사용한다.


    class SomeClass

         def [ ]= (*params)

              value = params.pop

              puts "Indexed with #{params.join(', ')}"

              puts "value = #{value.inspect}"

         end

    end



    s = SomeClass.new

    s[1] = 2

    s['cat', 'dog'] = 'enemies'


    실행결과

    Indexed with 1

    value = 2

    Indexed with cat, dog

    value = "enemies"



    기타 표현식 



    명령어 확장

    문자열을 역따옴표로 둘러싸거나 %x{...} 같은 구분자 형식을 사용하면, 기본적으로 사용중인 운영 체제에 의해 커맨드로 실행된다. 결괏값은 해당하는 명령어의 표준 출력이다. 줄바꿈이 잘리지 않고 남아 있어 문자열 값 끝에 리턴이나 줄바꿈이 포함되어 잇을 수 있다.


    `date`                # => "Tus Nov 14 16:31:02 CST 2013\n"

    `ls`.split[34]       # => "metaprogramming.pml"

    %x{echo "hello there"}     # => "hello there\n"




    역따옴표 재정의하기

    명령어 출력 표현식을 설명할때 역따옴표로 문자열을 둘러싸면 이 문자열이 갖는 의미는 '기본적으로 운영 체제에서 명령어를 실행하라는 의미'라고 설명했다 . 실재로는 문자열을 Object&`(역따옴표) 메서드에 매개 변수로 넘기는 것이다. 원한다면 이를 재정의 할 수 있다.


    alis old_backquote `

    def ` (cmd)

         result = old_backquote(cmd)

         if $? != 0

              puts "*** Command #{cmd} failed: status = #{$?.exitstatus}"

         end

         result

    end


    print `ls -l /etc/passwd`

    print `ls -l /etc/wibble`


    실행결과

    -rw-r--r-- 1 root wheel 5253 Oct 31 09:09 /etc/passwd

    ls: /etc/wibble: No such file or directory

    *** Command ls -l /etc/wibble failed: status = 1



    끄읕.




    'Ruby ' 카테고리의 다른 글

    Programming Ruby (16) 표현식 - 3  (0) 2016.11.02
    Programming Ruby (15) 표현식 - 2  (0) 2016.10.31
    What is Ruby Proc??  (0) 2016.10.29
    Programming Ruby (13) 메서드 파헤치기  (0) 2016.10.28
    Programming Ruby (11) 숫자  (0) 2016.10.27
Designed by Tistory.