Различия между .Bool, .so,? так что - PullRequest
10 голосов
/ 23 июня 2019

Я пытаюсь выяснить, в чем различия между вышеупомянутыми процедурами, и если такие выражения, как

say $y.Bool;
say $y.so;
say ? $y;
say so $y;

, приведут к другому результату.

Пока единственное отличие, которое для меня очевидно, состоит в том, что ? имеет более высокий приоритет, чем so..Bool и .so кажутся полностью синонимами.Это правильно и (практически говоря) полная история?

1 Ответ

8 голосов
/ 23 июня 2019

Что я сделал, чтобы ответить на ваш вопрос, так это написать исходный код компилятора Rakudo.

Как вы заметили, один из аспектов, который отличается между префиксами, - это анализ различий. Варианты имеют разные приоритеты, и so является буквенным, тогда как ? является пунктуацией. Чтобы увидеть точный код, управляющий этим синтаксическим анализом, просмотрите Rakudo Grammar.nqp и поищите на этой странице prefix:sym<...>, где ... равно ?, so и т. Д. Это выглядит как троичный (... ?? ... !! ...) превращается в if. Я вижу, что ни один из этих токенов не имеет соответственно названных Actions.pm6 методов. Можно предположить, что генерация кода, которая им соответствует, обрабатывается этой частью method EXPR. (Кто-нибудь знает или хочет следовать инструкциям в этом блоге , чтобы узнать?)

Определения в Bool.pm6 и Mu.pm6 показывают, что:

  • В Mu.pm6 метод .Bool возвращает False для неопределенного объекта и .defined в противном случае. В свою очередь .defined возвращает False для неопределенного объекта и True в противном случае. Так что это по умолчанию.

  • .defined задокументировано как переопределенный в двух встроенных классах и .Bool в 19 .

  • so, .so и ? все вызывают один и тот же код, который присваивается Bool / .Bool. Теоретически классы / модули могут переопределять их вместо или даже как переопределение .Bool или .defined, но я не могу понять, почему кто-то когда-либо делал бы это либо во встроенных классах / модулях, либо в пользовательских.

  • not и ! одинаковы (за исключением того, что используется ! с :exists dies ) и оба превращаются в вызовы на nqp::hllbool(nqp::not_i(nqp::istrue(...))). Я предполагаю, что основная причина, по которой они не проходят обычный маршрут .Bool, заключается в том, чтобы избежать обработки пометок Failure s .

  • В Mu.pm6 определены методы .so и .not. Они просто звонят .Bool.

  • Существуют логические побитовые операторы, которые включают ?. Они далеки от вашего вопроса, но их код включен в ссылки выше.

...