ekkis
ekkis

Reputation: 10226

How can I get out of the loop once and for all?

I have this file:

function t {
    "abcd" -split "" |%{ if ($_ -eq "b") { return; } write-host $_; }
}
$o = @{}
$o |add-member -name t -membertype scriptmethod -value {
    "abcd" -split "" |%{ if ($_ -eq "b") { return; } write-host $_; }
}

write-host '-function-'
t;
write-host '-method-'
$o.t();

and if I run it I'll get:

-function-
a
c
d
-method-
a
c
d

as expected. but if what I wanted was 'a', I could replace the return with break. if I do so in the function what I get is:

-function-
a

so the method never even gets called. if I replace it in the method, it won't compile (and complains about calling it). what is going on here?

and what's the proper way to exit the foreach-object loop once and for all?

Upvotes: 2

Views: 41

Answers (2)

Jaykul
Jaykul

Reputation: 15814

The simplest solution is to rewrite it as a foreach statement, instead of using the ForEach-Object command, which is particularly hard to stop:

$o | add-member -name t -membertype scriptmethod -value {
    foreach($e in "abcd" -split "") {
        if ($_ -eq "b") { break }
        write-host $_; 
    }
}

As a side note, the foreach(){} keyword/construct runs a lot faster than piping through ForEach-Object.

For the sake of completeness ...

To stop a pipeline, throw PipelineStoppedException

"abcd" -split "" | % {
    if($_ -eq "b") {
      throw [System.Management.Automation.PipelineStoppedException]::new() 
    }
    $_ 
}

Upvotes: 3

yelsayed
yelsayed

Reputation: 5532

You don't use break to stop the ForEach, you use return since it's executed as a lambda on each member of the object anyway.

Upvotes: 0

Related Questions