Движок вызывает на нем GetNewClosure()
, что лучше для него, чем нет.
Когда я запустил вышеупомянутое, я получил вывод только Value:
, но потом яглобально объявил $y = 25
и снова запустил [void](new-event -sourcei 'foo')
, результат был Value: 25
.Затем я снова изменил его значение, $y = 38
, и снова запустил событие: Value: 38
.
Если вы хотите выпекать значение $y
во время создания действия, одинспособ сделать это - создать скрипт-блок таким образом, чтобы значение $y
становилось литералом или частью литерала:
$action = &{ $y = 100
return (invoke-expression "{write-host 'Value: $y'}")
}
Сначала выполняется синтаксический анализ строки для вставки значения, поэтому Invoke-Expression
заканчивает тем, что делал эквивалент этого:
{write-host 'Value: 100'}
Я не уверен, есть ли какие-либо другие способы запекать в значении кроме составления всего содержания блока скрипта в строке и передачи егочерез Invoke-Expression
.
В ответ на ваш комментарий, дальнейшее объяснение замыканий:
> $action100 = &{$y = 100; return {write-host "Value: $y"}.GetNewClosure()}
> &$action100
Value: 100
Это ожидаемый результат, и это то, что вы получаете, потому что блок скриптоввсе еще "закрыт" вокруг значения $y
в области, где был вызван GetNewClosure()
.
> $y = 25
> &$action100
Value: 100
Все еще закрыт вокруг $y
, то есть 100
.
> $action25 = $action100.GetNewClosure()
> &$action25
Value: 25
Это создает новый скрипт-блок, который содержит переменныев текущем объеме.Это заставляет его переоценивать, что $y
находится в этом блоке сценариев, и в этом контексте $y
теперь равно 25.
> $y = 38
> &$action100
Value: 100
> &$action25
Value: 25
> &($action100.GetNewClosure())
Value: 38
На данный момент, потому что $y
объявлено глобально сейчас, когдаВы звоните New-Event
, он будет использовать GetNewClosure()
и повторно оценивать $y
в 38
, и печатать Value: 38
.Вы получаете Value:
, потому что в контексте, где события движка вызывают GetNewClosure()
, переменная $y
не определена, поэтому "Value: $y"
становится "Value: "
.