openlang

My function returns an array when all I asked for was a path

Writing a PowerShell function from scratch for once (rather than squinting at someone else's), and it misbehaves in a way I can't explain. It's meant to hand back one path. It hands back an array.

function Get-ReportPath {
    $names = [System.Collections.ArrayList]::new()
    foreach ($f in Get-ChildItem -Filter *.xlsx) {
        $names.Add($f.Name)
    }
    Write-Verbose "found $($names.Count) workbooks"
    Join-Path $PWD 'report.xlsx'
}

$path = Get-ReportPath
$path.GetType().Name   # Object[]

With three workbooks in the folder, $path holds four things. The last is the path I wanted. The first three are 0, 1 and 2 (which looked like a counter I never wrote, and I stared at it for a good while). Where do those numbers come from, and what's the usual way to stop a helper list leaking into the result?

后续讨论 4

顺着彼此的依据读下去
  1. 固定链接

    Every bare expression goes to output, so be explicit. Write return (Join-Path $PWD 'report.xlsx') and that becomes the result, the stray output before it gets dropped.

  2. 固定链接

    Sadly no, and this one surprises everybody once. return in PowerShell just emits its value and leaves the function. Anything already written to the output stays there. The leak is ArrayList.Add, which returns the index of the new item, and a return value nobody captures is output like anything else. That's where the 0, 1, 2 come from.

    Throw the index away at the call. Any of these works.

    [void]$names.Add($f.Name)
    $null = $names.Add($f.Name)
    $names.Add($f.Name) | Out-Null

    (The about_Return help page has nearly the same example, with a "Please wait" string that ends up in the variable next to the result.) Keeping return for readability is fine, it just doesn't clean anything up.

  3. 固定链接

    Disagree that the call site is where to fix it. Three casts in three loops and somebody forgets the fourth. Fair that [void] is the quickest patch for this one function. But the list type is the real problem, and [System.Collections.Generic.List[string]]::new() has an Add that returns nothing, so there's no index to leak in the first place.

同一个问题的其他角度

  1. My init set fill-column for exactly one buffer

    Had (setq fill-column 72) in my init for ages and only just noticed that M-q in a fresh buffer still wraps at 70. (In *scratc…

    回复 8最近活动 emacs-lisp
  2. Upgradeable means the storage layout is forever

    People hear proxy pattern and think the immutability problem went away. It moved. The proxy holds the state and forwards call…

    回复 3最近活动 solidity
  3. SilentlyContinue is On Error Resume Next with better spelling

    Went from inherited workbooks to inherited PowerShell scripts and found my old friend in a new coat. -ErrorAction SilentlyCon…

    回复 0最近活动 powershell