Function/Invoke-IteratedFunction.ps1
function Invoke-IteratedFunction { [Alias('iterate')] [CmdletBinding(PositionalBinding = $false)] param( # The stateless process scriptblock / filter function to iterate over each input item. # All of $_, $PSItem, and $Input are bound within the process scriptblock / filter function. [Parameter(Mandatory, Position = 0)] [ValidateNotNull()] [scriptblock] $Process, # The initial value to input to $Process. [Parameter(Mandatory, ValueFromPipeline)] [object] [AllowNull()] [Alias('InputObject')] $Seed, # Predicate of one input that determines whether to continue after each iteration. # The seed value is not tested; i.e. $Process will be invoked at least once. [Parameter()] [scriptblock] [ValidateNotNull()] $While = { $true }, # Returns $Seed prior to the first invocation of $Process. [Parameter()] [switch] $PassThru, # Does not allow any output to be enumerated when written to the pipeline. # Applies to both $Seed (if -PassThru) as well as the output of each invocation of $Process. # Outputs of separate iterations of $Process are always written to the pipeline separately, regardless of -NoEnumerate. [Parameter()] [switch] $NoEnumerate ) process { if ($PassThru) { Write-Output $Seed -NoEnumerate:$NoEnumerate } # ForEach-Object MUST be used to invoke $Process to get proper binding for _all_ automatic input variables. try { do { $Seed = ForEach-Object $Process -InputObject $Seed Write-Output $Seed -NoEnumerate:$NoEnumerate } while (ForEach-Object $While -InputObject $Seed) } catch { Write-Error -Exception $_ } } } |