openlang

Функция должна вернуть путь, а возвращает массив

На этот раз пишу функцию на PowerShell с нуля, а не разбираю чужую, и она ведёт себя так, что объяснить не получается. Она должна вернуть один путь. Возвращает массив.

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[]

Когда в папке три книги, в $path оказывается четыре значения. Последнее - нужный путь. Первые три - 0, 1 и 2 (похоже на счётчик, которого в коде нет, и на него пришлось долго смотреть). Откуда эти числа и как обычно не дают вспомогательному списку утечь в результат?

Переведено с английскогоПоказать оригинал

Разговор продолжается 4

Следуя доводам
  1. Ссылка на ответ

    Любое голое выражение уходит в вывод, так что пиши явно. return (Join-Path $PWD 'report.xlsx') - и результатом станет это значение, а случайный вывод перед ним отбросится.

    Переведено с английскогоПоказать оригинал
  2. Ссылка на ответ

    Увы, нет, и на этом все хоть раз спотыкаются. return в PowerShell просто выводит своё значение и выходит из функции. Всё, что уже ушло в вывод, там и остаётся. Утекает ArrayList.Add - он возвращает индекс нового элемента, а возвращаемое значение, которое никто не забрал, становится выводом, как и всё остальное. Отсюда и 0, 1, 2.

    Индекс нужно выбросить прямо в месте вызова. Подойдёт любой из вариантов.

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

    (В справке about_Return есть почти такой же пример, там строка "Please wait" попадает в переменную вместе с результатом.) return можно оставить ради читаемости, просто он ничего не убирает.

    Переведено с английскогоПоказать оригинал
  3. Ссылка на ответ

    Не согласен, что чинить надо в месте вызова. Три приведения в трёх циклах, и в четвёртом кто-нибудь забудет. Ладно, для одной этой функции [void] - самая простая заплатка. Но настоящая проблема в типе списка. У [System.Collections.Generic.List[string]]::new() метод Add ничего не возвращает, так что утекать нечему с самого начала.

    Переведено с английскогоПоказать оригинал
  4. Ссылка на ответ

    Да, дело было в этом, спасибо обоим. После замены на обобщённый List[string] в $path снова одна строка (и Test-Path больше не выдаёт целый столбик ответов, на который до этого было проще не смотреть).

    Переведено с английскогоПоказать оригинал

Другие стороны того же вопроса

  1. Зависший тест лучше читать по дампу, а не по print

    Раньше при зависшем тесте рука сама тянулась расставить fmt.Println и запустить заново. Сейчас делаю иначе. Ставлю короткий т…

    Ответы 9go
  2. Мой init поменял fill-column ровно в одном буфере

    (setq fill-column 72) годами лежал у меня в init, и только сейчас выяснилось, что M-q в свежем буфере по-прежнему переносит н…

    Ответы 8emacs-lisp
  3. SilentlyContinue как On Error Resume Next с другим написанием

    После унаследованных рабочих книг дошло дело до унаследованных скриптов PowerShell, и там нашёлся старый знакомый в новом пал…

    Ответы 0powershell