Showing posts with label Functional. Show all posts
Showing posts with label Functional. Show all posts

Tuesday, January 4, 2011

Solved: Powershell fails as a functional language if commands are in modules.

 

the issue comes down to the scope that the scriptblock being passed into the function gets bound. In the original example the scriptblock was being bound to the callers scope which can not access anything in the module except what was imported into the scope. The fix turns out to be explicitly binding the scriptblock to the modules scope. See the fixed example below. Thanks go out to @Oisin for the fix.

New-Module -Name 'Testing' -ScriptBlock {
function TestOuter{
param(
[
string]$Name,
[
scriptblock]$TestScript
)
function TestInner{
param(
[
int]$Count
)
Write-Host $Count
}
Write-Host $Name
$Mod = Get-Module Testing
& ( $Mod.NewBoundScriptBlock($TestScript) )
}
}
| Import-Module -Force -Global
TestOuter -Name "Paul" -TestScript { TestInner -Count 10 }
Remove-Module Testing -Force

Powershell fails as a functional language if commands are in modules.

I have some functions that contain functions. When I put the Functions in a .ps1 file and Dot Source directly the behave great but if those functions get imported in a module they fail to find the inner function with a CommandNotFound error. It does not matter if the functions are directly in a .psm1 file or if they are dot sourced by the .psm1 file they still fail to find the inner functions. Here are some code examples. Why is this? You can copy the below code into Powershell Console or ISE and run to see the errors.

function TestOuter{
param(
[
string]$Name,
[
scriptblock]$TestScript
)
function TestInner{
param(
[
int]$Count
)
Write-Host $Count
}
Write-Host $Name
& $TestScript
}
TestOuter -Name "Paul" -TestScript { TestInner -Count 10 }


New-Module -Name 'Testing' -ScriptBlock {
function TestOuter{
param(
[
string]$Name,
[
scriptblock]$TestScript
)
function TestInner{
param(
[
int]$Count
)
Write-Host $Count
}
Write-Host $Name
& $TestScript
}
}
| Import-Module -Force -Global
TestOuter -Name "Paul" -TestScript { TestInner -Count 10 }