Skip to content

Compound Assignment Operators Guide

This guide covers compound assignment operators in Harneet, which provide a concise way to perform operations and assign the result back to a variable in a single statement.

Overview

Compound assignment operators combine a binary operation with assignment, making code more concise and often more efficient. Instead of writing variable = variable + value, you can write variable += value.

Arithmetic Compound Assignment Operators

Addition Assignment (+=)

Adds the right operand to the left operand and assigns the result.

Addition Assignment
1
2
3
4
5
package main
import fmt
var x int = 10
x += 5  // Equivalent to: x = x + 5
fmt.Printf("x = %d\n", x)  // Output: x = 15

Equivalent Forms:

Equivalent Forms
1
2
3
4
5
// Compound assignment (preferred)
counter += increment

// Expanded form (verbose)
counter = counter + increment

Subtraction Assignment (-=)

Subtracts the right operand from the left operand and assigns the result.

Subtraction Assignment
1
2
3
4
5
package main
import fmt
var balance int = 100
balance -= 25  // Equivalent to: balance = balance - 25
fmt.Printf("balance = %d\n", balance)  // Output: balance = 75

Multiplication Assignment (*=)

Multiplies the left operand by the right operand and assigns the result.

Multiplication Assignment
1
2
3
4
5
package main
import fmt
var score int = 10
score *= 3  // Equivalent to: score = score * 3
fmt.Printf("score = %d\n", score)  // Output: score = 30

Division Assignment (/=)

Divides the left operand by the right operand and assigns the result.

Division Assignment
1
2
3
4
5
package main
import fmt
var total int = 100
total /= 4  // Equivalent to: total = total / 4
fmt.Printf("total = %d\n", total)  // Output: total = 25

Modulo Assignment (%=)

Computes the modulo of the left operand with the right operand and assigns the result.

Modulo Assignment
1
2
3
4
5
package main
import fmt
var remainder int = 17
remainder %= 5  // Equivalent to: remainder = remainder % 5
fmt.Printf("remainder = %d\n", remainder)  // Output: remainder = 2

Exponentiation Assignment (**=)

Raises the left operand to the power of the right operand and assigns the result.

Exponentiation Assignment
1
2
3
4
5
package main
import fmt
var base int = 2
base **= 3  // Equivalent to: base = base ** 3
fmt.Printf("base = %d\n", base)  // Output: base = 8

Floor Division Assignment (</=)

Performs floor division and assigns the result.

Floor Division Assignment
1
2
3
4
5
package main
import fmt
var dividend int = 17
dividend </= 3  // Equivalent to: dividend = dividend </ 3
fmt.Printf("dividend = %d\n", dividend)  // Output: dividend = 5

Bitwise Compound Assignment Operators

Bitwise AND Assignment (&=)

Performs bitwise AND and assigns the result.

Bitwise AND Assignment
1
2
3
4
5
package main
import fmt
var flags int = 15  // 1111 in binary
flags &= 7          // 0111 in binary
fmt.Printf("flags = %d\n", flags)  // Output: flags = 7

Bitwise OR Assignment (|=)

Performs bitwise OR and assigns the result.

Bitwise OR Assignment
1
2
3
4
5
package main
import fmt
var permissions int = 4  // 100 in binary (read)
permissions |= 2         // 010 in binary (write)
fmt.Printf("permissions = %d\n", permissions)  // Output: permissions = 6 (110)

Bitwise XOR Assignment (^=)

Performs bitwise XOR and assigns the result.

Bitwise XOR Assignment
1
2
3
4
5
package main
import fmt
var value int = 12  // 1100 in binary
value ^= 5          // 0101 in binary
fmt.Printf("value = %d\n", value)  // Output: value = 9 (1001)

Left Shift Assignment (<<=)

Performs left shift and assigns the result.

Left Shift Assignment
1
2
3
4
5
package main
import fmt
var number int = 3  // 11 in binary
number <<= 2        // Shift left by 2 positions
fmt.Printf("number = %d\n", number)  // Output: number = 12 (1100)

Right Shift Assignment (>>=)

Performs right shift and assigns the result.

Right Shift Assignment
1
2
3
4
5
package main
import fmt
var value int = 24  // 11000 in binary
value >>= 2         // Shift right by 2 positions
fmt.Printf("value = %d\n", value)  // Output: value = 6 (110)

Practical Examples

1. Counter and Accumulator Patterns

Counter and Accumulator Patterns
package main
import fmt
// Event counter
var eventCount int = 0
eventCount += 1  // Increment by 1
eventCount += 5  // Increment by 5

// Running total
var total int = 0
var values = [10, 20, 30, 40]
for var i = 0; i < len(values); i = i + 1 {
    total += values[i]
}
fmt.Printf("Total: %d\n", total)  // Output: Total: 100

2. Mathematical Calculations

Compound Interest Calculation
package main
import fmt
// Compound interest calculation
var principal int = 1000
var rate int = 5  // 5% as integer
var years int = 3

for var year = 0; year < years; year = year + 1 {
    principal += (principal * rate) / 100
    fmt.Printf("Year %d: $%d\n", year + 1, principal)
}

3. Bit Flag Management

Bit Flag Management
package main
import fmt
// File permission system
var READ_PERMISSION int = 1   // 001
var WRITE_PERMISSION int = 2  // 010
var EXEC_PERMISSION int = 4   // 100

var userPermissions int = 0

// Grant read permission
userPermissions |= READ_PERMISSION
fmt.Printf("After granting read: %d\n", userPermissions)  // 1

// Grant write permission
userPermissions |= WRITE_PERMISSION
fmt.Printf("After granting write: %d\n", userPermissions)  // 3

// Revoke write permission
userPermissions &= ~WRITE_PERMISSION
fmt.Printf("After revoking write: %d\n", userPermissions)  // 1

4. Performance Optimizations

Bit-Shift Optimizations
package main
import fmt
// Fast multiplication/division by powers of 2
var value int = 10

value <<= 1  // Multiply by 2 (faster than value *= 2)
fmt.Printf("After <<= 1: %d\n", value)  // 20

value >>= 2  // Divide by 4 (faster than value /= 4)
fmt.Printf("After >>= 2: %d\n", value)  // 5

5. String and Array Processing

String and Array Processing
package main
import fmt
// Character frequency counting (conceptual)
var charCount int = 0
// For each character in string
charCount += 1  // Increment count

// Array size management
var arraySize int = 10
arraySize *= 2  // Double the size
fmt.Printf("New array size: %d\n", arraySize)  // 20

Advanced Usage Patterns

1. Chained Operations

Chained Operations
1
2
3
4
5
6
7
8
package main
import fmt
var value int = 5
value += 3   // 8
value *= 2   // 16
value -= 4   // 12
value /= 3   // 4
fmt.Printf("Final value: %d\n", value)  // 4

2. Conditional Compound Assignment

Conditional Compound Assignment
package main
import fmt
var score int = 85
var bonus int = 10

// Add bonus if score is above threshold
if score > 80 {
    score += bonus
}
fmt.Printf("Final score: %d\n", score)  // 95

3. Loop-Based Accumulation

Loop-Based Accumulation
package main
import fmt
// Factorial calculation using compound assignment
var factorial int = 1
var n int = 5

for var i = 1; i <= n; i = i + 1 {
    factorial *= i
}
fmt.Printf("%d! = %d\n", n, factorial)  // 5! = 120

4. Bit Manipulation Algorithms

Bit Manipulation Algorithms
package main
import fmt
// Set multiple bits using compound assignment
var bitMask int = 0
bitMask |= 1 << 0  // Set bit 0
bitMask |= 1 << 2  // Set bit 2
bitMask |= 1 << 4  // Set bit 4
fmt.Printf("Bit mask: %d\n", bitMask)  // 21 (10101 in binary)

// Clear specific bits
bitMask &= ~(1 << 2)  // Clear bit 2
fmt.Printf("After clearing bit 2: %d\n", bitMask)  // 17 (10001 in binary)

Performance Benefits

1. Efficiency

Compound assignment operators can be more efficient than their expanded forms:

Efficiency Example
1
2
3
4
5
// More efficient (single operation)
array[complexIndex()] += value

// Less efficient (evaluates complexIndex() twice)
array[complexIndex()] = array[complexIndex()] + value

2. Atomic Operations

In concurrent programming contexts, compound assignments can be more atomic:

Atomicity Considerations
1
2
3
4
5
6
7
// Single atomic operation (conceptually)
counter += 1

// Multiple operations (potential race condition)
var temp = counter
temp = temp + 1
counter = temp

3. Compiler Optimizations

Compilers can better optimize compound assignments:

Compiler Optimizations
1
2
3
4
5
// Compiler can optimize this better
value <<= 2  // Multiply by 4 using bit shift

// Less optimizable
value = value * 4

Best Practices

1. Use for Readability

Use for Readability
1
2
3
4
5
6
7
8
9
// Clear and concise
total += item.price
count -= removed
balance *= interestRate

// Verbose and repetitive
total = total + item.price
count = count - removed
balance = balance * interestRate

2. Consistent Style

Consistent Style
1
2
3
4
5
6
7
8
9
// Consistent compound assignment style
score += basePoints
score += bonusPoints
score -= penalties

// Mixed style (avoid)
score += basePoints
score = score + bonusPoints
score -= penalties

3. Appropriate Spacing

Appropriate Spacing
1
2
3
4
5
6
7
// Good spacing
value += increment
result *= factor

// Poor spacing (avoid)
value+=increment
result*=factor

4. Complex Expressions

Complex Expressions
1
2
3
4
5
6
7
// Use parentheses for clarity
result += (a * b) + (c / d)

// Avoid overly complex right-hand sides
// Break into multiple statements if needed
var temp int = complexCalculation()
result += temp

Common Pitfalls and Solutions

1. Type Compatibility

Type Compatibility
1
2
3
4
5
6
7
8
9
// Ensure compatible types
var intValue int = 10
var floatValue float64 = 3.14

// This would cause a type error:
// intValue += floatValue  // Error: type mismatch

// Solution: explicit conversion
intValue += int(floatValue)

2. Overflow Considerations

Overflow Considerations
1
2
3
4
5
6
7
8
// Be aware of potential overflow
var largeValue int = 1000000
largeValue *= 1000000  // Potential overflow

// Consider bounds checking for critical applications
if largeValue <= maxSafeValue / multiplier {
    largeValue *= multiplier
}

3. Division by Zero

Division by Zero
// Always check for division by zero
var dividend int = 100
var divisor int = getDivisor()

if divisor != 0 {
    dividend /= divisor
} else {
    // Handle division by zero
    fmt.Println("Error: Division by zero")
}

4. Bitwise Operations on Signed Numbers

Bitwise on Signed Numbers
1
2
3
4
5
6
7
// Be careful with bitwise operations on negative numbers
var signedValue int = -8
signedValue >>= 1  // Result depends on sign extension behavior

// Use unsigned types for pure bit manipulation
var unsignedValue uint = 8
unsignedValue >>= 1  // Predictable result

Comparison with Other Languages

Similarities with C/C = C + 1/Java

Similarities
1
2
3
4
// Harneet (similar to C/C++/Java)
value += 5
count *= 2
flags |= mask

Differences from Python

Differences from Python
1
2
3
4
5
// Harneet uses </ for floor division assignment
result </= 3

// Python uses // for floor division, but Harneet uses </
// about integer vs float behavior

Summary

Compound assignment operators in Harneet provide:

  1. Conciseness: Shorter, more readable code
  2. Efficiency: Potentially better performance
  3. Consistency: Uniform syntax across different operations
  4. Safety: Reduced chance of errors from repeated variable names

All Compound Assignment Operators

Operator Operation Example Equivalent
+= Addition x += 5 x = x + 5
-= Subtraction x -= 3 x = x - 3
*= Multiplication x *= 2 x = x * 2
/= Division x /= 4 x = x / 4
%= Modulo x %= 3 x = x % 3
**= Exponentiation x **= 2 x = x ** 2
</= Floor Division x </= 3 x = x </ 3
&= Bitwise AND x &= 7 x = x & 7
\|= Bitwise OR x \|= 8 x = x \| 8
^= Bitwise XOR x ^= 5 x = x ^ 5
<<= Left Shift x <<= 2 x = x << 2
>>= Right Shift x >>= 1 x = x >> 1

Use compound assignment operators to write cleaner, more efficient, and more maintainable Harneet code.