【问题标题】:Powershell recursion failing? Variable clears when returnedPowershell递归失败?返回时变量清除
【发布时间】:2014-07-14 18:36:55
【问题描述】:

我正在尝试创建一个包含 1-8 个“单词”的“句子”列表,提供了一个单词列表,我不关心唯一性,因为我可以稍后过滤掉重复项。我认为递归函数是最好的方法,尤其是在我想在以后更改最大长度的情况下。

当我运行这段代码时,我得到了一个空结果。当我调试并单步执行时,我发现 $sents 会在 return 语句之前包含数据,然后在返回到第一个 else 语句中的 $sents 变量后立即没有数据。

这是我为 PowerShell 编写的第二个递归函数,但都没有用。第一个我最终崩溃并编写了 4 个嵌套的 foreach 语句。这将是 8 个嵌套语句(我不希望这样做),只是为了构建一个字符串数组,以便我可以处理它们。

任何帮助将不胜感激。谢谢!

function make-sentences ($ws, $ml, [String[]] $sent = @(), [String[]] $sents = @()) {
    [String[]] $nws = @()
    $sent += $ws[0]

if ($sent.length -ge $ml) {
    $sents += ($sent -join ",")
    return $sents
} elseif ($ws.length -le 1) {
    $sents += ($sent -join ",")
    return $sents
} else {
    for ($i = 1; $i -lt $ws.length; $i++) { $nws += $ws[$i] }
    $sents += make-sentences $nws $ml $sent $sents
}

[String[]] $nws = @()

if ($ws.length -le 1) {
    $sents += ($sent -join ",")
    return $sents
} else {
    $sent = @()
    for ($i = 1; $i -lt $ws.length; $i++) { $nws += $ws[$i] }
    $sents += make-sentences $nws $ml $sent $sents
}
}

$words = ("acfj","acfk","adfk","aefj","aefk","aegi","aehi","afgh")
[String[]] $sentences = make-sentences $words 8

$sentences

【问题讨论】:

  • 老实说,我很难说出你的方法是什么。看来您应该在 while 循环中执行此操作。但是,有几件事很突出。 1 - 您不能更改输入的非对象变量,除非它们是引用变量。 2 - 这对于手头的任务来说过于复杂:)

标签: powershell recursion return


【解决方案1】:

抱歉,我没有花太多时间阅读您的代码,但您必须知道的是,在 PowerShell 中,当您调用函数时,参数的默认行为如下(通过参数调用):

function Dumy ($param1)
{
  $param1 = 100
  Write-Host "$param1 in function Dumy"
}


$param1 = 10
Write-Host "$param1 in main function before call to Dumy"
Dumy $param1
Write-Host "$param1 in main function after call to Dumy"

它给出:

10 in main function before call to Dumy
100 in function Dumy
10 in main function after call to Dumy

如果你想修改参数的值,你应该使用引用调用:

function Dumy ([ref]$param1)
{
  $param1.value = 100
  Write-Host "$($param1.value) in function Dumy"
}


$param1 = 10
Write-Host "$param1 in main function before call to Dumy"
Dumy ([ref]$param1)
Write-Host "$param1 in main function after call to Dumy"

它给出:

10 in main function before call to Dumy
100 in function Dumy
100 in main function after call to Dumy

另一种解决方案是使用变量作用域来修改调用作用域内函数中的变量(对我来说就像使用全局变量一样)。

【讨论】:

    【解决方案2】:

    我认为您的 $sentences 变量是空的,因为您的函数 - 即使是递归的 - 也没有 return 语句。您有一个仅用于终端情况的 return 语句,但在递归调用函数时不要求 return 语句。然后,您的函数返回调用堆栈内部的内容,但不会要求您的主调用返回任何内容。

    以下是阶乘递归函数的两个示例,第一个看起来像您的实现,并且不返回任何内容。实际上,递归调用存储在一个变量中,然后该函数不会返回任何内容。 第二个例子确实返回了一些东西,因为在每种情况下,函数都被要求返回一个值,即使是通过递归调用:

    function fact-Noresult ([int]$n, [int]$result=1){
      if ($n -eq 0) {
        Write-Host "returning now ! value = $result"
        return $result
      }else {
        $result = $n * (fact-Noresult ($n-1) ($result*$n))        
      }
    }
    
    function fact-WithResult ([int]$n, [int]$result=1){
      if ($n -eq 0) {
        return $result
      }else {
        $result=$n*$result
        fact-WithResult ($n-1) $result
    
      }
    }
    

    如果您尝试调用它们,您会看到第一个显示消息,并显示正确的值,但不返回它。

    【讨论】:

    • 值得注意的是,Powershell 中的return 是语法糖——你可以在函数末尾加上$result 来返回它。
    • @JNK :我知道 return 不需要让函数返回一些东西。我的意思是 OP 试图以不提供任何结果的方式调用递归函数。这也是我试图用上面的两个函数来展示的。如果您删除returnkeywords,我的两个示例仍然正确
    • 是的,我并不是要暗示你不知道,我只是想让其他阅读者清楚。
    猜你喜欢
    • 2011-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-29
    • 1970-01-01
    • 2016-02-02
    • 2022-11-10
    相关资源
    最近更新 更多