This post discusses a hypothetical C# feature called 'Argument Plurality'.
Consider the following:
Being written as:
The introduced 'each' keyword allows iteration-over-collection to be specified at the argument level:
Since 'name' isn't being referenced in this example it can be omitted:
Add to this tighter integration of SQL-style querying:
Iterating over nested collections:
Joining peer pluralities via operator:
Argument plurality alongside non-plural (conventional) argument:
Is (effectively) expanded to:
Zero invocations are possible too:
Function receiving multiple argument pluralities:
Lambda receiving collection param as a plurality:
Consider the following:
C#:
foreach (var name in names)
print(name);
Being written as:
Hypothetical C#:
for (each var name in names) // replaces foreach
print(name);
The introduced 'each' keyword allows iteration-over-collection to be specified at the argument level:
Hypothetical C#:
print(each var name in names); // Argument plurality invokes 'print' for each element in 'names' (this effects a foreach loop without writing one)
Since 'name' isn't being referenced in this example it can be omitted:
Hypothetical C#:
print(each var in names); // includes nulls
print(each String in names); // includes only String[s] (excludes nulls)
Add to this tighter integration of SQL-style querying:
Hypothetical C#:
print(each String name in names where name.StartsWith("B")); // null safe due to implied filtering for String[s]
Iterating over nested collections:
Hypothetical C#:
// Assume persons is Person[] containing everyone in the world
// Assume Person.inventory is Item[]
// Print everyone's items
for (each Item item in (each Person in persons).inventory)
print(item);
// The above, using argument plurality
print(each Item in (each Person in persons).inventory);
// Can similarly be written as
print(each var in (each Person in persons).inventory); // includes nulls
// However, specifying type qualifiers provides implicit filtering for those types
print(each ItemTool in (each Firefighter in persons).inventory); // implied filtering for ItemTool[s] and Firefighter[s]
// This is functionally equivalent to
print(each Item item in (each Person person in persons where person is Firefighter).inventory where item is ItemTool);
// Print all heavy tools of on-duty Firefighter[s] in city of Toronto
print(each ItemTool in (each Firefighter in persons where onDuty && location.Equals("Toronto")).inventory where weight >= 10);
Joining peer pluralities via operator:
Hypothetical C#:
var firstNames = new string[] { "Tom", "Bill", "Mike", "Gary", "Brad" };
var lastNames = new string[] { "Smith", "Johnson", "Edwards", "Brown" };
print(each var in firstNames + " " + each var in lastNames); // Print every first-last name permutation (lines outputted = 5 * 1 * 4 = 20)
print(each String f in firstNames where f.StartsWith("B") + " " + each var in lastNames); // with filtering (lines outputted = 2 * 1 * 4 = 8)
// Print multiplication table (assume factors = int[] {1..12})
print(each int m in factors + " x " + each int n in factors + " = " + (m * n)); // lines outputted = 12 * 1 * 12 = 144
Argument plurality alongside non-plural (conventional) argument:
Hypothetical C#:
// Assume 'print' function now has signature print(int indent, String text)
int indent = 4;
print(indent, each String in firstNames);
Is (effectively) expanded to:
C#:
print(4, "Tom");
print(4, "Bill");
print(4, "Mike");
print(4, "Gary");
print(4, "Brad");
Zero invocations are possible too:
Hypothetical C#:
var names = new string[] { }; // empty
print (4, each String in names); // called zero times
Function receiving multiple argument pluralities:
Hypothetical C#:
// Assume printProduct has signature (int m, int n)
// Assume factors = int[] {1..12}
printProduct(each int in factors, each int in factors); // lines outputted = 12 * 12 = 144
Lambda receiving collection param as a plurality:
Hypothetical C#:
c => foreach (var e in c) func(e) // conventional method of iterate-over-collection 'c'
var e in c => func(e) // using plurality mechanism