代码之家  ›  专栏  ›  技术社区  ›  VSO

Powershell中的显式返回

  •  2
  • VSO  · 技术社区  · 7 年前

    我可以用javascript编写以下代码:

    function sum(num1, num2) {
      return num1 + num2;
    }
    

    var someNum = sum(2,5);
    

    我也想在Powershell里做同样的事情,但是我读了 following guide:

    PowerShell也知道return关键字;但是,它遵循 执行代码段并将控件返回给父级 封锁。

    返回到调用子例程。然而,这也适用于 所有其他有输出的语句。这意味着任何输出 函数中产生的将与 返回参数。

    我想这样做是为了拥有纯函数。然而,它似乎做了

    var someNum = sum(2,5);

    someNum 在它内部,它将在全球范围内可用。

    我是否遗漏了什么,或者是否有可能在Powershell中编写不返回函数内部所有内容的纯函数?


    function GetPreviousKeyMD5Hashes() {
        $query = "SELECT Name, MD5, executed FROM [AMagicDb].[dbo].cr_Scripts";
    
        $command = New-Object System.Data.SQLClient.SQLCommand;
        $command.Connection = $connection;
        $command.CommandText = $query;
    
        try {
            $reader = $command.ExecuteReader();
            while ($reader.Read()) {
                $key = $reader.GetString(1)
                $previousScripts.Add($key) | Out-Null
            }
    
            $reader.Close();
            Write-Output "$(Get-Date) Finished querying previous scripts"
        }
        catch {
            $exceptionMessage = $_.Exception.Message;
            Write-Output "$(Get-Date) Error running SQL at with exception $exceptionMessage"
        }
    }
    

    然后:

    $previousScripts = New-Object Collections.Generic.HashSet[string];
    GetPreviousKeyMD5Hashes;
    

    我一点也不清楚这个代码-运行 GetPreviousKeyMD5Hashes 确定 $previousScripts ,但这对于在我之后修改这个的人来说是完全不清楚的。我唯一的另一个选择(afaik)是把所有这些都排成一行,这也是不可读的。

    3 回复  |  直到 7 年前
        1
  •  5
  •   mklement0    7 年前

    是完全多余的,当我可以调用上面的函数,在其中定义一些数,它将在全局范围内可用。

    不: 函数在 小孩 (除非你用 . ),因此在函数内部创建或分配的变量是 为了它。

    是的:那个 隐式输出行为仅适用于输出为 - $var = ... -也不是 重定向 ... > foo.txt

    如果有语句碰巧产生 你想要的输出 丢弃 ,使用 $null = ... ... > $null

    注: ... | Out-Null TheIncorrigible1 .

    状态消息 你想写的 而不是成为产出的一部分 ,使用 Write-Host Write-Verbose 或者,在PSv5+中, Write-Information ,但请注意,后两种情况需要opt-in才能在控制台中看到它们的输出。
    不使用 Write-Output ,当它写入成功输出流时,其目的是输出 数据
    this answer

    因此,JavaScript代码的等价物是:

    function sum($num1, $num2) {
      Write-Host "Adding $num1 and $num2..."  # print status message to host (console)
      $num1 + $num2 # perform the addition and implicitly output result
    }
    
    PS> $someNum = sum 1 2 # NOTE: arguments are whitespace-separated, without (...)
    Adding 1 and 2...  # Write-Host output was passed through to console
    
    PS> $someNum  # $someNum captured the success output stream of sum()
    3
    
        2
  •  1
  •   Kory Gill    7 年前

    你不能把蛋糕也吃了。。。

    如果你没有在你的功能,那么它是“纯”如你所愿。如果你有输出,这也成为回报的一部分。

    [ref] 参数。例如,见下文。

    function DoStuff([ref]$refObj)
    {
        Write-Output "DoStuff: Enter"
        $refObj.Value += $(1 + 2)
        $refObj.Value += "more strings"
        Write-Output "DoStuff: Exit"
    }
    
    $refRet = @()
    $allRet = DoStuff([ref]$refRet)
    
    "allRet"
    $allRet
    "refRet"
    $refRet
    
    "`n`nagain"
    $allRet = DoStuff([ref]$refRet)
    
    "allRet"
    $allRet
    "refRet"
    $refRet
    
        3
  •  1
  •   toastifer    7 年前

    只要可能,最好避免在函数中更改全局状态。将输入作为参数传递,并返回输出,这样就不必只以一种方式使用函数。您的示例可能如下所示:

    function sum
    {
        param($num1,$num2)
        return $num1+$num2
    }
    
    $somenum=sum 2 5
    

    现在,使用Powershell,不需要返回语句。每一条语句的结果如果不是以其他方式分配、捕获、重定向或使用的话,都会随返回值一起被抛出。所以我们可以用简单的

    $num1+$num2
    

    $previousScripts.Add($key) | Out-Null
    

    你要放弃的结果 .Add() . 否则它将包含在返回值中。

    return 显式标记返回值使其更易于读取。Powershell把所有的如果输出作为回报的方式给我造成了很多麻烦,因为我正在学习。

    所以,我对你的代码做的唯一修正是:

    $previousScripts = New-Object Collections.Generic.HashSet[string] 在函数内部,使其成为本地函数。

    添加 return $previousScripts 直到函数结束。

    推荐文章