Операторы увеличения / уменьшения до / после операции ( ++
и --
) представляют собой довольно стандартный синтаксис языка программирования (по крайней мере, для процедурных и объектно-ориентированных языков).
Почему Руби их не поддерживает? Я понимаю, что вы могли бы сделать то же самое с помощью +=
и -=
, но кажется странным произвольным исключать что-то подобное, тем более что это настолько кратко и условно.
Пример:
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
Я понимаю, что Fixnum
это неизменяемое, но если +=
можно просто создать новый экземпляр Fixnum
и установить его, почему бы не сделать то же самое для ++
?
=
Единственная причина этого - последовательность в назначениях, содержащих персонажа, или я что-то упускаю?
ruby
operators
language-design
Andy_Vulhop
источник
источник
+=
оператора. В C я стараюсь использовать++
/--
только внутри условных выражений , предпочитая более буквальное+=
/-=
в базовом выражении. Вероятно, потому что я выучил Python (задолго до C, хотя ...)Ответы:
Вот как Мац (Юкихиро Мацумото) объясняет это в старой беседе :
источник
+=
/-=
нормально? И не было1+=1
бы так плохо? (Он терпит неудачу в IRB сsyntax error, unexpected ASSIGNMENT
)+=
заменяет объект, на который ссылается переменная, на совершенно новый объект. Вы можете проверить это, позвонивi.object_id
до и послеi+=1
. Почему это было технически сложнее++
?++
метод).Одна из причин заключается в том, что до сих пор каждый оператор присваивания (т.е. оператор, изменяющий переменную) имел
=
в себе. Если вы добавите++
и--
, это уже не так.Другая причина в том, что поведение
++
и--
часто сбивает с толку людей. Показательный пример: возвращаемое значениеi++
в вашем примере на самом деле будет 1, а не 2 (i
однако новое значение будет 2).источник
=
кажется, имеет смысл рассуждение о том, что «все задания содержат в себе». Я могу относиться к этому с уважением как к неистовой приверженности последовательности.a.capitalize!
не переназначаетa
, он изменяет строку, на которуюa
указывает. Другие ссылки на ту же строку будут затронуты, и если вы сделаете этоa.object_id
до и после вызоваcapitalize
, вы получите тот же результат (ни один из которых не был бы верным, если бы вы это сделалиa = a.capitalize
).a.capitalize!
повлияет на другие ссылки на ту же строку. Это очень практическая разница. Например, если у вас есть,def yell_at(name) name.capitalize!; puts "HEY, #{name}!" end
а затем вы назовете его так:,my_name = "luis"; yell_at(my_name)
значениеmy_name
будет теперь равным"LUIS"
, тогда как оно не изменилось бы, если бы вы использовалиcapitalize
и присвоение.Это необычно для объектно-ориентированных языков. Фактически, нет
++
в Smalltalk, языке, который ввел термин «объектно-ориентированное программирование» (а язык Ruby находится под сильным влиянием). Вы имеете в виду, что это обычное явление для C и языков, сильно имитирующих C. Ruby действительно имеет синтаксис, отчасти похожий на C, но он не рабски придерживается традиций C.Что касается того, почему этого нет в Ruby: Мац этого не хотел. Это действительно главная причина.
Причина, по которой в Smalltalk такой вещи не существует, заключается в том, что это часть основной философии языка, согласно которой присвоение переменной - это принципиально другой вид вещей, чем отправка сообщения объекту - это другой уровень. Это мышление, вероятно, повлияло на Матца при разработке Ruby.
Было бы невозможно включить его в Ruby - вы могли бы легко написать препроцессор, который все преобразует
++
в+=1
. но, очевидно, Матцу не понравилась идея оператора, выполняющего «скрытое назначение». Также кажется немного странным наличие оператора со скрытым целым операндом внутри него. Ни один другой оператор в языке не работает таким образом.источник
Я думаю, есть еще одна причина:
++
в Ruby не будет удаленной пользы, как в C и его прямых преемниках.Причина в том, что
for
ключевое слово: хотя это важно в C, в Ruby оно по большей части излишне. Большая часть итераций в Ruby выполняется с помощью методов Enumerable, таких какeach
иmap
при итерации по некоторой структуре данных, иFixnum#times
метода, когда вам нужно выполнить цикл определенное количество раз.На самом деле, насколько я видел, большую часть времени
+=1
используют люди, только что перешедшие на Ruby с языков C-стиля.Короче говоря, действительно сомнительно, будут ли методы
++
и--
вообще использоваться.источник
Я думаю, что Матц не любит их потому, что фактически заменяет переменную на новую.
например:
Теперь, если бы кто-нибудь мог убедить его, что он должен просто позвонить #succ! или что нет, это имело бы больший смысл и позволило бы избежать проблемы. Можете предложить на рубиновом ядре.
источник
Вы можете определить
.+
оператор самоприращения:Дополнительная информация о «переменной класса» доступна в разделе « Переменная класса для увеличения объектов Fixnum ».
источник
Как сказал Дэвид Блэк из своей книги «Основанный на рубине»:
источник
Нельзя ли этого добиться, добавив новый метод в класс fixnum или Integer?
возвращает 2
Кажется, что "деструктивные" методы добавляются
!
для предупреждения возможных пользователей, поэтому добавление нового вызываемого метода вnext!
значительной степени сделает то, что было запрошено, т.е.возвращает 2 (поскольку число numb было увеличено)
Конечно,
next!
метод должен будет проверить, является ли объект целочисленной переменной, а не действительным числом, но это должно быть доступно.источник
Integer#next
уже существует (более или менее), за исключением того, что он называетсяInteger#succ
вместо этого (для «преемника»). НоInteger#next!
(илиInteger#succ!
) было бы чепухой: помните, что методы работают с объектами , а не с переменными , поэтомуnumb.next!
были бы точно равны1.next!
, то есть изменили бы 1 на 2 .++
было бы немного лучше, поскольку это может быть синтаксический сахар для присваивания, но лично я предпочитаю текущий синтаксис, в котором все присваивания выполняются с=
.Integer#pred
получить предшественника.Проверьте эти операторы из семейства C в irb Ruby и проверьте их сами:
источник
(x++)
недопустимый оператор в Ruby.