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