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

Scala中的增量(+;+;)运算符,scala,increment,Scala,Increment,Scala是否有任何理由不支持++操作符在默认情况下递增基元类型? 例如,您不能写入: var i=0 i++ 谢谢我猜这被省略了,因为它只对可变变量有效,而对不可变值没有意义。可能是因为决定了++操作符不会尖叫赋值,所以包含它可能会导致关于是否要变异变量的错误 我觉得这样做是安全的(一句话): 但这将是一种糟糕的做法(在任何语言中): 你不想把赋值语句和副作用/变异混为一谈。我认为部分原因是+=1只是多了一个字符,而++在用于串联的代码集合中使用得相当多。因此,它使代码更干净 此外,Scal

Scala是否有任何理由不支持++操作符在默认情况下递增基元类型? 例如,您不能写入:

var i=0
i++

谢谢

我猜这被省略了,因为它只对可变变量有效,而对不可变值没有意义。可能是因为决定了
++
操作符不会尖叫赋值,所以包含它可能会导致关于是否要变异变量的错误

我觉得这样做是安全的(一句话):

但这将是一种糟糕的做法(在任何语言中):


你不想把赋值语句和副作用/变异混为一谈。

我认为部分原因是
+=1
只是多了一个字符,而
++
在用于串联的代码集合中使用得相当多。因此,它使代码更干净


此外,Scala鼓励使用不可变变量,
++
本质上是一种变异操作。如果您需要
+=
,至少您可以强制所有的突变都通过一个通用的赋值过程(例如
def a_=
)。

不包括它,因为Scala开发人员认为它使规范更复杂,但只获得微不足道的好处,而且Scala根本没有运算符

你可以这样写你自己的:

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

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

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

但我相信你会遇到一些麻烦,因为你不能像你期望的那样工作。此外,如果要添加i++,人们也会要求使用++i,这并不符合Scala的语法。

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

P> >一个较长的答案是,如C++和java语言特别处理<代码> ++>代码>,Scala特别处理“<代码> = /代码>,并且以不一致的方式处理。

在Scala中,当您编写
i+=1
时,编译器首先在Int上查找名为
+=
的方法。它不在那里,所以接下来它在
=
上执行它的神奇操作,并尝试编译该行,就像它读取
i=i+1
一样。如果您编写
i++
,Scala将调用
i
上的方法
++
,并将结果分配给。。。没有什么。因为只有
=
意味着分配。您可以编写
i++=1
,但这种方法无法达到目的

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

我喜欢的是,但我想这一点必须更加明确

  • 没有“原语”——如果
    Int
    可以做到这一点,那么用户制作的
    Complex
    也可以做到这一点(例如)

  • ++
    的基本用法如下:

    class PlusPlusInt(i: Int){
      def ++ = i+1
      }
    
    implicit def int2PlusPlusInt(i: Int) = new PlusPlusInt(i)
    
    val a = 5++
    // a is 6
    
    case class Complex(real: Double = 0, imaginary: Double = 0) {
      def ++: @Complex = {
        assign copy(real = real + 1)
        // instead of return copy(real = real + 1)
    }
    
    var x=1//或复数(1,0)

    x++

  • 如何在类
    Complex
    中实现
    ++
    ?假设像
    Int
    一样,对象是不可变的,那么
    ++
    方法需要返回一个新对象,但必须指定该新对象

  • 这将需要一个新的语言功能。例如,假设我们创建一个
    assign
    关键字。类型签名也需要更改,以指示
    ++
    没有返回
    复合体
    ,而是将其分配给保存当前对象的任何字段。本着不侵入程序员名称空间的Scala精神,假设我们在类型前面加上
    @

    那么它可能是这样的:

    class PlusPlusInt(i: Int){
      def ++ = i+1
      }
    
    implicit def int2PlusPlusInt(i: Int) = new PlusPlusInt(i)
    
    val a = 5++
    // a is 6
    
    case class Complex(real: Double = 0, imaginary: Double = 0) {
      def ++: @Complex = {
        assign copy(real = real + 1)
        // instead of return copy(real = real + 1)
    }
    
    下一个问题是后缀运算符与Scala规则不符。例如:

    def inc(x: Int) = {
      x++
      x
    }
    
    由于Scala规则,这与:

    def inc(x: Int) = { x ++ x }
    
    这不是我的目的。现在,Scala有一种流动的风格:
    obj method param method param method param…
    。它将
    对象方法参数
    的C++/Java传统语法与函数编程概念很好地结合在一起,即通过多个函数流水线输入以获得最终结果。这种风格最近也被称为“流畅的界面”


    问题是,通过对这种样式进行特权,它削弱了后缀操作符(和前缀操作符,但Scala几乎没有)。因此,最终,Scala将不得不进行重大更改,并且它将能够达到C/Java的增量和减量运算符的优雅程度——除非它确实偏离了它所支持的类型。

    当然,如果您真的想要:

    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
    
    让我们定义一个变量:

    var i = 0
    
    ++我已经够矮了:

    {i+=1;i}
    
    现在i++可以如下所示:

    i(i+=1)
    
    要使用上述语法,请在包对象内的某个位置定义,然后导入:

    class IntPostOp(val i: Int) { def apply(op: Unit) = { op; i } } 
    implicit def int2IntPostOp(i: Int): IntPostOp = new IntPostOp(i)
    
    操作员链接也可以:

    i(i+=1)(i%=array.size)(i&=3)
    
    上述示例类似于此Java(C++?)代码:


    当然,风格可能会有所不同。

    主要原因是Scala没有必要像C一样使用它。在C中,您经常:

    for(i = 0, i < 10; i++)
    {
      //Do stuff
    }
    
    因为集合库使用了++操作符,所以我觉得最好避免在非集合类中使用它。我曾经在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     
    }
    

    但是我把它拿走了。大多数时候,当我在整数上使用++或+1时,我后来发现了一种更好的方法,而这并不需要它

    如果您定义自己的类来模拟所需的输出,那么这是可能的,但是如果您还想使用普通的“Int”方法,那么可能会很麻烦,因为您必须始终使用*()

    一些可能的测试用例

    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
    

    好奇的是,你能在Scala中发布i+=1吗?是的,你能,但前提是它是
    var
    而不是
    val
    。当Scala编译器在变量上找到一个以=结尾的方法,而该类没有该方法时
    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
    }
    
    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