Powershell, эквивалентный F # Seq.forall - PullRequest
4 голосов
/ 19 января 2010

Я написал это (что работает):

function ForAll {
    BEGIN {
        $allTrue = $true
    }
    PROCESS {
        if ($_ -lt 1) { $allTrue = $false }  
    }
    END {
        $allTrue
    }
}

$aList = (0..4)
$bList = (1..4)

$aList | ForAll # returns false
$bList | ForAll # returns true

Но я хочу заменить ($ _ -lt 1) на функцию с именем что-то вроде предиката $, которую я передаю в функцию ForAll. Я не могу заставить это работать. Есть идеи?

Ответы [ 3 ]

3 голосов
/ 19 января 2010

Если вы используете PowerShell 2.0, вы можете использовать param с блоком скриптов для объявления параметров, например ::100100

function ForAll {
    param(
        [Parameter(Position=0,Mandatory=$true)]
        [scriptblock]
        $Expression,

        [Parameter(Position=1,Mandatory=$true,ValueFromPipeline=$true)]
        [psobject]
        $InputObject
    ) 

    Begin { $allTrue = $true } 

    Process { 
        foreach ($obj in $InputObject) {
            if (!(&$Expression $obj)) { $allTrue = $false }
        }
    } 

    End { $allTrue } 
} 

$aList = (0..4) 
$bList = (1..4) 

ForAll {param($val) $val -gt 0} (0..4) # returns false 

$aList | ForAll {param($val) $val -gt 0} # returns false 
$bList | ForAll {param($val) $val -gt 0} # returns true 
$aList | ForAll {param($val) $val -ge 0 -and $val -le 4} # returns true
3 голосов
/ 19 января 2010

Используйте [scriptblock], imho, это намного проще, чем использовать функции здесь. Вот почему были изобретены скриптовые блоки.

function ForAll([scriptblock]$predicate) {

    BEGIN {
        $allTrue = $true
    }
    PROCESS {
        if (!(& $predicate $_)) { $allTrue = $false }  
    }
    END {
        $allTrue
    }
}

$aList = (0..4)
$bList = (1..4)

$aList | ForAll {$args[0] -le -10 } # returns false
$bList | ForAll {$args[0] -le 10 } # returns true

$ args [0] обозначает первый аргумент, переданный блоку сценария - в данном случае это $ _.

0 голосов
/ 30 октября 2012

Для эффективной обработки мы будем использовать фильтр вместо функции и "сломаемся", как только найдем паразитный элемент. Это также останавливает весь процесс upstream:

filter ForAll([scriptblock] $predicate) {
    PROCESS {
        if ( @($_ | Where-Object $predicate).Length -eq 0 ) {
            $false;
            break;
        }
    }
    END {
        $true;
    }
}

Используйте это идиоматически:

(0..4) | ForAll { $_ -gt 0 }     # returns false
(1..4) | ForAll { $_ -gt 0 }     # returns true
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...