为什么Ruby不支持i ++或i-(增加/减less运算符)?

前/后递增/递减运算符( ++-- )是非常标准的编程语言语法(至less对于过程和面向对象的语言)。

为什么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 

我知道Fixnum是不可变的,但是如果+=可以实例化一个新的Fixnum并设置它,为什么不对++做同样的操作呢?

包含=字符的赋值的一致性是唯一的原因,还是我错过了什么?

马茨(松本行弘)用一个古老的线索来解释这个问题:

 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. 

一个原因是,到现在为止,每个赋值操作符(即一个variablesvariables的操作符)都有一个。 如果你添加++-- ,那不再是这种情况了。

另一个原因是, ++的行为和--经常混淆人。 例子:在你的例子中, i++的返回值实际上是1,而不是2(然而i的新值是2)。

这在OO语言中不是常规的。 事实上,Smalltalk中没有++语言,这个语言创造了“面向对象编程”这个术语(以及Ruby最受其影响的语言)。 你的意思是用C语言和传统的语言来模仿C语言。Ruby的语法有点像C语言,但是坚持C语言的传统不是奴隶制。

至于为什么它不在Ruby中:Matz不想要它。 这真的是最终的原因。

Smalltalk中不存在这样的事情的原因是因为它是语言压倒一切的哲学的一部分,赋予一个variables从根本上说是一种不同于向对象发送消息的事物 – 它在不同的层次上。 这个想法可能影响了Matz在deviseRuby。

把它包含在Ruby中是不可能的 – 你可以很容易地编写一个预处理器,将所有的++转换成+=1 。 但显然Matz不喜欢做一个“隐藏的任务”的操作员的想法。 在内部有一个隐藏的整数操作数的操作符似乎有点奇怪。 语言中没有其他操作符以这种方式工作。

我认为还有另一个原因:Ruby中的++不会像C及其直接后继者那样远程有用。

原因是, for关键字:尽pipe在C中是必不可less的,但在Ruby中大部分是多余的。 Ruby中的大部分迭代都是通过Enumerable方法来完成的,比如遍历某些数据结构时的each方法和map ,以及需要循环确切次数的Fixnum#times方法。

实际上,就我所见,大多数时间+=1被刚刚从C风格语言迁移到Ruby的人使用。

总而言之,如果方法++--完全可以使用的话,这是非常有问题的。

我认为Matz不喜欢他们的理由是它实际上用新的替代了variables。

例如:

 a = SomeClass.new
 def a.go
   '你好'
结束
 #在这一点上,你可以调用a.go
 #但如果你做了一个++
 #这真的意味着a = a + 1
 #所以你不能再打电话给a.go
 #因为你已经失去了你的原创

现在如果有人能说服他,应该叫#succ! 或什么不是,那会更有意义,并避免这个问题。 你可以build议在ruby核心。

你可以定义一个.+自增运算符:

 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 

有关“类variables”的更多信息,请参见“ 类variables增加Fixnum对象 ”。

用大卫·布莱克(David Black)的着作“坚实的Rubyist”一书中的话来说:

Ruby中的一些对象作为立即值存储在variables中。 这些包括整数,符号(看起来像:this),以及特殊对象true,false和nil。 当您将这些值中的一个赋值给一个variables(x = 1)时,该variables保存该值本身,而不是对该variables的引用。 实际上,这并不重要(在本书的参考文献和相关主题的讨论中,它经常会被隐含,而不是被重复地指出)。 Ruby自动处理对象引用的解引用; 您不必做任何额外的工作就可以将消息发送到包含string引用的对象,而不是包含立即数整数值的对象。 但是直接值表示规则有一些有趣的分支,特别是当涉及到整数时。 一方面,表示为立即值的任何对象总是完全相同的对象,无论它分配了多less个variables。 只有一个对象100,只有一个对象为false,依此类推。 整数绑定variables的直接,唯一的本质是Ruby缺乏前后增量操作符 – 也就是说,你不能在Ruby中这样做:x = 1 x ++#没有这样的操作符原因是,到x的即时存在,x ++就像1 ++,这意味着你将把数字1改成数字2,这是没有意义的。

难道这不是通过在fixnum或Integer类中添加新方法来实现的吗?

 $ ruby -e 'numb=1;puts numb.next' 

返回2

“破坏性”方法似乎附加! 警告可能的用户,所以添加一个叫做next!的新方法next! 几乎可以做什么要求,即。

 $ ruby -e 'numb=1; numb.next!; puts numb' 

返回2(因为麻木已经增加)

当然, next! 方法将不得不检查对象是一个整数variables,而不是一个实数,但这应该是可用的。

从Ruby的irb中检查C系列中的这些运算符并自行testing:

 x = 2 # x is 2 x += 2 # x is 4 x++ # x is now 8 ++x # x reverse to 4