I see you already have a solution, but your initial question triggered my curiosity to find an elegant algorithm. Initially I thought you needed a parallel approach, then later I saw your ‘higher order’ solution which uses sequential calculations, so I worked that out too. In short, the sequential solution below performs the same calculations as in your example (I think). The parallel algorithm does not, but I thought it worth sharing FWIW. Cheers!
from algorithm.functional import parallelize
alias fn_sig = fn (a: Int, b: Int) -> Int
struct Op(Copyable & Movable):
"""Contains mathematical operations."""
alias Add = Self.add
alias Mul = Self.mul
var operation: fn_sig
var a: Int
var b: Int
fn __init__(out self, operation: fn_sig, a: Int, b: Int):
self.operation = operation
self.a = a
self.b = b
@parameter
fn __call__(self, out value: Int):
"""Parallel - returns values from initial arguments."""
value = self.operation(self.a, self.b)
@parameter
fn __call__(self, mut value: Int):
"""Sequential - mutates the 'value' argument."""
value = self.operation(value, self.b)
@staticmethod
fn bind(func: fn_sig, a: Int, b: Int, out result: Self):
result = Self(func, a, b)
@staticmethod
fn add(a: Int, b: Int, out value: Int):
value = a + b
@staticmethod
fn mul(a: Int, b: Int, out value: Int):
value = a * b
fn main():
alias RESIZE_DEFAULT = -1 # Value not important.
operations = List[Op]()
# 1) Sequential calculations.
value = 1
operations.append(Op.bind(Op.Add, value, 7))
operations.append(Op.bind(Op.Mul, value, 11))
# Perform Sequential calculations.
for op in operations:
op[](value)
print("Sequential value =", String(value))
print()
# 2) Parallel calculations.
print("Parallel results:")
operations.clear()
operations.append(Op.bind(Op.Add, 1, 2))
operations.append(Op.bind(Op.Mul, 3, 4))
operations.append(Op.bind(Op.Add, 5, 6))
operations.append(Op.bind(Op.Mul, 7, 8))
operations.append(Op.bind(Op.Add, 9, 10))
results = List[Int]()
results.resize(len(operations), RESIZE_DEFAULT)
# Nested function for parallel calculations.
@parameter
fn calc(index: Int):
results.insert(index, operations[index]())
print("results[" + String(index) + "] =", results[index])
# Perform parallel calculations.
num_work_items = len(operations)
num_workers = num_work_items
parallelize[calc](num_work_items, num_workers)
Output:
Sequential value = 88
Parallel results:
results[0] = 3
results[4] = 19
results[1] = 12
results[3] = 56
results[2] = 11