Почему добавление string + fixnum вызывает ошибку приведения? - PullRequest
3 голосов
/ 12 октября 2009

Почему добавление ruby ​​не может привести данную строку к fixnum и наоборот?

irb>fixnum = 1
=> 1
irb> fixnum.class
=> Fixnum
irb> string = "3"
=> "3"
irb> string.class
=> String
irb> string.to_i
=> 3
irb> fixnum + string
TypeError: String can't be coerced into Fixnum
    from (irb):96:in `+'
    from (irb):96
    from :0
irb(main):097:0> 

Ответы [ 4 ]

10 голосов
/ 12 октября 2009

Потому что ruby ​​не знает, хотите ли вы преобразовать строку в int или int в строку. Например, 1 + "3" - это "13". Ruby предпочитает выдавать ошибку, чтобы пользователь мог решить, следует ли to_s один операнд или to_i другой, а не делать неправильные действия автоматически.

5 голосов
/ 12 октября 2009

Выдает ошибку, потому что ruby ​​не знает, что вы хотите. String + fixnum - неоднозначное утверждение. Это может означать, что вы хотите добавить значение int строки и числа или строковое значение int и строки. Например:

str = "5"
num =  3

puts str.to_i + num
=> 8

puts str + num.to_s
=> 53

Вместо того, чтобы угадывать, какой из них вы хотите, ruby ​​просто выбрасывает исключение.

1 голос
/ 12 октября 2009

Fixnum#+ это просто метод. Упрощенно это работает так:

class Fixnum
  def +(other)
    if Fixnum === other
      # normal operation
    else
      n1, n2= other.coerce(self)
      return n1+n2
    end
  end
end

coerce используется для автоматического преобразования числовых типов. Это используется, например, если вы делаете 42 + 3.141. Строка в ruby ​​не может быть автоматически преобразована в числовые значения. Вы можете улучшить класс String, чтобы сделать это. Вам просто нужно сделать

class String
  def coerce(other)
    coerced= case other
    when Integer
      self.to_i
    when
      self.to_f
    end
    return coerced, other
  end
end

Теперь вы можете сделать

23 + "42" # => 65
0.859 - "4" # => 3.141

Это не работает наоборот. coerce только для числовых значений "23" + 42 не будет работать. String#+ не будет использовать принуждение.

Упрощенный + делается в Fixnum, а не в Integer специально. Fixnum и Bignum имеют свои отдельные методы, потому что они работают по-разному.

1 голос
/ 12 октября 2009

Вам необходимо установить переменную обратно на себя, так как выполнение .to_i возвращает целочисленное значение, но не изменяет исходный объект.

>> string = "3"
=> "3"
>> string.class
=> String
>> string.to_i
=> 3
>> string
=> "3"
>> string.class
=> String
>> string = string.to_i
=> 3
>> string.class
=> Fixnum
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...