초보자가주의해야 할 Ruby Gotchas는 무엇입니까? [닫은]


108

나는 최근에 Ruby 프로그래밍 언어를 배웠고 대체로 좋은 언어입니다. 하지만 제가 예상했던 것만 큼 간단하지 않다는 사실에 놀랐습니다. 더 정확하게는, "최소 놀라움의 법칙"은 나에게 그다지 존경스럽지 않은 것처럼 보였습니다 (물론 이것은 매우 주관적입니다). 예를 들면 :

x = true and false
puts x  # displays true!

그리고 유명한 :

puts "zero is true!" if 0  # zero is true!

Ruby 초보자에게 경고 할 다른 "Gotchas"는 무엇입니까?


@ phrases.insert (0, p) OK @ phrases.insert (p) 아무 일도 일어나지 않습니다 @phrases << p # OK
Anno2001

true and false진실을 반환합니까?
Jürgen Paul

3
"x = true 및 false"는 실제로 "(x = true) 및 false"로 해석되기 때문입니다. 연산자 우선 순위의 문제입니다. "and"는 "="보다 우선 순위가 낮습니다. 대부분의 다른 언어는 역 우선 순위를 가지고 있습니다. 왜 Rails에서이 순서를 선택했는지 모르겠습니다. 매우 혼란 스럽습니다. "정상"동작을 원하면 "x = (true 및 false)"를 입력하면 x가 false가됩니다.
MiniQuark 2013

4
또 다른 해결책은 "&&"및 "||"를 사용하는 것입니다. "and"및 "or"대신 : 예상대로 작동합니다. 예를 들어 : "x = true && false"는 x가 false가됩니다.
MiniQuark 2013

"적어도 깜짝 원칙은 최소한의 원칙을 의미합니다 나의 놀람." 에서 en.wikipedia.org/wiki/Ruby_(programming_language)#Philosophy 같은 파이썬 간다. 나는 파이썬의 창조자에 대해 비슷한 말을했지만 그것이 어디에 있었는지 잊어 버렸습니다.
Darek Nędza

답변:


59

Wikipedia 루비 문제

기사에서 :

  • 대문자로 시작하는 이름은 상수로 취급되므로 지역 변수는 소문자로 시작해야합니다.
  • $및 문자 @는 Perl에서와 같이 가변 데이터 유형을 나타내지 않고 범위 분석 연산자로 기능합니다.
  • 부동 소수점 숫자를 표시하려면 0 자리 숫자 ( 99.0) 또는 명시 적 변환 ( 99.to_f)을 따라야합니다 . 99.숫자는 메서드 구문에 영향을 받기 때문에 점 ( ) 을 추가하는 것만으로는 충분하지 않습니다 .
  • 비 부울 데이터의 부울 평가는 엄격 : 0, ""그리고 []모든 평가된다 true. C에서 표현식 0 ? 1 : 00(즉, false)로 평가됩니다 . 그러나 Ruby에서는 1모든 숫자 가 다음 과 같이 평가되므로 true. 만 nilfalse평가합니다 false. 이 규칙의 결과는 규칙에 따라 Ruby 메서드 (예 : 정규 표현식 검색)가 성공시 숫자, 문자열, 목록 또는 기타 거짓이 아닌 값을 반환하지만 nil실패시 (예 : 불일치) 반환한다는 것 입니다. 이 규칙은 단지 특수 목적 스몰 토크에서 사용 true하고는 false부울 표현식에 사용할 수 있습니다.
  • 1.9 이전 버전에는 문자 데이터 유형이 없습니다 (문자 유형을 제공하는 C와 비교 char). 이것은 문자열을 슬라이싱 할 때 놀라움을 유발할 수 있습니다. "abc"[0]yields 97( 문자열 의 첫 번째 문자의 ASCII 코드를 나타내는 정수); 수득 "a"사용 "abc"[0,1]하거나 (1 길이의 문자열을) "abc"[0].chr.
  • 표기법 statement until expression은 다른 언어의 동등한 명령문 (예 : do { statement } while (not(expression));C / C ++ / ...)과 달리 표현식이 이미이면 실제로 명령문을 실행하지 않습니다 true. 이것은 statement until expression실제로 구문 상 설탕 이기 때문 입니다.

    until expression
      statement
    end

    등가의 C에있는 / C ++이다 while (not(expression)) statement;처럼 statement if expression에 상당

    if expression
      statement
    end

    그러나 표기법

    begin
      statement
    end until expression

    루비에서는 표현식이 이미 참인 경우에도 실제로 한 번 문을 실행합니다.

  • 상수는 객체에 대한 참조이므로 상수가 참조하는 내용을 변경하면 경고가 생성되지만 객체 자체를 수정하면 그렇지 않습니다. 예를 들어 Greeting << " world!" if Greeting == "Hello"오류 또는 경고를 생성하지 않습니다. 이것은 finalJava의 변수 와 유사 하지만 Ruby에는 Java와 달리 객체를 "고정"하는 기능도 있습니다.

다른 언어와 현저하게 다른 일부 기능 :

  • 조건식 and및 의 일반적인 연산자 or는 일반적인 우선 순위 규칙을 따르지 and않습니다 or. 보다 엄격하게 바인딩하지 않습니다 . Ruby에는 표현식 연산자도 있습니다.||&&예상대로 작동합니다.

  • def 내부 def 는 파이썬 프로그래머가 기대하는 바를 수행하지 않습니다.

    def a_method
        x = 7
        def print_x; puts x end
        print_x
    end

    이것은 다음에 대한 오류를 제공합니다. x 정의되지 않은 것에 . 당신은을 사용해야합니다 Proc.

언어 기능

  • 메서드 인수 주위에 괄호를 생략하면 메서드가 여러 매개 변수를 사용하는 경우 예기치 않은 결과가 발생할 수 있습니다. Ruby 개발자는 향후 Ruby 버전에서 다중 매개 변수 메소드에서 괄호를 생략하는 것이 허용되지 않을 수 있다고 말했습니다. 현재 (2007 년 11 월) Ruby 인터프리터는 ()코드의 모호한 의미를 피하기 위해 작성자가를 생략하지 않도록 권장하는 경고를 표시 합니다. 사용하지 않는 ()것은 여전히 ​​일반적인 관행이며, 루비를라는 메소드와 함께 사람이 읽을 수있는 도메인 별 프로그래밍 언어 자체로 사용하는 것이 특히 좋습니다 method_missing().

1
Ruby 1.9에는 문자 데이터 유형도 없습니다. 1.8에서 인덱스 연산자는 Fixnum을 반환했습니다. 1.9에서는 한 문자 문자열을 자르는 것과 같습니다.
whitequark

38

초보자는 평등 방법에 문제가 있습니다 .

  • a == b : a와 b가 같은지 확인합니다. 이것이 가장 유용합니다.
  • a.eql? b : 또한 a와 b가 같은지 확인하지만 때로는 더 엄격합니다 (예를 들어 a와 b가 동일한 유형인지 확인할 수 있음). 주로 해시에서 사용됩니다.
  • a. 같습니까? b : a와 b가 동일한 객체인지 확인 (신원 확인)
  • a === b : case 문에 사용됩니다 ( " a matches b " 로 읽음 ).

이 예제는 처음 세 가지 방법을 명확히해야합니다.

a = b = "joe"

a==b       # true
a.eql? b   # true
a.equal? b # true (a.object_id == b.object_id)

a = "joe"
b = "joe"

a==b       # true
a.eql? b   # true
a.equal? b # false (a.object_id != b.object_id)

a = 1
b = 1.0

a==b       # true
a.eql? b   # false (a.class != b.class)
a.equal? b # false

참고 == , EQL? 그리고 동등합니까? 항상 대칭이어야합니다. a == b이면 b == a입니다.

또한 ==eql? 둘 다 동일한 별칭으로 Object 클래스에서 구현 됩니까? , 그래서 새 클래스를 만들고 ==eql을 원한다면 ? 평범한 정체성이 아닌 다른 것을 의미하려면 둘 다 재정의해야합니다. 예를 들면 :

class Person
    attr_reader name
    def == (rhs)
      rhs.name == self.name  # compare person by their name
    end
    def eql? (rhs)
      self == rhs
    end
    # never override the equal? method!
end

=== 다른 방법 동작합니다. 우선 그것은 대칭 적이 지 않습니다 (a === b는 b === a를 의미 하지 않습니다 ). 내가 말했듯이 a === b를 "a가 b와 일치"로 읽을 수 있습니다. 다음은 몇 가지 예입니다.

# === is usually simply an alias for ==
"joe" === "joe"  # true
"joe" === "bob"  # false

# but ranges match any value they include
(1..10) === 5        # true
(1..10) === 19       # false
(1..10) === (1..10)  # false (the range does not include itself)

# arrays just match equal arrays, but they do not match included values!
[1,2,3] === [1,2,3] # true
[1,2,3] === 2       # false

# classes match their instances and instances of derived classes
String === "joe"   # true
String === 1.5     # false (1.5 is not a String)
String === String  # false (the String class is not itself a String)

경우 문을 기반으로 ===의 방법 :

case a
  when "joe": puts "1"
  when 1.0  : puts "2"
  when (1..10), (15..20): puts "3"
  else puts "4"
end

다음과 같습니다.

if "joe" === a
  puts "1"
elsif 1.0 === a
  puts "2"
elsif (1..10) === a || (15..20) === a
  puts "3"
else
  puts "4"
end

인스턴스가 일종의 컨테이너 또는 범위를 나타내는 새 클래스를 정의하는 경우 ( include? 또는 match? 메서드 같은 것이있는 경우 ) 다음 과 같이 === 메서드 를 재정의하는 것이 유용 할 수 있습니다 .

class Subnet
  [...]
  def include? (ip_address_or_subnet)
    [...]
  end
  def === (rhs)
    self.include? rhs
  end
end

case destination_ip
  when white_listed_subnet: puts "the ip belongs to the white-listed subnet"
  when black_listed_subnet: puts "the ip belongs to the black-listed subnet"
  [...]
end

1
또한 : a = 'строка'; b = 'строка'; pa == b; a = a.force_encoding 'ASCII-8BIT'; b = b.force_encoding 'UTF-8'; pa == b; pa === b; p a.eql? 비; p a. 같습니까? b
Nakilon 2010-08-29


18

다음 코드는 저를 놀라게했습니다. 위험한 문제라고 생각합니다. 쉽게 실행할 수 있고 디버깅하기 어렵습니다.

(1..5).each do |number|
  comment = " is even" if number%2==0
  puts number.to_s + comment.to_s
end

이것은 다음을 인쇄합니다.

1
2 is even
3
4 is even
5

하지만 블록 앞에 comment =아무것도 추가 하면 ...

comment = nil
(1..5).each do |number|
  comment = " is even" if number%2==0
  puts number.to_s + comment.to_s
end

그런 다음 얻을 :

1
2 is even
3 is even
4 is even
5 is even

기본적으로 변수가 블록 내부에서만 정의되면 블록의 끝에서 소멸되고 nil매 반복마다 재설정됩니다 . 그것은 일반적으로 당신이 기대하는 것입니다. 그러나 변수 블록 이전에 정의 된 외부 변수가 블록 내부에서 사용되므로 그 값은 반복 사이에 지속됩니다.

한 가지 해결책은 다음과 같이 작성하는 것입니다.

comment = number%2==0 ? " is even" : nil

나는 (나를 포함하여) 많은 사람들이 " a = b if c"대신 " " 를 쓰는 경향이 있다고 생각합니다 a = (c ? b : nil). 왜냐하면 더 읽기 쉬우 기 때문입니다. 그러나 분명히 부작용이 있습니다.


4
(1..5) do | number; comment |에 의해 외부 범위 변수를 섀도 잉 할 수도 있습니다. ..... 여기 읽기 stackoverflow.com/questions/1654637/…
Özgür

6
이것은 나에게 논리적으로 보인다. 이 범위 지정은 다른 언어의 전형이며 구문이 다릅니다.
g.

그러나 a = (b if c)삼항없이 원하는 효과를 얻기 위해 쓸 수 있습니다 . 거짓 b if c이면 nil로 평가 되기 때문 c입니다.
Cameron Martin

16

super인수없이 호출 할 때 재정의 된 메서드는 실제로 재정의 메서드와 동일한 인수를 사용하여 호출됩니다.

class A
  def hello(name="Dan")
    puts "hello #{name}"
  end
end

class B < A
  def hello(name)
    super
  end
end

B.new.hello("Bob") #=> "hello Bob"

실제로 super인수없이 호출하려면 라고 말해야 super()합니다.


3
경우 B#helloname = 42전과 super, 그것은 "42 안녕하세요"말했다.
Andrew Grimm

14

블록과 메서드는 기본적으로 마지막 줄의 값을 반환합니다. puts디버깅 목적으로 끝에 문을 추가 하면 불쾌한 부작용이 발생할 수 있습니다.



11

클래스 변수, 클래스 속성 및 클래스 메서드를 이해하는 데 많은 어려움이있었습니다. 이 코드는 초보자에게 도움이 될 수 있습니다.

class A
  @@classvar = "A1"
  @classattr = "A2"
  def self.showvars
    puts "@@classvar => "+@@classvar
    puts "@classattr => "+@classattr
  end
end

A.showvars
  # displays:
  # @@classvar => A1
  # @classattr => A2

class B < A
  @@classvar = "B1"
  @classattr = "B2"
end

B.showvars
  # displays:
  # @@classvar => B1
  # @classattr => B2

A.showvars
  # displays:
  # @@classvar => B1   #Class variables are shared in a class hierarchy!
  # @classattr => A2   #Class attributes are not

1
예, 클래스 변수는 까다로울 수 있습니다. 대부분의 경험이 풍부한 루비 스트들은 그것들 없이는 문제를 해결하는 다른 방법들이 있기 때문에 그것들을 피하는 것이 현명하다고 말할 것이라고 생각합니다. 일부 언어 애호가들은 Ruby의 클래스 변수가 언어 수준에서 잘못 설계되었다고 말할 수도 있습니다.
David J.

8

내가 배운 한 가지는 연산자 || =를 조심스럽게 사용하는 것이었다. 부울을 다루는 경우 특별히주의하십시오. 다른 모든 것이 실패하고 'a'가 nil 인 경우 'a'에 기본값을 제공하기 위해 일반적으로 a || = b를 catch all로 사용했습니다. 그러나 a가 거짓이고 b가 참이면 a가 참으로 할당됩니다.


당신은 사용할 수 있습니다 a = b if a.nil?또는 @a = b unless defined?(@a).
Andrew Grimm

8
  • 블록은 이해하는 데 정말 중요하며 모든 곳에서 사용됩니다.

  • 메서드 매개 변수를 괄호로 묶지 않아도됩니다. 사용 여부는 귀하에게 달려 있습니다. 어떤 사람들은 항상 그것을 사용해야한다고 말합니다 .

  • 예외 처리를 위해 throw 및 catch가 아닌 raise 및 rescue를 사용하십시오.

  • 사용할 수 ;있지만 한 줄에 여러 항목을 넣고 싶지 않으면 사용할 필요가 없습니다.


Ruby 1.8.6 이상으로 넘어갈 계획이 없다면 원하는만큼 괄호를 무시하십시오. 그렇지 않으면 아마 사용하는 것이 좋습니다.
Mike Woodhouse

7

인스턴스 메서드 클래스 메서드 를 포함하는 믹스 인에 문제가있었습니다 . 이 코드는 초보자에게 도움이 될 수 있습니다.

module Displayable
  # instance methods here
  def display
    puts name
    self.class.increment_displays
  end
  def self.included(base)
    # This module method will be called automatically
    # after this module is included in a class.
    # We want to add the class methods to the class.
    base.extend Displayable::ClassMethods
  end
  module ClassMethods
    # class methods here
    def number_of_displays
      @number_of_displays # this is a class attribute
    end
    def increment_displays
      @number_of_displays += 1
    end
    def init_displays
      @number_of_displays = 0
    end
    # this module method will be called automatically
    # after this module is extended by a class.
    # We want to perform some initialization on a
    # class attribute.
    def self.extended(base)
      base.init_displays
    end
  end
end

class Person
  include Displayable
  def name; @name; end
  def initialize(name); @name=name; end
end

puts Person.number_of_displays # => 0
john = Person.new "John"
john.display # => John
puts Person.number_of_displays # => 1
jack = Person.new "Jack"
jack.display # => Jack
puts Person.number_of_displays # => 2

처음에는 다음 과 같이 간단하게 인스턴스 메서드 클래스 메서드 를 모두 포함하는 모듈을 가질 수 있다고 생각 했습니다.

module Displayable
  def display
    puts name
    self.class.increment_displays
  end
  def self.number_of_displays  # WRONG!
    @number_of_displays
  end
  [...]
end

불행히도 number_of_displays 메소드 는 "모듈 클래스 메소드"이기 때문에 절대 포함되거나 확장되지 않습니다. "모듈 인스턴스 메서드"만 클래스에 포함되거나 (인스턴스 메서드로) 클래스로 확장 될 수 있습니다 (클래스 메서드로). 이것이 믹스 인의 인스턴스 메서드를 모듈에 넣고 믹스 인의 클래스 메서드를 다른 모듈에 넣어야하는 이유입니다 (일반적으로 클래스 메서드를 "ClassMethods"하위 모듈에 넣습니다). 포함 된 매직 메서드 덕분 에 단 하나의 간단한 "include Displayable"호출에 인스턴스 메서드와 클래스 메서드를 모두 쉽게 포함 할 수 있습니다 (위 예제 참조).

이 믹스 인은 각 디스플레이를 클래스 별로 계산합니다. 카운터는 클래스 속성이므로 각 클래스는 고유 한 속성을 갖습니다 (파생 클래스의 @number_of_displays 카운터가 초기화되지 않으므로 Person 클래스에서 새 클래스를 파생하면 프로그램이 실패 할 수 있음). @number_of_displays@@ number_of_displays 로 대체 하여 글로벌 카운터로 만들 수 있습니다. 이 경우 각 클래스 계층에는 자체 카운터가 있습니다. 전역적이고 고유 한 카운터를 원한다면 모듈 속성으로 만들어야합니다.

루비로 시작했을 때이 모든 것이 제게 직관적이지 않았습니다.

나는 여전히 이러한 mixin 메소드 중 일부를 비공개 또는 보호로 만드는 방법을 알 수 없습니다 ( displaynumber_of_displays 메소드 만 공개 메소드로 포함되어야 함).


7

범위 표기법에주의하십시오.

(적어도 보다 더 집중 해 처음에 한을!)

0..10 (2 개의 점)과 0...10(3 개의 점) 사이에 차이가 있습니다 .

저는 Ruby를 아주 좋아합니다. 그러나이 점-점 대 점-점-점은 나를 괴롭힌다. 다음과 같은 미묘한 이중 구문 "기능"이 있다고 생각합니다.

  • 오타하기 쉽고
  • 코드를 훑어 보면서 눈으로 쉽게 놓칠 수 있습니다.

내 프로그램에서 치명적인 버그를 일으킬 수 없어야합니다.


1
for (i=0; i<max; i++)for (i=0; i<=max; i++)
g

0..10과 0 ... 10의 차이점이 무엇인지 알아 내려고 노력했습니다.
Luis D Urraca 2012

6

나는 " and"와 " or"는 루비의 더 명백한 "부모"(가장 두드러진 다른 것은 스몰 토크) 중 하나 인 Perl에게 고개를 끄덕 이라고 생각한다 . 그들은 모두 (지적 행동의 출처 인 사실, 할당보다) 훨씬 낮은 우선 순위가 이상 &&하고|| 있는 사용되어야하는 사업자이다.

알아 두어야 할 다른 사항은 즉시 명확하지 않습니다.

그렇게 보이지만 실제로 메서드 / 함수를 호출하는 것은 아닙니다. 대신 스몰 토크 에서처럼 객체에 메시지를 보냅니다. 그래서 method_missing정말 더 비슷 message_not_understood합니다.

some_object.do_something(args)

다음과 같다

some_object.send(:do_something, args) # note the :

기호는 매우 널리 사용됩니다. 그것이 바로 시작되는 것들 :이고 그들은 즉시 명백하지는 않지만 (글쎄요, 저에게는 그렇지 않았습니다), 당신이 그것들을 더 빨리 이해하게 될수록 좋습니다.

Ruby는 "오리처럼 걷고 오리처럼 꽥꽥 거리는 경우 ..."라는 원칙을 따르며, 명시적인 상속이나 혼합 관계없이 메서드의 공통 하위 집합으로 객체를 비공식적으로 대체 할 수 있다는 원칙을 따릅니다.


감사. send 메서드 에 대해 제가 싫어하는 한 가지가 있습니다 . 클래스 외부에서도 private 메서드를 호출 할 수 있다는 것입니다! 아야.
MiniQuark

1
@MiniQuark : 그것이 내가 send 메소드에 대해 좋아하는 것입니다!
Andrew Grimm

6

attr_writer또는 attr_accessor(또는 def foo=)를 사용하여 setter (일명 mutator)를 선언하는 경우 클래스 내부에서 호출하지 않도록주의하세요. 변수가 암시 적으로 선언되기 때문에 인터프리터는 항상 foo = bar메서드를 호출하는 대신 foo라는 새 변수를 선언하는 것으로 확인해야합니다 self.foo=(bar).

class Thing
  attr_accessor :foo
  def initialize
    @foo = 1      # this sets @foo to 1
    self.foo = 2  # this sets @foo to 2
    foo = 3       # this does *not* set @foo
  end
end

puts Thing.new.foo #=> 2

이는 데이터베이스의 필드를 기반으로 정의 된 접근자를 가져 오는 Rails ActiveRecord 객체에도 적용됩니다. 그들은 심지어 스타일의 인스턴스 변수 @ 아니에요 때문에, 개별적으로 그 값을 설정하는 적절한 방법은 함께 self.value = 123또는 self['value'] = 123.


5

시간과 날짜 클래스의 차이점 이해. 둘 다 다르며 레일에서 사용하는 동안 문제가 발생했습니다. Time 클래스는 때때로 표준 ruby ​​/ rails 라이브러리에있는 다른 Time 클래스 라이브러리와 충돌합니다. 레일스 앱에서 정확히 무슨 일이 일어나고 있는지 이해하는 데 개인적으로 많은 시간이 걸렸습니다. 나중에 내가 언제 그랬는지

Time.new

내가 알지도 못하는 위치에있는 도서관을 언급하고 있었다.

내가하고 싶은 말이 명확하지 않다면 죄송합니다. 다른 사람들이 비슷한 문제에 직면했다면 다시 설명하십시오.


4

과거에 저를 붙잡은 것은 줄 바꿈 문자 ( \n) 이스케이프 시퀀스 ( 다른 것들 중에서도)가 작은 따옴표 안의 문자열에서 지원되지 않는다는 것 입니다. 백 슬래시 자체가 이스케이프됩니다. 이스케이프가 예상대로 작동하려면 큰 따옴표를 사용해야합니다.


1
그리고 그것은 다른 언어와 다른가요?
Robert Gamble

자바, 하나. Java의 작은 따옴표는 문자열이 아닌 단일 문자를 묶는 데만 사용할 수 있습니다.
John Topley

1
이것은 문자열에 작은 따옴표를 사용할 수있는 모든 언어와 일치하며 그 이유입니다.
singpolyma

@John : 사실이지만 Java에서 '\ n'은 여전히 ​​개행 문자입니다.
Jorn

1
그러나 Java에서 작은 따옴표는 char 유형의 값만 만듭니다. 문자열이 아닙니다. 그 차이입니다.
jmucchiello

4
x = (true and false) # x is false

지적했듯이 0과 ''는 사실입니다.

같은 이름으로 메서드와 모듈 / 클래스를 가질 수 있습니다 (메서드가 실제로 Object에 추가되어 자체 네임 스페이스를 갖기 때문에 의미가 있습니다).

다중 상속은 없지만 여러 클래스에 공통 메소드를 추가하기 위해 자주 "믹신 모듈"이 사용됩니다.


0 == true // argh 내 두뇌의 C 컴파일러가 폭발하고 있습니다 !!
kenny

1
0 == true는 Ruby에서 거짓을 제공합니다. 0이 참인 이유는 참이 루비의 객체이기 때문입니다. C 0에서는 거짓과 같은 표현을합니다.
Jules

Ruby의 조건에서 만 falsenil거짓입니다. 다른 모든 것은 진정한 가치입니다.
rubyprince

4

방법은 재정의 할 수 있으며 원인을 찾을 때까지 마음을 긁는 사람이 될 수 있습니다. ( 물론,이 오류는 Ruby on Rails 컨트롤러의 동작이 실수로 재정의 될 때 감지하기가 약간 "더 어렵습니다"! )

#demo.rb
class Demo

  def hello1
    p "Hello from first definition"
  end

  # ...lots of code here...
  # and you forget that you have already defined hello1

  def hello1
    p "Hello from second definition"
  end

end
Demo.new.hello1

운영:

$ ruby demo.rb
=> "Hello from second definition"

그러나 경고를 활성화하여 호출하면 이유를 볼 수 있습니다.

$ ruby -w demo.rb
demo.rb:10: warning: method redefined; discarding old hello1
=> "Hello from second definition"

가능하면 경고 사용을 +100으로 할 것입니다.
Andrew Grimm 2011

3

나는 항상 .length를 사용하는 것이 좋다고 생각합니다 ... 크기는 거의 모든 것에 의해 지원되고 Ruby는 동적 유형을 가지고 있기 때문에 잘못된 유형이있을 때 .size를 호출하는 정말 이상한 결과를 얻을 수 있습니다 ... NoMethodError : undefined method`length ', 그래서 저는 일반적으로 Ruby에서 객체의 size를 호출하지 않습니다.

나를 두 번 이상 물었다.

또한 객체에는 ID가 있으므로 혼란을 피하기 위해 변수 호출 id 또는 object_id를 사용하지 않으려 고합니다. 사용자 개체에 대한 ID가 필요한 경우 user_id와 같은 이름으로 호출하는 것이 가장 좋습니다.

내 2 센트


2

나는 루비를 처음 접했고 첫 번째 라운드에서 수레 / 문자열을 정수로 변경하는 것과 관련된 문제가 발생했습니다. 나는 수레로 시작하여 모든 것을 f.to_int 로 코딩 했습니다 . 그러나 계속해서 문자열에 동일한 방법을 사용했을 때 프로그램을 실행할 때 곡선이 생겼습니다.

분명히 문자열에는 to_int 메서드가 없지만 float와 int에는 있습니다.

irb(main):003:0* str_val = '5.0'
=> "5.0"
irb(main):006:0> str_val.to_int
NoMethodError: undefined method `to_int' for "5.0":String
        from (irb):6
irb(main):005:0* str_val.to_i
=> 5


irb(main):007:0> float_val = 5.0
=> 5.0
irb(main):008:0> float_val.to_int
=> 5
irb(main):009:0> float_val.to_i
=> 5
irb(main):010:0>

처음에는 임의의 괄호가 나를 던졌습니다. 나는 일부 코드를 보았습니다. 두 가지 스타일이 모두 허용된다는 사실을 깨닫는 데는 시간이 걸렸습니다.


2

monkut의 응답과 관련하여 Ruby의 to_foo방법은 변환이 얼마나 엄격한지를 암시합니다.

과 같은 짧은 것 to_i, to_s게으르다 고 말하고 해당 형식으로 정확하게 표현할 수 없더라도 대상 유형으로 변환하십시오. 예를 들면 :

"10".to_i == 10
:foo.to_s == "foo"

더 이상 명시 적 기능이 좋아 to_int, to_s개체가 기본적으로 데이터의 형식으로 표현 될 수 있다는 것을 의미한다. 예를 들어, Rational클래스는 모든 유리수를 나타내므로를 호출하여 Fixnum (또는 Bignum) 정수로 직접 나타낼 수 있습니다 to_int.

Rational(20,4).to_int == 5

더 긴 메서드를 호출 할 수 없다면 객체가 해당 유형으로 기본적으로 표현 될 수 없음을 의미합니다.

따라서 기본적으로 변환 할 때 메서드 이름에 게으 르면 Ruby는 변환에 게으 릅니다.


1
여기에서 "게으른"단어가 올바른가요?
Andrew Grimm


1

루비 해시에 대한 반복은 특정 순서로 발생하는 것이 보장되지 않습니다. (버그가 아니라 기능)

Hash#sort 특정 주문이 필요한 경우 유용합니다.

관련 질문 : Ruby의 1000 개 해시의 키와 값 쌍이 항상 특정 순서로 배열되어있는 이유는 무엇입니까?


4
이것은 1.9에서 유효하지 않습니다. Ruby 프로그래밍 언어의 "Ruby 1.9에서는 해시 요소가 삽입 순서에서 반복됩니다."
Özgür

0

이것은 나를 한 번 화나게 만들었습니다.

1/2 == 0.5 #=> false
1/2 == 0   #=> true

저는 이것이 Java, C 및 C ++에서 정확히 동일한 방식으로 작동 할 것이라고 믿습니다.
Larry

재밌 네요. 생각도 안했지만 irb를 열어서 시도해 보면 말이됩니다. 그래서 (1/2)는 Fixnum이고 (0.5)는 Float입니다. 그리고 우리는 Fixnim! = Float를 알고 있습니다.
DemitryT

2
@DemitryT 더 간단한 이유는 유형에 관계없이 같지 않은으로 1/2평가 된다는 것 입니다. 그러나, 및 . 00.5Rational(1, 2) == 0.51.0 == 1
Max Nanasy 2012 년

여기에 보편적 언어 딸꾹질이 있습니다. 이것은 루비와 프로그래밍을 처음 접하는 누군가가 알아야 할 것입니다.
dtc

0
1..5.each {|x| puts x}

작동하지 않습니다. 범위를 괄호 안에 넣어야합니다.

(1..5).each {|x| puts x}

그래서 그것은 당신이 전화하고 있다고 생각하지 않습니다 5.each. 나는 이것이 x = true and falsegotcha 와 마찬가지로 우선 순위 문제라고 생각합니다 .


대신 괄호라고 부릅니다. 둘째, 반환 값 / 우선 순위 문제가있는 것처럼 보이는 코드가 있으면 어쨌든 괄호로 묶어야합니다. 그래서 나에게는이 "gotcha"에 특별한 것이 없습니다. 그래도 시간 낭비가 될 모든 조합 "gotchas"를 계속 쓸 수 있습니다. 솔직히 짝을 지으십시오. 예상 한 결과가 있더라도 괄호로 묶는 것이 좋습니다.
Özgür
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.