package main

import "fmt"

// section: example

// Example variadic function that accepts any number of integers
func sum(numbers ...int) int {
	total := 0
	for _, n := range numbers {
		total += n
	}
	return total
}

// Another variadic function
func printNames(prefix string, names ...string) {
	fmt.Printf("%s: ", prefix)
	for i, name := range names {
		if i > 0 {
			fmt.Print(", ")
		}
		fmt.Print(name)
	}
	fmt.Println()
}

func main() {
	// The ellipsis operator (...) has five main uses in Go:

	// Use 1: Variadic function parameters
	// Allows a function to accept a variable number of arguments
	fmt.Println("--- Use 1: Variadic Function Parameters ---")
	fmt.Println("sum(1, 2, 3):", sum(1, 2, 3))
	fmt.Println("sum(10, 20, 30, 40, 50):", sum(10, 20, 30, 40, 50))

	// Use 2: Unpacking slices into variadic functions
	// The ... operator "unpacks" a slice into individual arguments
	fmt.Println("\n--- Use 2: Unpacking Slices ---")
	numbers := []int{5, 10, 15, 20}
	fmt.Printf("numbers slice: %v\n", numbers)
	fmt.Printf("sum(numbers...): %d\n", sum(numbers...))

	// Without ..., this would be a compile error:
	// sum(numbers) // ERROR: cannot use numbers (type []int) as type int

	// Use 3: Unpacking slices with append
	fmt.Println("\n--- Use 3: Append with Slice Unpacking ---")
	fruits := []string{"apple", "banana"}
	moreFruits := []string{"cherry", "date", "elderberry"}

	// Append individual elements
	fruits = append(fruits, "fig")
	fmt.Printf("After append single: %v\n", fruits)

	// Append entire slice - requires ... to unpack
	fruits = append(fruits, moreFruits...)
	fmt.Printf("After append slice:  %v\n", fruits)

	// Use 4: Array literals with inferred length
	fmt.Println("\n--- Use 4: Array Literals (inferred length) ---")
	// The compiler counts the elements and sets the array size
	inferredArray := [...]string{"red", "green", "blue"}
	fmt.Printf("Array: %v (type: %T, len: %d)\n", inferredArray, inferredArray, len(inferredArray))

	// This is equivalent to:
	explicitArray := [3]string{"red", "green", "blue"}
	fmt.Printf("Array: %v (type: %T, len: %d)\n", explicitArray, explicitArray, len(explicitArray))

	// Use 5: Combining variadic functions
	fmt.Println("\n--- Use 5: Practical Example ---")
	allNames := []string{"Alice", "Bob", "Charlie"}
	printNames("Team members", allNames...)

	// You can also mix literal values with slice unpacking in some contexts
	moreNames := []string{"David", "Eve"}
	combined := append(allNames, moreNames...)
	printNames("All members", combined...)

	// Common gotcha: Can't use ... on left side of assignment
	fmt.Println("\n--- Common Gotcha ---")
	fmt.Println("The ... operator ONLY works on the right side (as an argument)")
	fmt.Println("You CANNOT use it to destructure/unpack on the left side like:")
	fmt.Println("  a, b, c... := []int{1, 2, 3, 4, 5}  // This is INVALID")
}

// section: example
