随笔 - 89, 评论 - 163, 引用 - 33

导航

关于

标签

每月存档

最新留言

广告

 

[原文作者]:Jared Parsons

[原文链接]:Simulating Closures in PowerShell

 

    在之前的博文中我曾经提到过Power Shell缺少在脚本块中对闭包的支持.这对我正在研究的开发针对PowerShell的LINQ, 比如DSL, 是个很大的障碍。想象下下面的语句:

     $a = from it in $source where {$it -gt 5 }

    它大致相当于以下的C#代码

     var a = from it in source where it > 5;

    在C#中这段代码是能正常运行的,因为追根究底其中的WHERE语句“it > 5”被转化成了Lambda表达式。它要获取的变量在Lambda表达式中是通过闭包来实现的。为了在PowerShell中实现相似的功能,值$it在“where”句块执行的时候必须被转换。

    所幸PowerShell的灵活性出乎意料的好。当一个脚本块执行的时候,它会通过遍历各个不同的域并尝试转换所有的变量。第一被搜索的域是脚本块,然后是脚本块执行所在的本地代码块。使用new-variable,我们能生成和脚本块所寻求的变量名相同的变量。

PS) $sb = { write-host $it }
PS) & $sb
 
PS) new-variable "it" 42 -scope local
PS) & $sb
42

    成功了!现在我们唯一要做的就是通过生成一个函数Run-Scriptblock来概括这种行为。这个函数涉及到以下两点:

    1.需要执行的脚本块;

     2.一系列名字/值对。每一对都代表执行脚本块所必需的一个变量。

     代码:

#============================================================================
# Runs a script block.  The $list parameter must be a list of string, value
# combinations.  The script block will be executed with variables of the 
# specified name and value in scope
#============================================================================
function Run-Scriptblock() {
    param ( [scriptblock] $sb = $(throw "Need a script block"), 
            [object[]]$list= $(throw "Please specify the list of names and values") )
 
    for ( $i = 0; $i -lt $list.Length; $i = $i+2 ) {
        $name = [string]($list[$i])
        $value = $list[$i+1]
        new-variable -name $name -value $value -scope "local"
    }
 
    & $sb
}

    Example Usage:

PS) $sb = { write-host $it }
PS) run-scriptblock $sb "it",42
42
PS) $it
 

     现在我们已经有执行一个“where”语句的方法了。下次我们将讨论如何在PowerShell中定一个LINQ DSL的实际操作。

打印 | 张贴于 2009-02-20 14:26:04 | Tag:暂无标签

留言反馈

暂时没有留言纪录
博客主人设置本博客不允许匿名用户发表言论,请登录后再试

Powered by: Joycode.MVC引擎 0.5.2.0