Function Variadic Arguments (*args)¶
Sharpy supports a limited form of variadic arguments using the *args syntax. Unlike Python's fully dynamic *args, Sharpy's variadic arguments are homogeneously typed: all arguments must be of the same type T.
Syntax¶
Examples¶
# Sum any number of integers
def sum_all(*numbers: int) -> int:
result = 0
for n in numbers:
result += n
return result
# Call with any number of arguments
total = sum_all(1, 2, 3) # 6
total = sum_all(1, 2, 3, 4, 5) # 15
total = sum_all() # 0 (empty tuple)
# Print multiple messages
def log_all(*messages: str) -> None:
for msg in messages:
print(msg)
log_all("Starting", "Processing", "Done")
Rules and Restrictions¶
Homogeneous typing¶
All variadic arguments must be of the same declared type T:
def process(*items: int) -> int:
return sum(items)
process(1, 2, 3) # OK: all ints
process(1, "two", 3) # ERROR: "two" is str, not int
Position requirement¶
The *args parameter must appear after all positional parameters. Keyword-only parameters may follow *args (see Flexible Arguments):
# ✅ Valid - *args at the end
def greet(prefix: str, *names: str) -> None:
for name in names:
print(f"{prefix} {name}")
greet("Hello", "Alice", "Bob", "Charlie")
# ✅ Valid - keyword-only parameters after *args
def log(level: str, *messages: str, sep: str = " ") -> None:
print(sep.join(messages))
log("INFO", "hello", "world", sep=", ")
# ❌ Invalid - positional parameters after *args
def broken(suffix: str, *items: int, other: str) -> None: # ERROR: positional after *args not allowed
pass
Note:
*argsimplicitly acts as the keyword-only separator*. See Flexible Arguments for details on positional-only and keyword-only parameter markers.
Only one *args per function¶
Type of *args Inside the Function¶
Inside the function body, the *args parameter has type array[T], mapping to C#'s params T[]:
def analyze(*values: float) -> tuple[float, float]:
# values: array[float]
if len(values) == 0:
return (0.0, 0.0)
return (min(values), max(values))
Unpacking Iterables with *¶
When calling a function with *args, you can unpack an iterable using the * operator:
def sum_all(*numbers: int) -> int:
result = 0
for n in numbers:
result += n
return result
# Direct arguments
sum_all(1, 2, 3) # 6
# Unpack a list
nums = [1, 2, 3, 4, 5]
sum_all(*nums) # 15
# Unpack a homogenously-typed tuple
t = (10, 20, 30)
sum_all(*t) # OK: 60
# Mixed: direct args and unpacking
sum_all(1, 2, *[3, 4], 5) # 15
Type checking for unpacking¶
The unpacked iterable must contain elements of the correct type:
def process(*items: int) -> int:
return sum(items)
int_list: list[int] = [1, 2, 3]
str_list: list[str] = ["a", "b", "c"]
int_tuple = (10, 20, 30)
mixed_tuple = (10, "str", 30)
process(*int_list) # OK
process(*str_list) # ERROR: list[str] cannot unpack to *args: int
process(*int_tuple) # OK
process(*mixed_tuple) # ERROR: tuple[int, str, int] cannot unpack to *args: int
C# Interop¶
Sharpy's *args maps directly to C#'s params arrays:
Sharpy:
Generated C#:
public static string FormatMessage(string template, params object[] args) {
return string.Format(template, args);
}
Calling C# params methods from Sharpy¶
from system import String
# String.Format has params signature: Format(string format, params object[] args)
result = String.format("Hello {0}, you have {1} messages", "Alice", 42)
# Or unpack from a collection
args = ["Bob", 10]
result = String.format("Hello {0}, you have {1} messages", *args)
Calling Sharpy *args functions from C¶
// Individual arguments (compiler creates array)
var total = SumAll(1, 2, 3, 4, 5);
// Explicit array
var numbers = new int[] { 1, 2, 3, 4, 5 };
var total = SumAll(numbers);
Function Type Compatibility¶
Function types cannot express variadic parameters. When you need a function type for a variadic function, use the non-variadic equivalent:
def sum_all(*numbers: int) -> int:
return sum(numbers)
# Cannot directly use sum_all as (int, int, int) -> int
# Instead, wrap it:
fixed_sum: (int, int, int) -> int = lambda a, b, c: sum_all(a, b, c)
Implementation
- ✅ Native - Maps to C# params T[] arrays.
See Also¶
- Function Parameters - Overview of all parameter types
- Function Default Parameters - Default parameter values
- Spread Operator - More about unpacking with
* - Function Definition - Basic function syntax