Почему Ruby не поддерживает I++ или I- (операторы инкремента/декремента)?
оператор pre/post increment/decrement (++
и --
) - довольно стандартный синтаксис языка программирования (по крайней мере, для процедурных и объектно-ориентированных языков).
почему Ruby не поддерживает их? Я понимаю, что вы могли бы сделать то же самое с +=
и -=
, но это просто кажется странно произвольным, чтобы исключить что-то подобное, тем более, что это так лаконично и традиционно.
пример:
i = 0 #=> 0
i += 1 #=> 1
i #=> 1
i++ #=> expect 2, but as far as I can tell,
#=> irb ignores the second + and waits for a second number to add to i
I пойми!--5-- > является неизменным, но если +=
может просто instanciate новый Fixnum
и установить его, почему бы не сделать то же самое для ++
?
согласованность в назначениях, содержащих =
характер единственная причина этого, или я что-то упускаю?
9 ответов
вот как МАЦ(Юкихиро Мацумото) объясняет это в старом нить:
Hi,
In message "[ruby-talk:02706] X++?"
on 00/05/10, Aleksi Niemelä <aleksi.niemela@cinnober.com> writes:
|I got an idea from http://www.pragprog.com:8080/rubyfaq/rubyfaq-5.html#ss5.3
|and thought to try. I didn't manage to make "auto(in|de)crement" working so
|could somebody help here? Does this contain some errors or is the idea
|wrong?
(1) ++ and -- are NOT reserved operator in Ruby.
(2) C's increment/decrement operators are in fact hidden assignment.
They affect variables, not objects. You cannot accomplish
assignment via method. Ruby uses +=/-= operator instead.
(3) self cannot be a target of assignment. In addition, altering
the value of integer 1 might cause severe confusion throughout
the program.
matz.
одна из причин заключается в том, что до сих пор каждый оператор присваивания (т. е. оператор, который изменяет переменную) имеет =
в нем. Если добавить ++
и --
, это не так.
другая причина заключается в том, что поведение ++
и --
часто путают люди. Case in point: возвращаемое значение i++
в вашем примере будет 1, а не 2 (новое значение i
было бы 2, однако).
это не принято в языках OO. На самом деле, нет ++
в Smalltalk, язык, который придумал термин "объектно-ориентированное программирование" (и язык Ruby наиболее сильно влияют). Вы имеете в виду, что это обычное в C и языки, близко имитирующие C. Ruby, имеют несколько C-подобный синтаксис,но он не рабски придерживается традиций C.
что касается того, почему это не в Ruby: Matz не хотел этого. Это действительно окончательное причина.
причина, по которой такая вещь не существует в Smalltalk, заключается в том, что это часть переопределяющей философии языка, что назначение переменной принципиально отличается вид вещь, чем отправка сообщения объекту - это на другом уровне. Это мышление, вероятно, повлияло на Matz в разработке Ruby.
было бы возможно включить его в Ruby - вы могли бы легко написать препроцессор, который преобразует все ++
на +=1
. но очевидно, мацу не нравилась идея оператора, выполняющего "скрытое задание"."Также кажется немного странным иметь оператор со скрытым целочисленным операндом внутри него. Ни один другой оператор в языке не работает таким образом.
Я думаю, есть еще одна причина:++
в Ruby не было бы удаленно полезно, как в C и его прямых преемниках.
причина в том, что for
ключевое слово: хотя это важно в C, это в основном лишнее в Ruby. Большая часть итерации в Ruby выполняется с помощью перечисляемых методов, таких как each
и map
при итерации через некоторую структуру данных и Fixnum#times
метод, когда вам нужно зациклить точное количество раз.
на самом деле, насколько я видел, большую часть времени +=1
используется людьми, недавно перенесенными в Ruby из языков C-style.
короче говоря, это действительно сомнительно, если методы ++
и --
будет использоваться вообще.
Я думаю, что рассуждение Matz о том, что они им не нравятся, заключается в том, что он фактически заменяет переменную новой.
ex:
a = SomeClass.new def a.go 'hello' end # at this point, you can call a.go # but if you did an a++ # that really means a = a + 1 # so you can no longer call a.go # as you have lost your original
теперь, если кто-то может убедить его, что он должен просто позвонить #succ! или нет, это имело бы больше смысла, и избежать проблемы. Вы можете предложить его на ruby core.
Вы можете определить .+
Авто-инкремент оператор:
class Variable
def initialize value = nil
@value = value
end
attr_accessor :value
def method_missing *args, &blk
@value.send(*args, &blk)
end
def to_s
@value.to_s
end
# pre-increment ".+" when x not present
def +(x = nil)
x ? @value + x : @value += 1
end
def -(x = nil)
x ? @value - x : @value -= 1
end
end
i = Variable.new 5
puts i #=> 5
# normal use of +
puts i + 4 #=> 9
puts i #=> 5
# incrementing
puts i.+ #=> 6
puts i #=> 6
дополнительная информация о " переменной класса "доступна в"переменная класса для увеличения объектов Fixnum".
и, по словам Дэвида Блэка из его книги "обоснованный Рубиист":
некоторые объекты в Ruby хранятся в переменных, как непосредственные значения. Они включают целые числа, символы (которые выглядят так: this) и специальные объекты true, false и нуль. Когда вы присваиваете одно из этих значений переменной (x = 1), переменная имеет значение ценность сама по себе, а не Ссылка на нее. С практической точки зрения это не имеет значения (и это часто будет оставлено как подразумевается, а не изложено неоднократно, при обсуждении ссылок и смежных тем в этой книге). Ruby обрабатывает разыменование ссылок на объекты автоматически; вам не нужно выполните дополнительную работу для отправки сообщения объекту, содержащему, скажем, ссылку на строка, в отличие от объекта, который содержит немедленное целое значение. Но правило представления непосредственного значения имеет несколько интересных последствий, особенно когда дело доходит до чисел. Во-первых, любой объект, который представлен поскольку немедленное значение всегда точно такой же объект, независимо от того, сколько переменные, которым он назначен. Есть только один объект 100, только один объект false, и так далее. Непосредственная, уникальная природа переменных с целочисленной привязкой стоит за отсутствием Ruby операторы pre - и post-increment-то есть, вы не можете сделать это в Ruby: x = 1 х++ # нет такого оператора Причина в том, что в непосредственном присутствии 1 в Х, Х++ будет как 1++, это означает, что вы измените число 1 на число 2-и это делает никакого смысла.
не может ли это быть достигнуто путем добавления нового метода в класс fixnum или Integer?
$ ruby -e 'numb=1;puts numb.next'
возвращает 2
"разрушительные" методы, похоже, добавляются с !
чтобы предупредить возможных пользователей, поэтому добавление нового метода под названием next!
будет в значительной степени делать то, что было запрошено ie.
$ ruby -e 'numb=1; numb.next!; puts numb'
возвращает 2 (так как numb был увеличен)
конечно,next!
метод должен был бы проверить, что объект был целочисленной переменной, а не реальное число, но это должны быть доступен.
проверьте эти операторы из семейства C в irb Ruby и проверьте их для себя:
x = 2 # x is 2
x += 2 # x is 4
x++ # x is now 8
++x # x reverse to 4