Where-Object is going to let you cut down on the number of lines of code compared to foreach() and for(), and in my opinion will make the code more readable.
$vms | Where-Object -Property Name -match "sql"
vs
$vmOutput = @()
for($i = 0; $i -lt $vms.count; $i++) {
if($i.Name -match "sql"){
$vmOutput += $i
}
}vs
$vmOutput = @()
foreach($vm in $vms){
if($vm.Name -match "sql"){
$vmOutput += $vm
}
}For the Foreach-Object point, that cmdlet also give you the option to use begin{}, process{} and end{} blocks. So that you can with begin{} do something before any of your objects are processed, process your objects with process{}, and after all objects have been process do something with end{}. This logic with for and foreach would have to come before and after the for and foreach statements.
I don't see this as a "PowerShell being clever" but more as a PowerShell is a shell that uses pipelines like nix shells but it has everything as an object unlike nix shells. So you get to take advantage of that.