12

PowerShell ScriptBlock は、宣言環境で参照される変数を閉じないため、レキシカル クロージャーではありません。代わりに、ラムダ式で実行時にバインドされる動的スコープと自由変数を利用しているようです。

function Get-Block {
  $b = "PowerShell"
  $value = {"Hello $b"}
  return $value
}
$block = Get-Block
& $block
# Hello
# PowerShell is not written as it is not defined in the scope
# in which the block was executed.


function foo {
  $value = 5
  function bar {
    return $value
  }
  return bar
}
foo
# 5
# 5 is written $value existed during the evaluation of the bar function
# it is my understanding that a function is a named scriptblock
#  which is also registered to function:

ScriptBlock で GetNewClosure() を呼び出すと、参照されている変数を閉じる新しい ScriptBlock が返されます。しかし、これは範囲と能力が非常に限られています。

ScriptBlock の分類とは何ですか?

4

2 に答える 2

8

ドキュメントによると、 scriptblockは「スクリプトテキストのプリコンパイルされたブロック」です。したがって、デフォルトでは、事前に解析されたスクリプトのブロックだけで、それ以上でもそれ以下でもありません。実行すると子スコープが作成されますが、それを超えると、コードをインラインで貼り付けたようになります。したがって、最も適切な用語は単に「読み取り専用のソースコード」です。

動的に生成されたモジュールの呼び出しGetNewClosureボルト。基本的に、呼び出し時に呼び出し元のスコープ内のすべての変数のスナップショットを保持しますGetNewClosure。これは実際のクロージャではなく、単に変数のスナップショットコピーです。スクリプトブロック自体はまだ単なるソースコードであり、変数のバインドは呼び出されるまで発生しません。必要に応じて、添付のモジュールで変数を追加/削除/編集できます。

function GetSB
{
   $funcVar = 'initial copy'

   {"FuncVar is $funcVar"}.GetNewClosure()

   $funcVar = 'updated value'  # no effect, snapshot is taken when GetNewClosure is called
}

$sb = GetSB

& $sb  # FuncVar is initial copy

$funcVar = 'outside'
& $sb  # FuncVar is initial copy

$sb.Module.SessionState.PSVariable.Remove('funcVar')
& $sb  # FuncVar is outside
于 2012-09-25T17:44:13.277 に答える