为什么 Ruby 不支持 i++或者我——​ (递增/递减运算符)?

发布于 2024-09-18 06:24:00 字数 616 浏览 5 评论 0原文

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

为什么 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 并设置它,为什么不对 += 执行相同的操作代码>++?

包含 = 字符的赋值的一致性是造成这种情况的唯一原因,还是我遗漏了什么?

The pre/post increment/decrement operator (++ and --) are pretty standard programing language syntax (for procedural and object-oriented languages, at least).

Why doesn't Ruby support them? I understand you could accomplish the same thing with += and -=, but it just seems oddly arbitrary to exclude something like that, especially since it's so concise and conventional.

Example:

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 understand Fixnum is immutable, but if += can just instanciate a new Fixnum and set it, why not do the same for ++?

Is consistency in assignments containing the = character the only reason for this, or am I missing something?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

仅冇旳回忆 2024-09-25 06:24:00

以下是 Matz(Yukihiro Matsumoto)在旧线程中的解释:

Hi,

In message "[ruby-talk:02706] X++?"
    on 00/05/10, Aleksi Niemelä <[email protected]> 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.

Here is how Matz(Yukihiro Matsumoto) explains it in an old thread:

Hi,

In message "[ruby-talk:02706] X++?"
    on 00/05/10, Aleksi Niemelä <[email protected]> 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.
脸赞 2024-09-25 06:24:00

原因之一是到目前为止,每个赋值运算符(即更改变量的运算符)中都有一个=。如果添加 ++--,情况就不再是这样了。

另一个原因是++--的行为经常让人感到困惑。举个例子:在您的示例中,i++ 的返回值实际上是 1,而不是 2(但是,i 的新值将是 2)。

One reason is that up to now every assignment operator (i.e. an operator which changes a variable) has a = in it. If you add ++ and --, that's no longer the case.

Another reason is that the behavior of ++ and -- often confuse people. Case in point: The return value of i++ in your example would actually be 1, not 2 (the new value of i would be 2, however).

℉絮湮 2024-09-25 06:24:00

这在 OO 语言中并不常见。事实上,Smalltalk 中没有 ++,Smalltalk 是创造“面向对象编程”一词的语言(也是受 Ruby 影响最强烈的语言)。您的意思是,它在 C 和密切模仿 C 的语言中是约定俗成的。Ruby 确实有一些类似 C 的语法,但它并不盲目地遵守 C 传统。

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

Smalltalk 中不存在这样的事情的原因是,它是该语言最重要哲学的一部分,即分配变量与向对象发送消息本质上是不同的事情 - 它处于不同的级别。这种想法可能影响了 Matz 设计 Ruby。

将它包含在 Ruby 中并非不可能 - 您可以轻松编写一个预处理器,将所有 ++ 转换为 +=1。但显然马茨不喜欢操作员执行“隐藏任务”的想法。拥有一个内部隐藏整数操作数的运算符似乎也有点奇怪。该语言中没有其他运算符以这种方式工作。

It's not conventional in OO languages. In fact, there is no ++ in Smalltalk, the language that coined the term "object-oriented programming" (and the language Ruby is most strongly influenced by). What you mean is that it's conventional in C and languages closely imitating C. Ruby does have a somewhat C-like syntax, but it isn't slavish in adhering to C traditions.

As for why it isn't in Ruby: Matz didn't want it. That's really the ultimate reason.

The reason no such thing exists in Smalltalk is because it's part of the language's overriding philosophy that assigning a variable is fundamentally a different kind of thing than sending a message to an object — it's on a different level. This thinking probably influenced Matz in designing Ruby.

It wouldn't be impossible to include it in Ruby — you could easily write a preprocessor that transforms all ++ into +=1. but evidently Matz didn't like the idea of an operator that did a "hidden assignment." It also seems a little strange to have an operator with a hidden integer operand inside of it. No other operator in the language works that way.

舞袖。长 2024-09-25 06:24:00

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

原因是 for 关键字:虽然它在 C 中很重要,但在 Ruby 中却是多余的。 Ruby 中的大部分迭代都是通过 Enumerable 方法完成的,例如迭代某些数据结构时的 eachmap 以及 Fixnum#times 方法,当您需要循环精确的次数时。

实际上,据我所知,大多数时候 +=1 是由刚从 C 风格语言迁移到 Ruby 的人使用的。

简而言之,是否会使用 ++-- 方法确实值得怀疑。

I think there's another reason: ++ in Ruby wouldn't be remotely useful as in C and its direct successors.

The reason being, the for keyword: while it's essential in C, it's mostly superfluous in Ruby. Most of the iteration in Ruby is done through Enumerable methods, such as each and map when iterating through some data structure, and Fixnum#times method, when you need to loop an exact number of times.

Actually, as far as I have seen, most of the time +=1 is used by people freshly migrated to Ruby from C-style languages.

In short, it's really questionable if methods ++ and -- would be used at all.

甜中书 2024-09-25 06:24:00

您可以定义 .+ 自增运算符:

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 对象的类变量"。

You can define a .+ self-increment operator:

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

More information on "class Variable" is available in "Class Variable to increment Fixnum objects".

飘然心甜 2024-09-25 06:24:00

我认为 Matz 不喜欢它们的原因是它实际上用一个新变量替换了变量。

例如:

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 上推荐它。

I think Matz' reasoning for not liking them is that it actually replaces the variable with a new one.

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

Now if somebody could convince him that it should just call #succ! or what not, that would make more sense, and avoid the problem. You can suggest it on ruby core.

一个人的旅程 2024-09-25 06:24:00

用 David Black 在他的书《The Well-Grounded Rubyist》中的话来说:

Ruby 中的某些对象作为立即值存储在变量中。这些包括
整数、符号(看起来像 :this)以及特殊对象 true、false 和
零。当您将这些值之一分配给变量 (x = 1) 时,该变量保存
值本身,而不是对其的引用。
实际上,这并不重要(并且通常会被隐含地保留,而不是
在本书的参考文献和相关主题的讨论中反复阐明)。
Ruby 自动处理对象引用的取消引用;你不必
做任何额外的工作来将消息发送到包含对的引用的对象
字符串,而不是包含立即整数值的对象。
但是立即值表示规则有一些有趣的后果,
尤其是当涉及到整数时。一方面,任何表示的对象
因为立即值总是完全相同的对象,无论有多少个
它分配给的变量。只有一个对象 100,只有一个对象 false,并且
很快。
整数绑定变量的直接、独特性质是 Ruby 缺乏
前置和后置自增运算符——也就是说,你不能在 Ruby 中执行此操作:
x = 1
x++ # 没有这样的运算符
原因是由于 x 中直接存在 1,x++ 将类似于 1++,
这意味着您要将数字 1 更改为数字 2,这使得
没有意义。

And in the words of David Black from his book "The Well-Grounded Rubyist":

Some objects in Ruby are stored in variables as immediate values. These include
integers, symbols (which look like :this), and the special objects true, false, and
nil. When you assign one of these values to a variable (x = 1), the variable holds
the value itself, rather than a reference to it.
In practical terms, this doesn’t matter (and it will often be left as implied, rather than
spelled out repeatedly, in discussions of references and related topics in this book).
Ruby handles the dereferencing of object references automatically; you don’t have to
do any extra work to send a message to an object that contains, say, a reference to
a string, as opposed to an object that contains an immediate integer value.
But the immediate-value representation rule has a couple of interesting ramifications,
especially when it comes to integers. For one thing, any object that’s represented
as an immediate value is always exactly the same object, no matter how many
variables it’s assigned to. There’s only one object 100, only one object false, and
so on.
The immediate, unique nature of integer-bound variables is behind Ruby’s lack of
pre- and post-increment operators—which is to say, you can’t do this in Ruby:
x = 1
x++ # No such operator
The reason is that due to the immediate presence of 1 in x, x++ would be like 1++,
which means you’d be changing the number 1 to the number 2—and that makes
no sense.

甲如呢乙后呢 2024-09-25 06:24:00

Ruby 中的某些对象作为立即值存储在变量中。其中包括整数、符号(看起来像 :this)以及特殊对象 true、false 和 nil。当您将这些值之一分配给变量 (x = 1) 时,该变量保存该值本身,而不是对其的引用。

任何表示为立即值的对象始终是完全相同的对象,无论分配给多少个变量。只有一个对象 100,只有一个对象为 false,依此类推。

整数绑定变量的直接、唯一性质是 Ruby 缺乏前置和后置增量运算符的原因 - 也就是说,您无法在 Ruby 中执行此操作:

x=1

x++ # 没有这样的运算符

原因是,由于 x 中直接存在 1,x++ 将类似于 1++,这意味着您将把数字 1 更改为数字 2,并且没有任何意义。

Some objects in Ruby are stored in variables as immediate values. These include integers, symbols (which look like :this), and the special objects true, false, and nil. When you assign one of these values to a variable (x = 1), the variable holds the value itself, rather than a reference to it.

Any object that’s represented as an immediate value is always exactly the same object, no matter how many variables it’s assigned to. There’s only one object 100, only one object false, and so on.

The immediate, unique nature of integer-bound variables is behind Ruby’s lack of pre-and post-increment operators—which is to say, you can’t do this in Ruby:

x=1

x++ # No such operator

The reason is that due to the immediate presence of 1 in x, x++ would be like 1++, which means you’d be changing the number 1 to the number 2—and that makes no sense.

烟酉 2024-09-25 06:24:00

难道不能通过向 fixnum 或 Integer 类添加新方法来实现吗?

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

返回 2 个

“破坏性”方法似乎附加了 ! 来警告可能的用户,因此添加一个名为 next! 的新方法几乎可以完成所请求的操作,即。

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

返回 2(因为 numb 已递增)

当然,next! 方法必须检查该对象是否是整型变量而不是实数,但这应该可用。

Couldn't this be achieved by adding a new method to the fixnum or Integer class?

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

returns 2

"Destructive" methods seem to be appended with ! to warn possible users, so adding a new method called next! would pretty much do what was requested ie.

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

returns 2 (since numb has been incremented)

Of course, the next! method would have to check that the object was an integer variable and not a real number, but this should be available.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文