Scala 中的增量 (++) 运算符

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3992399/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 02:31:26  来源:igfitidea点击:

Increment (++) operator in Scala

scalaincrement

提问by adelarsq

Is there any reason for Scala not support the ++ operator to increment primitive types by default? For example, you can not write:

Scala 是否有任何理由不支持 ++ 运算符默认增加原始类型?例如,你不能写:

var i=0
i++

Thanks

谢谢

采纳答案by pkaeding

My guess is this was omitted because it would only work for mutable variables, and it would not make sense for immutable values. Perhaps it was decided that the ++operator doesn't scream assignment, so including it may lead to mistakes with regard to whether or not you are mutating the variable.

我的猜测是这被省略了,因为它只适用于可变变量,而对不可变值没有意义。也许决定++运算符不会尖叫赋值,因此包含它可能会导致关于您是否正在改变变量的错误。

I feel that something like this is safe to do (on one line):

我觉得这样做是安全的(在一行上):

i++

but this would be a bad practice (in any language):

但这将是一个不好的做法(在任何语言中):

var x = i++

You don't want to mix assignment statements and side effects/mutation.

您不想混合赋值语句和副作用/变异。

回答by Daniel C. Sobral

I like Craig's answer, but I think the point has to be more strongly made.

我喜欢Craig回答,但我认为必须更加强调这一点。

  1. There are no "primitives" -- if Intcan do it, then so can a user-made Complex(for example).

  2. Basic usage of ++would be like this:

    var x = 1 // or Complex(1, 0)

    x++

  3. How do you implement ++in class Complex? Assuming that, like Int, the object is immutable, then the ++method needs to return a newobject, but that new object has to be assigned.

  1. 没有“原语”——如果Int可以做到,那么用户制作的Complex(例如)也可以。

  2. 的基本用法++如下:

    var x = 1 // or Complex(1, 0)

    x++

  3. 你是如何++在课堂上实施的Complex?假设Int对象是不可变的,那么该++方法需要返回一个对象,但必须为该新对象赋值

It would require a new language feature. For instance, let's say we create an assignkeyword. The type signature would need to be changed as well, to indicate that ++is not returninga Complex, but assigningit to whatever field is holding the present object. In Scala spirit of not intruding in the programmers namespace, let's say we do that by prefixing the type with @.

它需要一个新的语言功能。例如,假设我们创建了一个assign关键字。类型签名也需要更改,以指示++返回a Complex,而是分配给保存当前对象的任何字段。本着不侵入程序员命名空间的 Scala 精神,假设我们通过在类型前加上@.

Then it could be like this:

那么它可能是这样的:

case class Complex(real: Double = 0, imaginary: Double = 0) {
  def ++: @Complex = {
    assign copy(real = real + 1)
    // instead of return copy(real = real + 1)
}

The next problem is that postfix operators suck with Scala rules. For instance:

下一个问题是后缀运算符对 Scala 规则很不利。例如:

def inc(x: Int) = {
  x++
  x
}

Because of Scala rules, that is the same thing as:

由于 Scala 规则,这与以下内容相同:

def inc(x: Int) = { x ++ x }

Which wasn't the intent. Now, Scala privileges a flowing style: obj method param method param method param .... That mixes well C++/Java traditional syntax of object method parameterwith functional programming concept of pipelining an input through multiple functions to get the end result. This style has been recently called "fluent interfaces" as well.

这不是本意。现在,Scala 赋予了一种流畅的风格:obj method param method param method param .... 这很好地混合了 C++/Java 传统语法object method parameter和函数式编程概念,即通过多个函数管道输入以获得最终结果。这种风格最近也被称为“流畅的界面”。

The problem is that, by privileging that style, it cripples postfix operators (and prefix ones, but Scala barely has them anyway). So, in the end, Scala would have to make big changes, and it would be able to measure up to the elegance of C/Java's increment and decrement operators anyway -- unless it really departed from the kind of thing it doessupport.

问题是,通过赋予这种风格特权,它削弱了后缀运算符(和前缀运算符,但无论如何 Scala 几乎没有它们)。所以,最终,Scala 将不得不做出重大改变,无论如何它都能够达到 C/Java 递增和递减运算符的优雅——除非它真的偏离了它确实支持的那种东西。

回答by Craig P. Motlin

In Scala, ++ is a valid method, and no method implies assignment. Only =can do that.

在 Scala 中,++ 是一个有效的方法,没有任何方法意味着赋值。只能=这样做。

A longer answer is that languages like C++ and Java treat ++specially, and Scala treats =specially, and in an inconsistent way.

一个更长的答案是像 C++ 和 Java 这样的语言有++特殊对待,而 Scala 则有=特殊对待,并且以不一致的方式对待。

In Scala when you write i += 1the compiler first looks for a method called +=on the Int. It's not there so next it does it's magic on =and tries to compile the line as if it read i = i + 1. If you write i++then Scala will call the method ++on iand assign the result to... nothing. Because only =means assignment. You could write i ++= 1but that kind of defeats the purpose.

在 Scala 中,当您编写i += 1编译器时,首先会查找+=Int 上调用的方法。它不在那里,所以接下来它会变魔术=并尝试编译该行,就好像它读取i = i + 1. 如果你写i++那么斯卡拉将调用方法++i和结果分配给什么都没有。因为只=意味着赋值。你可以写,i ++= 1但那种违背了目的。

The fact that Scala supports method names like +=is already controversial and some people think it's operator overloading. They could have added special behavior for ++but then it would no longer be a valid method name (like =) and it would be one more thing to remember.

Scala 支持像这样的方法名称这一事实+=已经引起争议,有些人认为这是运算符重载。他们本可以为++它添加特殊行为,但它不再是有效的方法名称(如=),而且要记住另一件事。

回答by Rex Kerr

I think the reasoning in part is that +=1is only one more character, and ++is used pretty heavily in the collections code for concatenation. So it keeps the code cleaner.

我认为部分原因是这+=1只是一个字符,并且++在集合代码中大量使用以进行连接。所以它使代码更干净。

Also, Scala encourages immutable variables, and ++is intrinsically a mutating operation. If you require +=, at least you can force all your mutations to go through a common assignment procedure (e.g. def a_=).

此外,Scala 鼓励不可变变量,并且++本质上是一种可变操作。如果您需要+=,至少您可以强制您的所有突变通过一个共同的分配程序(例如def a_=)。

回答by Apocalisp

Of course you can have that in Scala, if you really want:

当然,如果你真的想要,你可以在 Scala 中使用它:

import scalaz._
import Scalaz._

case class IncLens[S,N](lens: Lens[S,N], num : Numeric[N]) { 
  def ++ = lens.mods(num.plus(_, num.one))
}

implicit def incLens[S,N:Numeric](lens: Lens[S,N]) =
  IncLens[S,N](lens, implicitly[Numeric[N]])

val i = Lens[Int,Int](identity, (x, y) => y)

val imperativeProgram = for {
  _ <- i := 0;
  _ <- i++;
  _ <- i++;
  x <- i++
} yield x

def runProgram = imperativeProgram ! 0

And here you go:

给你:

scala> runProgram
runProgram: Int = 3

回答by Rich Oliver

The primary reason is that there is not the need in Scala, as in C. In C you are constantly:

主要原因是在 Scala 中不需要,就像在 C 中一样。在 C 中,您不断:

for(i = 0, i < 10; i++)
{
  //Do stuff
}

C++ has added higher level methods for avoiding for explicit loops, but Scala has much gone further providing foreach, map, flatMap foldLeft etc. Even if you actually want to operate on a sequence of Integers rather than just cycling though a collection of non integer objects, you can use Scala range.

C++ 已经添加了更高级别的方法来避免显式循环,但 Scala 更进一步提供了 foreach、map、flatMap foldLeft 等。 即使你真的想对整数序列进行操作,而不是仅仅通过非整数对象的集合进行循环,您可以使用 Scala 范围。

(1 to 5) map (_ * 3) //Vector(3, 6, 9, 12, 15)
(1 to 10 by 3) map (_ + 5)//Vector(6, 9, 12, 15)

Because the ++ operator is used by the collection library, I feel its better to avoid its use in non collection classes. I used to use ++ as a value returning method in my Util package package object as so:

因为++运算符是集合库使用的,所以我觉得在非集合类中避免使用比较好。我曾经在我的 Util 包包对象中使用 ++ 作为值返回方法,如下所示:

implicit class RichInt2(n: Int)
{      
  def isOdd: Boolean = if (n % 2 == 1) true else false
  def isEven: Boolean = if (n % 2 == 0) true else false
  def ++ : Int = n + 1
  def -- : Int = n - 1     
}

But I removed it. Most of the times when I have used ++ or + 1 on an integer, I have later found a better way, which doesn't require it.

但我删除了它。大多数情况下,当我在整数上使用 ++ 或 + 1 时,我后来找到了一个更好的方法,它不需要它。

回答by Dev_anon101

It is possible if you define you own class which can simulate the desired output however it may be a pain if you want to use normal "Int" methods as well since you would have to always use *()

如果您定义自己的可以模拟所需输出的类是可能的,但是如果您也想使用普通的“Int”方法可能会很痛苦,因为您必须始终使用 *()

import scala.language.postfixOps //otherwise it will throw warning when trying to do num++

/*
 * my custom int class which can do ++ and --
 */
class int(value: Int) {

  var mValue = value

  //Post-increment
  def ++(): int = {

    val toReturn = new int(mValue)
    mValue += 1
    return toReturn 
  }

  //Post-decrement
  def --(): int = {

    val toReturn = new int(mValue)
    mValue -= 1
    return toReturn 
  }

  //a readable toString
  override def toString(): String = {
      return mValue.toString
  }
}

//Pre-increment
def ++(n: int): int = {
  n.mValue += 1
  return n;
}

//Pre-decrement
def --(n: int): int = {
  n.mValue -= 1
  return n;
}

//Something to get normal Int
def *(n: int): Int = {
  return n.mValue
}

Some possible test cases

一些可能的测试用例

scala>var num = new int(4)
num: int = 4

scala>num++
res0: int = 4

scala>num
res1: int = 5 // it works although scala always makes new resources

scala>++(num) //parentheses are required
res2: int = 6

scala>num
res3: int = 6

scala>++(num)++ //complex function
res4: int = 7

scala>num
res5: int = 8

scala>*(num) + *(num) //testing operator_*
res6: Int = 16

回答by idonnie

Lets define a var:

让我们定义一个 var:

var i = 0

++i is already short enough:

++i 已经够短了:

{i+=1;i}

Now i++ can look like this:

现在 i++ 看起来像这样:

i(i+=1)

To use above syntax, define somewhere inside a package object, and then import:

要使用上述语法,请在包对象内的某处定义,然后导入:

class IntPostOp(val i: Int) { def apply(op: Unit) = { op; i } } 
implicit def int2IntPostOp(i: Int): IntPostOp = new IntPostOp(i)

Operators chaining is also possible:

运算符链接也是可能的:

i(i+=1)(i%=array.size)(i&=3)

The above example is similar to this Java (C++?) code:

上面的例子类似于这个 Java (C++?) 代码:

i=(i=i++ %array.length)&3;

The style could depend, of course.

当然,风格可能取决于。

回答by soc

It isn't included because Scala developers thought it make the specification more complex while achieving only negligible benefits and because Scala doesn't have operators at all.

它没有被包括在内,因为 Scala 开发人员认为它使规范更加复杂,而只实现了微不足道的好处,并且因为 Scala 根本没有运算符。

You could write your own one like this:

你可以这样写自己的:

class PlusPlusInt(i: Int){
  def ++ = i+1
  }

implicit def int2PlusPlusInt(i: Int) = new PlusPlusInt(i)

val a = 5++
// a is 6

But I'm sure you will get into some trouble with precedence not working as you expect. Additionally if i++ would be added, people would ask for ++i too, which doesn't really fit into Scala's syntax.

但我相信你会遇到一些麻烦,因为优先级不能按预期工作。此外,如果要添加 i++,人们也会要求 ++i,这并不真正适合 Scala 的语法。