首页 > 解决方案 > Powershell lambda 范围

问题描述

我正在尝试使用高阶函数来执行某个任务,但似乎范围没有按我的预期工作。代码如下:

function DoSomething($scriptBlock, $message) {

    # if not only running a check, run the given code
    if ($shouldRunCheck) {
       return $scriptBlock.Invoke()
    }

    Write-Host $message -foreground cyan
    # write $message to file
}

这似乎工作正常,但是当我调用它时,我似乎无法保存到脚本块之外的变量。

$myArray = @()
$myArray += 'test 1'

DoSomething {
   write-host $myArray # test 1
   $myArray += 'test 2'

   write-host $myArray # test 2
}

write-host $myArray # test 1
$myArray += 'test 3'
write-host $myArray # test 1 test 3

本质上,我需要从回调函数中添加到数组变量中,但它似乎只是覆盖了变量,就好像变量是只读的一样?

标签: powershellscopehigher-order-functions

解决方案


您对范围界定是正确的。

发生的情况是,在脚本块内,变量在执行$myArray时被创建为类型 [String] 的新变量$myArray += 'test 2'。这个新变量在函数之外不存在,所以原始变量根本$myArray没有改变。

为此,您需要在 上使用作用域$myArray并将其声明为$script:myArray = @('test 1')可以在整个脚本中访问它。
然后在脚本块中使用 向它添加新值$script:myArray += 'test 2',例如:

function DoSomething($scriptBlock) {
    return $scriptBlock.Invoke()
}

$script:myArray = @('test 1')                # declared in script-scope

# while inside the main script, you can simply access it as $myArray
Write-Host "MainScript:  $myArray"           # --> test 1   

$scriptBlock = {
   Write-Host "ScriptBlock: $script:myArray" # --> test 1
   $script:myArray += 'test 2'

   Write-Host "ScriptBlock: $script:myArray" # --> test 1 test 2
}

DoSomething $scriptBlock

Write-Host "MainScript:  $myArray"          # --> test 1 test 2
$myArray += 'test 3'
Write-Host "MainScript:  $myArray"          # --> test 1 test 2 test 3

结果:

MainScript:  test 1
ScriptBlock: test 1
ScriptBlock: test 1 test 2
MainScript:  test 1 test 2
MainScript:  test 1 test 2 test 3

推荐阅读