Scala의 증분 (++) 연산자
기본적으로 기본 유형을 증가시키기 위해 Scala가 ++ 연산자를 지원하지 않는 이유가 있습니까? 예를 들어 다음과 같이 쓸 수 없습니다.
var i=0
i++
감사
내 생각 엔 이것은 변경 가능한 변수에 대해서만 작동하고 변경 불가능한 값에는 의미가 없기 때문에 생략되었습니다. ++
운영자가 할당을 비명을 지르지 않기로 결정 했을 수 있으므로 변수를 변경하는지 여부와 관련하여 실수로 이어질 수 있습니다.
나는 이와 같은 일이 안전하다고 생각합니다 (한 줄로).
i++
그러나 이것은 (모든 언어에서) 나쁜 습관입니다.
var x = i++
할당 문과 부작용 / 돌연변이를 혼합하고 싶지 않습니다.
나는 Craig 의 대답을 좋아 하지만, 요점은 더 강하게 만들어야한다고 생각합니다.
"기본 요소"는 없습니다. 가능하다면
Int
사용자가 만든 것도 가능합니다Complex
(예를 들어).의 기본 사용법
++
은 다음과 같습니다.var x = 1 // or Complex(1, 0)
x++
++
수업에서 어떻게 구현Complex
합니까?Int
객체가 불변 이라고 가정하면++
메서드는 새 객체 를 반환해야 하지만 해당 새 객체를 할당해야 합니다.
새로운 언어 기능이 필요합니다. 예를 들어 assign
키워드를 생성한다고 가정 해 보겠습니다 . 유형 서명은 그 나타 내기 위해,뿐만 아니라 변경 될 필요가 ++
되지 않는 반환 을 Complex
하지만, 할당 본 개체를 들고 어떤 필드에. 프로그래머 네임 스페이스에 침입하지 않는다는 스칼라의 정신에서 타입 앞에 @
.
그러면 다음과 같을 수 있습니다.
case class Complex(real: Double = 0, imaginary: Double = 0) {
def ++: @Complex = {
assign copy(real = real + 1)
// instead of return copy(real = real + 1)
}
다음 문제는 접미사 연산자가 스칼라 규칙에 문제가 있다는 것입니다. 예를 들면 :
def inc(x: Int) = {
x++
x
}
Scala 규칙 때문에 다음과 같습니다.
def inc(x: Int) = { x ++ x }
의도가 아니 었습니다. 이제 Scala는 유동적 인 스타일 : obj method param method param method param ...
. 그것은 object method parameter
최종 결과를 얻기 위해 여러 함수를 통해 입력을 파이프 라이닝하는 함수 프로그래밍 개념과 C ++ / Java의 전통적인 구문을 잘 혼합합니다 . 이 스타일은 최근 "유창한 인터페이스"라고도 불립니다.
문제는 그 스타일을 특권으로 사용함으로써 접미사 연산자 (그리고 접두사 연산자도 불구가되지만 스칼라가 거의 가지고 있지 않다는 것입니다). 그래서, 결국, 스칼라는 큰 변화를 만들어야 할 것이고, 어쨌든 C / 자바의 증가 및 감소 연산자의 우아함까지 측정 할 수있을 것입니다 - 정말이 물건의 종류에서 출발하지 않는 한 수행 을 지원.
Scala에서 ++는 유효한 메서드이며 할당을 의미하는 메서드는 없습니다. 만 =
그렇게 할 수 있습니다.
더 긴 대답은 C ++ 및 Java와 같은 언어 ++
는 =
특별하게 취급하고 Scala는 특별하고 일관성없는 방식으로 취급 한다는 것입니다.
Scala i += 1
에서 컴파일러 를 작성할 때 먼저 +=
Int에서 호출 된 메서드를 찾습니다 . 그것은 거기에 없기 때문에 다음에 그것은 마술을 =
하고 마치 읽은 것처럼 라인을 컴파일하려고합니다 i = i + 1
. 작성 i++
하면 Scala는 메서드 ++
를 호출 i
하고 결과를 ... 아무것도 할당하지 않습니다. 단지 =
할당을 의미 하기 때문 입니다. 글을 쓸 수는 i ++= 1
있지만 그런 종류는 목적에 맞지 않습니다.
Scala가 같은 메서드 이름을 지원한다는 사실 +=
은 이미 논란의 여지가 있으며 일부 사람들은 그것이 연산자 오버로딩이라고 생각합니다. 에 대한 특별한 동작을 추가 할 수 ++
있었지만 더 이상 유효한 메서드 이름 (예 :)이 아니며 =
기억해야 할 한 가지가 더 있습니다.
부분적으로 추론은 +=1
하나 이상의 문자이며 ++
연결을 위해 컬렉션 코드에서 상당히 많이 사용 된다는 것 입니다 . 따라서 코드를 깔끔하게 유지합니다.
또한 Scala는 변경 불가능한 변수를 권장하며 ++
본질적으로 변경 작업입니다. 필요한 경우 +=
최소한 모든 돌연변이가 공통 할당 절차 (예 :)를 거치도록 강제 할 수 있습니다 def a_=
.
물론 원하는 경우 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
그리고 여기 있습니다.
scala> runProgram
runProgram: Int = 3
주된 이유는 C에서와 같이 Scala에는 필요가 없기 때문입니다. C에서는 지속적으로 다음을 수행합니다.
for(i = 0, i < 10; i++)
{
//Do stuff
}
C ++는 명시 적 루프를 피하기 위해 더 높은 수준의 메서드를 추가했지만 Scala는 foreach, map, flatMap foldLeft 등을 훨씬 더 많이 제공했습니다. 실제로 정수가 아닌 개체의 컬렉션을 순환하는 것보다 정수 시퀀스에서 작동하려는 경우에도 마찬가지입니다. , 스칼라 범위를 사용할 수 있습니다.
(1 to 5) map (_ * 3) //Vector(3, 6, 9, 12, 15)
(1 to 10 by 3) map (_ + 5)//Vector(6, 9, 12, 15)
++ 연산자는 컬렉션 라이브러리에서 사용되기 때문에 컬렉션이 아닌 클래스에서는 사용하지 않는 것이 좋습니다. 내 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"메서드를 사용하려는 경우 고통 스러울 수 있습니다.
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
var를 정의 할 수 있습니다.
var i = 0
++ i는 이미 충분히 짧습니다.
{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 ++?) 코드와 유사합니다.
i=(i=i++ %array.length)&3;
물론 스타일은 달라질 수 있습니다.
Scala 개발자는 무시할만한 이점 만 달성하면서 사양을 더 복잡하게 만들고 Scala에는 연산자가 전혀 없기 때문에 포함되지 않았습니다.
다음과 같이 직접 작성할 수 있습니다.
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.
ReferenceURL : https://stackoverflow.com/questions/3992399/increment-operator-in-scala
'program story' 카테고리의 다른 글
분기 삭제 (0) | 2021.01.07 |
---|---|
JCheckBox가 확인되었는지 확인하는 방법은 무엇입니까? (0) | 2021.01.07 |
System.Net.Mail을 사용하여 Gmail을 통해 이메일 보내기 (0) | 2021.01.07 |
딕셔너리 목록과의 딕셔너리 목록 (0) | 2021.01.07 |
bash : 백그라운드 함수 프로세스를 조용히 종료 (0) | 2021.01.07 |