首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PowerShell ScriptBlock到底是什么?

PowerShell ScriptBlock到底是什么?
EN

Stack Overflow用户
提问于 2012-09-25 07:06:10
回答 2查看 13.2K关注 0票数 12

PowerShell ScriptBlock不是lexical closure,因为它不会关闭其声明环境中引用的变量。相反,它似乎利用了动态作用域和自由变量,这些变量在运行时绑定在lambda表达式中。

代码语言:javascript
复制
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的分类?

EN

回答 2

Stack Overflow用户

发布于 2012-09-26 01:44:13

根据the docs,scriptblock是“预编译的脚本文本块”。因此,默认情况下,您只是一个预先解析的脚本块,不多也不少。执行它会创建一个子作用域,但除此之外,它就像是粘贴了内联代码一样。因此,最合适的术语就是“只读源代码”。

在动态生成的模块上调用GetNewClosure螺栓,该模块在调用GetNewClosure时基本上携带调用者作用域中所有变量的快照。它不是真正的闭包,只是变量的快照副本。scriptblock本身仍然只是源代码,在调用它之前,变量绑定不会发生。您可以根据需要在附加的模块中添加/删除/编辑变量。

代码语言:javascript
复制
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
票数 8
EN

Stack Overflow用户

发布于 2015-11-07 18:41:03

PowerShell ScriptBlock等同于first-classanonymous function。我所看到的大多数混淆不是关于ScriptBlocks,而是关于function关键字。

  • PowerShell不支持function ,但是 function 关键字支持function

示例

功能:

代码语言:javascript
复制
PS> function Hello {
>>      param ([string] $thing)
>>      
>>      return ("Hello " + $thing)
>>  }

PS> Hello "World"
"Hello World"

ScriptBlock:

代码语言:javascript
复制
PS> $HelloSB = {
>>      param ([string] $thing)
>>      
>>      return ("Hello " + $thing)
>>  }

PS> & $HelloSB "World"
"Hello World"

PS> $HelloRef = $HelloSB
PS> & $HelloRef "Universe"
"Hello Universe"

代码语言:javascript
复制
PS> $Greeter = {
>>      param ([string] $Greeting)
>>      
>>      return ( {
>>          param ([string] $thing)
>>          
>>          return ($Greeting + " " + $thing)
>>      }.GetNewClosure() )
>>  }

PS> $Ahoy = (& $Greeter "Ahoy")
PS> & $Ahoy "World"
"Ahoy World"

PS> $Hola = (& $Greeter "Hola")
PS> & $Hola "Mundo"
"Hola Mundo"

尽管您可以使用"Set-Item“cmdlet绕过function关键字的限制:

代码语言:javascript
复制
PS> function Greeter = { ... }  # ✕ Error
PS> function Greeter { ... }.GetNewClosure()  # ✕ Error

PS> Set-Item -Path "Function:Greeter" -Value $Greeter  # (defined above)  ✓ OK
PS> $Hola = Greeter "Hola"
PS> & $Hola "Mundo"
"Hola Mundo"

"Set-Item“cmdlet的Value参数可以是任何ScriptBlock,甚至可以是另一个函数返回的值。(例如,"Greeter“函数返回一个闭包,如上所示。)

代码语言:javascript
复制
PS> Set-Item -Path "Function:Aloha" -Value (Greeter "Aloha")
PS> Aloha "World"
"Aloha World"

另外两个要点:

词法闭包在其源代码环境中是封闭的,而动态闭包是基于调用GetNewClosure()时存在的活动/动态环境而关闭的。( scripting language.)

  • PowerShell可能有"functions“和"return”语句,但实际上它的输入/输出是基于流和管道的。使用"Write-Output“或"write”cmdlet从ScriptBlock中写出的任何内容都将返回。
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12574146

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档