Отладка в вызовы функций - PullRequest
0 голосов
/ 17 мая 2018

Я хочу знать, если в этом коде

sub might-sink {
    return [1,2,Failure.new("boo!"),"still here"];
}

might-sink;
say might-sink;

первый вызов might-sink в контексте приемника фактически вызывает List.sink,то есть ничего не делает.Я догадываюсь, что это так, но я не уверен, так ли это, или это просто не reified , так что сбой не возникает позже.Я пробовал варианты отладки здесь , но ни один из них не попадает в код, вызываемый из этого.Итак, два вопроса, разделенных, но связанных:

  1. Как я могу отладить эти функции с помощью отладчика Perl 6 или модуля?
  2. Как я могу узнать, является ли это List.sinkна самом деле вызывается или, вообще, если sink вызывается, когда объект находится в контексте приемника?

1 Ответ

0 голосов
/ 17 мая 2018

Даже если вы явно вызвали .sink для этого возвращаемого значения, Failure не взорвется:

sub might-sink {
    return [1,2,Failure.new("boo!"),"still here"];
}

might-sink.sink;
say "Did not explode";
# OUTPUT: Did not explode

Взрыв в вашем коде происходит во время воспроизведения .gist во время say вызова, который проходит через первые 100 элементов вашего Array и вызывает .gist на них. Когда он делает это на элементе Failure, он взрывает его.

Вы путаете погружение самого объекта списка и отдельных значений, которые он содержит. Вы правильно упомянули, что List.sink не работает, но Seq.sink потребляет сам себя, но он также не взорвется, потому что потоплен только Seq, а не отдельные его элементы: (+"a", 42).Seq.sink

Если вы хотите вызвать потенциальные Failure взрывы, вы можете:

1: use fatal. Это приведет к тому, что компилятор приведет к фатальным сбоям, что приведет к их детонации во многих местах, где передается Failures. Это лексическая прагма, и она также автоматически включается в try {} блоках.

use fatal;
sub might-sink {
    return [1,2,Failure.new("boo!"),"still here"];
}
might-sink;

# OUTPUT:
# boo!
#  in block <unit> at

2: Hyper over .self вызов метода. Он предоставляется Mu (поэтому наследуется всеми объектами) и просто возвращает self, так что это неоперация (кроме выполнения decont ). Однако, поскольку большинство методов, вызываемых на вооруженных Failure, вызывают их детонацию, вызов .self для них приведет к их взрыву.

sub might-sink {
    return [1,2,Failure.new("boo!"),"still here"];
}
might-sink».self;

# OUTPUT:
# boo!
#  in block <unit> at

Как мне отладить эти функции с помощью отладчика Perl 6 или модуля?

Не используйте отладчики самостоятельно, но perl6-debug-m должен поставляться с предустановленной вашей установкой Rakudo. Требуется установить модуль Debugger::UI::CommandLine. И вы просто используете это вместо perl6 для запуска вашей программы, и она должна предложить некоторые инструкции в командной строке о том, что она делает. На нем также есть сообщение в блоге и видео (для воспроизведения требуется Flash).

Существует также недавно выпущенный альфа-качество App::MoarVM::Debug, которое позволяет отлаживать программы даже удаленно. Его прелесть в том, что он позволяет создавать дампы объектов и перемещаться по ним во время работы программы, поэтому, если вы справитесь с ее интерфейсом, это может быть удобно.

Лично я отлаживаю, просто используя подпрограмму dd, чтобы выгрузить вещи в стратегических точках и посмотреть, содержит ли то, что я ожидаю, в них.

Как я могу узнать, действительно ли вызывается этот List.sink или, вообще, вызывается ли приемник, когда объект находится в контексте приемника?

Вы можете добавить роль, используя операторы does или but, которые предоставляют метод sink, который делает то, что вы можете наблюдать. Нравится напечатать что-нибудь:

sub foo {
    return [<a b c>] does role { 
        method sink { say "sink called" }
    }
}
foo
# OUTPUT: sink called

Более продвинутым методом будет дамп постоптимизации Дерево QAST и проверка наличия ожидаемых вызовов. Модуль CoreHackers::Q облегчает визуализацию выгруженного дерева QAST.

P.S .: по теме подразумеваемой утечки, стоит отметить R # 1571 , которая перечисляет несколько ошибок с ним и предлагает полностью переработать внутренние системы обработки утечки.


¹ - точнее, Seq.sink вызывает .sink-all на своем Iterator, который по умолчанию просто потребляет значения, но пользовательские итераторы могут переопределить этот метод, чтобы он тоже не выполнялся .

...