Работа с неверными файловыми дескрипторами (и, возможно, с другими недействительными объектами тоже) - PullRequest
0 голосов
/ 03 февраля 2019

Как указал Том Браудер в этой проблеме , динамическая переменная $*ARGFILES может содержать недопустимые дескрипторы файлов, если какой-либо из файлов, упомянутых в командной строке, отсутствует.

for $*ARGFILES.handles -> $fh {
    say $fh;
}

завершится с ошибкой и X::AdHoc с исключением (вероятно, это тоже нужно улучшить):

Failed to open file /home/jmerelo/Code/perl6/my-perl6-examples/args/no-file: No such file or directory

Проблема возникнет, как только неверный дескриптор файла будет использоваться для чего-либо.Будет ли способ проверить, действителен ли дескриптор файла перед тем, как возникнет исключение?

Ответы [ 2 ]

0 голосов
/ 03 февраля 2019

TL; DR Я думал, что у Лиз это было прибито, но похоже, что есть ошибка или, возможно, тьфу.

Ошибка?

Похоже, когда IO::CatHandle метод .handles класса достигает дескриптора, который должен по праву генерировать Failure (задерживая любое исключение), вместо этого он немедленно генерирует исключение (возможно, именно то, которое будет работать, если его просто отложить).или, может быть, что-то сломано).

Это кажется неправильным или очень неправильным.

Тьфу

См. обмен между Зоффиксом и Брэдом Гилбертом и ответом Зоффикса на вопрос Как мне обращаться с Perl 6 $ * ARGFILES, которые нельзя прочитать по строкам ()?

Также:

Потенциальный обходной путь в настоящее время является еще одной ошибкой?

Вобсуждение "Реализовать обработчик для неудачного открытия в IO::CatHandle" Zoffix ++ закрыл его с помощью этого кода в качестве решения:

.say for ($*ARGFILES but role {
    method next-handle {
        loop {try return self.IO::CatHandle::next-handle}
    }
})

I seТо, что tbrowder вновь открыл эту проблему как часть связанной проблемы, о которой этот SO говорит:

Если это сработает, это будет, по крайней мере, полезным примером для переменной $*ARGFILES в документации.

Но когда я запускаю его в 6.d (и вижу аналогичные результаты для 6.c) с допустимым вводом или без него, я получаю:

say not yet implemented

(похожеесли я .put или что-то в этом роде.

Это чокнутый и наводит на мысль, что что-то не в порядке с мужеством.

Я искал проблемы с rt и gh / rakudo для "еще не реализовано" ине найдено соответствующих совпадений.

Еще один обходной путь?

Zoffix явно задумал свой код как постоянное решение, а не просто как обходной путь.Но, к сожалению, на данный момент это, похоже, не работает вообще.

Лучшее, что я придумал до сих пор:

try {$*ARGFILES} andthen say $_    # $_ is a defined ArgFiles instance
                 orelse  say $!;   # $! is an error encountered inside the `try`

Возможно, это работает как черно-белоеэто либо все работает, либо ни один из них не делает решение.(Хотя я не уверен, что это даже так.)

О чем говорит док $*ARGFILES

$*ARGFILES говорит, что это пример

IO::ArgFiles, который документируется как класс, который

существует по причинам обратной совместимости и не предоставляет методов.

И

Вся функциональность унаследована от

IO::CatHandle с субтитрами

Использовать несколькоIO обрабатывает, как если бы они были одним

и doc'd как класс, который is

IO::Handle, который с субтитрами

Открытый файл или поток

и doc'd как класс, который не наследуется ни от какого другого класса (поэтому по умолчанию наследуется от Any) или выполняет какую-либо роль.

Итак, $*ARGFILES - это (в точности то же самое, что и) объект IO::CatHandle, который (расширенный набор функций) является объектом IO::Handle, а именно:

Класс IO::CatHandle предоставляет средства длявыберите IO::Handle, который легко собирает данные из нескольких IO::Handle и IO::Pipe источников.Все методы IO::Handle реализованы, и хотя попытка использовать методы записи вызовет (на данный момент) исключение, IO::CatHandle можно использовать везде, где может использоваться только для чтения IO::Handle.

Изучение код IO::CatHandle

(заполняется позже?)

0 голосов
/ 03 февраля 2019

Вы можете проверить, является ли что-то Failure, проверив на правдивость или определенность без броска Failure:

for $*ARGFILES.handles -> $fh {
    say $fh if $fh;  # check truthiness
    .say with $fh;   # check definedness + topicalization
}

Если вы все еще хотите бросить Exception что Failure охватывает, тогда вы можете просто .throw это.

...