E041: Mixed Left And Right Associative Ops — 좌결합·우결합 연산자를 섞어 썼어요
E041: Mixed Left And Right Associative Ops — 좌결합·우결합 연산자를 섞어 썼어요
결합성(associativity) 이 서로 다르지만 우선순위(precedence) 가 같은 연산자들을 괄호 없이 한 표현식에 함께 사용했을 때 이 에러가 나와요.
본문
Scala에서 콜론(:)으로 끝나는 연산자는 우결합(right-associative) 이에요. 나머지 연산자는 모두 좌결합(left-associative) 이고요. 우선순위가 같은데 결합성이 다른 두 연산자를 함께 쓰면, 컴파일러가 평가 순서를 정할 수 없어요.
중위 연산자(infix operator)의 우선순위는 연산자의 첫 번째 문자로 결정돼요. 아래는 우선순위가 높아지는 순서로 문자를 나열한 거예요.
- (모든 문자)
|^&= !< >:+ -* / %- (그 외의 모든 특수 문자)
예제 (Example)
extension (x: Int)
def +: (y: Int): Int = x + y
def +* (y: Int): Int = x * y
def example = 1 +: 2 +* 3
+:는 우결합, +*는 좌결합이에요. 둘 다 첫 문자가 +라서 우선순위가 같은데, 결합성이 달라서 이들을 섞어 쓰면 애매해져요.
오류 메시지 (Error)
-- [E041] Syntax Error: example.scala:5:19 -------------------------------------
5 |def example = 1 +: 2 +* 3
| ^
|+: (which is right-associative) and +* (which is left-associative) have same precedence and may not be mixed
|-----------------------------------------------------------------------------
| Explanation (enabled by `-explain`)
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| The operators +: and +* are used as infix operators in the same expression,
| but they bind to different sides:
| +: is applied to the operand to its right
| +* is applied to the operand to its left
| As both have the same precedence the compiler can't decide which to apply first.
|
| You may use parenthesis to make the application order explicit,
| or use method application syntax operand1.+:(operand2).
|
| Operators ending in a colon : are right-associative. All other operators are left-associative.
|
| Infix operator precedence is determined by the operator's first character. Characters are listed
| below in increasing order of precedence, with characters on the same line having the same precedence.
| (all letters)
| |
| ^
| &
| = !
| < >
| :
| + -
| * / %
| (all other special characters)
| Operators starting with a letter have lowest precedence, followed by operators starting with `|`, etc.
-----------------------------------------------------------------------------
해결 방법 (Solution)
괄호로 적용 순서를 명확히 하거나, 메서드 호출 문법(operand1.+:(operand2))을 사용하면 돼요.
// Use parentheses to make the order explicit
extension (x: Int)
def +: (y: Int): Int = x + y
def +* (y: Int): Int = x * y
def example = (1 +: 2) +* 3
// Or use method call syntax
extension (x: Int)
def +: (y: Int): Int = x + y
def +* (y: Int): Int = x * y
def example = (1.+:(2)).+*(3)