匿名递归函数
Anonymous Recursive Function
是否可以在 PowerShell 中创建匿名递归函数? (如果是,如何?)
我有一个递归对象并使用递归函数向下钻取属性,例如:
$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
函数比较小,只需要一个,所以我想直接调用它作为一个匿名函数,有些像:
(&{
$Object.Name
if ($Object.Folder) { ???? $Object.Folder }
}) -Join '\'
这在 PowerShell 中可行吗?
如果是,我如何(尽可能干净)引用 ????
处的当前函数?
不幸的是,关于此主题的文档不多,但您可以通过调用 $MyInvocation.MyCommand.ScriptBlock
来执行匿名脚本块,一个简单的示例:
& {
param([int] $i)
if($i -eq 10) { return $i }
($i++)
& $MyInvocation.MyCommand.ScriptBlock $i
}
# Results in 0..10
以您当前的代码和 Json 为例:
(& {
param($s)
$s.Name
if ($s.Folder) { & $MyInvocation.MyCommand.ScriptBlock $s.Folder }
} $Object) -Join '\'
# Results in Level1\Level2\Level3
代码有点多,但同样可以使用 Collections.Queue
而不是递归来完成,这可能是一种更节省资源的方法:
$(
$queue = [System.Collections.Queue]::new()
$queue.Enqueue($object)
while($queue.Count) {
$node = $queue.Dequeue()
$node.Name
if($node.Folder) { $queue.Enqueue($node.Folder) }
}
) -Join '\'
@Santiago's helpful 正是我最初寻找的地方。
然而,并不总是需要递归函数来遍历递归对象。
就像在 mcve 中一样,我本可以做到的:
@(
do {
$Object.Name
$Object = $Object.Folder
} while ($Object)
) -Join '\'
是否可以在 PowerShell 中创建匿名递归函数? (如果是,如何?)
我有一个递归对象并使用递归函数向下钻取属性,例如:
$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
函数比较小,只需要一个,所以我想直接调用它作为一个匿名函数,有些像:
(&{
$Object.Name
if ($Object.Folder) { ???? $Object.Folder }
}) -Join '\'
这在 PowerShell 中可行吗?
如果是,我如何(尽可能干净)引用 ????
处的当前函数?
不幸的是,关于此主题的文档不多,但您可以通过调用 $MyInvocation.MyCommand.ScriptBlock
来执行匿名脚本块,一个简单的示例:
& {
param([int] $i)
if($i -eq 10) { return $i }
($i++)
& $MyInvocation.MyCommand.ScriptBlock $i
}
# Results in 0..10
以您当前的代码和 Json 为例:
(& {
param($s)
$s.Name
if ($s.Folder) { & $MyInvocation.MyCommand.ScriptBlock $s.Folder }
} $Object) -Join '\'
# Results in Level1\Level2\Level3
代码有点多,但同样可以使用 Collections.Queue
而不是递归来完成,这可能是一种更节省资源的方法:
$(
$queue = [System.Collections.Queue]::new()
$queue.Enqueue($object)
while($queue.Count) {
$node = $queue.Dequeue()
$node.Name
if($node.Folder) { $queue.Enqueue($node.Folder) }
}
) -Join '\'
@Santiago's helpful
然而,并不总是需要递归函数来遍历递归对象。
就像在 mcve 中一样,我本可以做到的:
@(
do {
$Object.Name
$Object = $Object.Folder
} while ($Object)
) -Join '\'