Is it possible to create an anonymous Recursive Function in PowerShell? (if yes, how?)
I have a recursive object and using a recursive function to drill down through the properties, like:
$Object = ConvertFrom-Json '
{
"Name" : "Level1",
"Folder" : {
"Name" : "Level2",
"Folder" : {
Name : "Level3"
}
}
}'
Function GetPath($Object) {
$Object.Name
if ($Object.Folder) { GetPath $Object.Folder }
}
(GetPath($Object)) -Join '\'
Level1\Level2\Level3
The function is relative small and only required ones, therefore I would like to directly invoke it as an anonymous function, some like:
(&{
$Object.Name
if ($Object.Folder) { ???? $Object.Folder }
}) -Join '\'
Is this possible in PowerShell?
If yes, how can I (as clean as possible) refer to the current function at ????
?
CodePudding user response:
Unfortunately there is not much documentation on this topic but you could execute the anonymous script block by calling $MyInvocation.MyCommand.ScriptBlock
, a simple example:
& {
param([int] $i)
if($i -eq 10) { return $i }
($i )
& $MyInvocation.MyCommand.ScriptBlock $i
}
# Results in 0..10
Using your current code and Json as example:
(& {
param($s)
$s.Name
if ($s.Folder) { & $MyInvocation.MyCommand.ScriptBlock $s.Folder }
} $Object) -Join '\'
# Results in Level1\Level2\Level3
A bit more code but the same can be accomplished using a Collections.Queue
instead of recursion, which is likely to be a more resource efficient way:
$(
$queue = [System.Collections.Queue]::new()
$queue.Enqueue($object)
while($queue.Count) {
$node = $queue.Dequeue()
$node.Name
if($node.Folder) { $queue.Enqueue($node.Folder) }
}
) -Join '\'
CodePudding user response:
@Santiago's helpful answer was exactly where I was initially looking for.
Nevertheless, it doesn't always require a recursive function to crawl through a recursive object.
As in the mcve, I could just have done:
@(
do {
$Object.Name
$Object = $Object.Folder
} while ($Object)
) -Join '\'