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 |
|---|
| 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 |
|---|
| // 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 |
|---|
| 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 |
|---|
| 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 |
|---|
| 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 |
|---|
| 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 |
|---|
| 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 |
|---|
| 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 |
|---|
| 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 |
|---|
| 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 |
|---|
| 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 |
|---|
| 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 |
|---|
| 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
|
| 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 |
|---|
| 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)
|
1. Efficiency
Compound assignment operators can be more efficient than their expanded forms:
| Efficiency Example |
|---|
| // 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 |
|---|
| // 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 |
|---|
| // 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 |
|---|
| // 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 |
|---|
| // 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 |
|---|
| // Good spacing
value += increment
result *= factor
// Poor spacing (avoid)
value+=increment
result*=factor
|
4. Complex Expressions
| Complex Expressions |
|---|
| // 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 |
|---|
| // 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 |
|---|
| // 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 |
|---|
| // 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 |
|---|
| // Harneet (similar to C/C++/Java)
value += 5
count *= 2
flags |= mask
|
Differences from Python
| Differences from Python |
|---|
| // 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:
- Conciseness: Shorter, more readable code
- Efficiency: Potentially better performance
- Consistency: Uniform syntax across different operations
- 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.