我可以用javascript编写以下代码:
function sum(num1, num2) {
return num1 + num2;
}
然后获取一个值
var someNum = sum(2,5);
我想在Powershell中做同样的事情,但是我读了following guide:
PowerShell也知道return关键字;但是,它遵循 不同的逻辑。一般而言,退货的目的是结束 执行代码段并将控制权交还给父代
如果在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)是使所有这些保持一致,这也不可读。
答案 0 :(得分:5)
完全是多余的,当我可以调用上面的函数,在其中定义someNum时,它将在全局范围内可用。
否:函数在 child 范围中执行(除非您使用.
点源它们),因此在函数内部创建或分配给它们的变量是本地。
我是否缺少某些东西,或者有可能在Powershell中编写不返回函数内部所有内容的纯函数?
是:隐式输出行为仅适用于既没有捕获-$var = ...
-也没有重定向-... > foo.txt
的语句
如果有一些语句恰好会产生您要放弃的输出,请使用$null = ...
或... > $null
注意:... | Out-Null
原则上也可以工作,但通常表现较差,尤其是在早期的PowerShell版本中,谢谢TheIncorrigible1。
如果您有 个状态消息,但您不想编写它们,则不写它们,请使用Write-Host
或最好使用{ {1}},或者在PSv5 +中,Write-Verbose
,尽管请注意,后两个要求选择接受才能在控制台中看到其输出。
请勿使用Write-Information
来写状态消息,因为它会写入成功输出流,其目的是输出 data (“返回值”)。< br />
有关PowerShell的输出流的更多信息,请参见我的this answer。
因此,您的JavaScript代码等效于:
Write-Output
答案 1 :(得分:1)
我是否缺少某些东西,或者有可能在Powershell中编写不返回函数内部所有内容的纯函数?
你不能吃蛋糕也不能吃...
如果您的功能没有投入,那么它就是您想要的“纯”。如果您有输出,那也将成为返回的一部分。
您可以使用[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
答案 2 :(得分:1)
注意:Powershell在每个语句的末尾不需要分号;仅用于分隔同一行中的多个语句。
尽可能避免在函数中更改全局状态是一个好主意。将输入作为参数传递,然后返回输出,因此您不必仅以一种方式使用该函数。您的示例可能如下所示:
function sum
{
param($num1,$num2)
return $num1+$num2
}
$somenum=sum 2 5
现在,使用Powershell,不需要return语句。未分配,捕获,重定向或以其他方式使用的每个语句的结果都将与返回值一起抛出。因此,我们可以简单地将上面的return语句替换为
$num1+$num2
您已经在代码中使用此功能了,
$previousScripts.Add($key) | Out-Null
您要丢弃.Add()
的结果的位置。否则它将包含在返回值中。
个人而言,我发现使用return
显式标记返回值使读取起来更容易。在我学习的过程中,Powershell将所有输出(如果输出返回)都给我带来了很多麻烦。
因此,我要对您的代码进行的唯一修复是:
将$previousScripts = New-Object Collections.Generic.HashSet[string]
移动到函数内部,使其位于本地。
在函数末尾添加return $previousScripts
。