Сочетание состояний и жетонов. Почему? - PullRequest
7 голосов
/ 06 января 2020

Это работает

sub test-string( $string )
{
    my token opening-brace { \( };
    my token closing-brace { \) };
    my token balanced-braces { 
        ( <opening-brace>+ ) <closing-brace> ** { $0.chars } 
    };

    so $string ~~ /^ <balanced-braces> $/;
}

Это

sub test-string( $string )
{
    state token opening-brace { \( };
    state token closing-brace { \) };
    state token balanced-braces { 
        ( <opening-brace>+ ) <closing-brace> ** { $0.chars } 
    };

    so $string ~~ /^ <balanced-braces> $/;
}    

умирает с

No such method 'opening-brace' for invocant of type 'Match'
  in regex balanced-braces at ch-2.p6 line 13
  in sub test-string at ch-2.p6 line 17
  in block <unit> at ch-2.p6 line 23

Я бы предпочел вторую версию, поскольку я считаю, что первая версия вполне неэффективно, когда приходится устанавливать token s каждый раз, когда вызывается функция. Поэтому, если бы это был реальный код, а не запись вызова, мне бы пришлось сделать токены (файлы) глобальными.

Почему это вообще происходит?

1 Ответ

6 голосов
/ 07 января 2020

TL; DR Мне нравится Take 0 . Есть обходной путь (см. Дубль 1 ), но я не думаю, что оно того стоит. Я не думаю, что это неэффективно с простой my (см. Взять 2 ). Я думаю, что использование state с регулярным выражением / методом должно быть отклонено во время компиляции (см. Берет 3 и 5 ) или оставлено как есть (см. Взять 4 ). Если вы не гений кодирования, желающий убедить, что Ракудо должен начать драматическое c усиление воздействия на продолжения (см. Дубль 5 ).

Почему это вообще происходит? (дубль 1)

«Это» не так, если вы напишите так:

sub test-string( $string )
{
    state &opening-brace = token { \( }
    state &closing-brace = token { \) }
    state &balanced-braces = token { 
        ( <&opening-brace>+ ) <&closing-brace> ** { $0.chars } 
    }

    so $string ~~ /^ <&balanced-braces> $/;
}   

(Необходимость & в вызовах регулярных выражений меня немного удивляет. 1 )

Почему это вообще происходит? (дубль 2)

Почему что происходит?

Я считаю, что первая версия довольно неэффективна, когда она должна устанавливать токены каждый раз, когда функция называется.

Что вы подразумеваете под «верьте», «совершенно неэффективно» и «настраивайте токены»? Я бы ожидал кода регулярного выражения, который будет скомпилирован только один раз (я был бы шокирован, если бы он был скомпилирован каждый раз), но не профилировал бы для проверки.

Что приводит меня к серии вопросов:

Является ли ваша забота исключительно временем, затрачиваемым на воссоздание 3 записей lexpad (&opening-parens et c; в более общем смысле, количество регулярных выражений) при каждом вызове функции test-string?

Действительно ли вы профилировали выполнение своего исходного кода и видели существенную проблему?

Вы действительно измерили это и обнаружили, что оно составляет часть ваших "критических 3%" в реальный проект?

Почему это вообще происходит? (принять 3)

Декларатор state делает разумные вещи с sub s - он выдает ошибку во время компиляции:

state sub foo {}    # Compile time error: "Cannot use 'state' with sub declaration"
state my sub foo {} # Compile time error: "Type 'my' is not declared"

Но с методом (который что такое регулярное выражение под прикрытием) оно компилируется, но не делает ничего полезного:

state method foo {} # Compiles, but I failed to find a way to access `foo`
state regex bar {.}  # Same

Я заглянул в очередь проблем GH Ракудо и не смог найти проблему, обсуждающую что-то вроде последних двух строк кода выше ( которые по сути совпадают с вашим token делом). Возможно, люди этого не заметили или, по крайней мере, не чувствовали, что было бы полезно сообщить об ошибке?

Почему это вообще происходит? (возьмите 4)

Таким образом, вы бы опубликовали SO документацию, что state regex следует отклонить во время компиляции или сделать что-то полезное. И @ Scimon ++ документировал бы другой взгляд на вещи. И еще я.

Почему это вообще происходит? (возьмите 5)

<Your Compiler Code Goes Here>

Потому что Раку - наша MMORPG . Если вы предпочитаете, чтобы декларатор state делал что-то полезное при использовании с объявлением процедуры (предположительно, он должен либо вызывать ошибку во время компиляции, как это в настоящее время происходит с sub, либо выполнять какие-то необычные продолжения внутри ограничение «продолжений в области действия» , поверх которого строится Raku), то эта работа, вероятно, просто «смоп», учитывая, что компилятор Rakudo в основном написан на Raku. Кто-то преднамеренно сделал state на sub ошибку времени компиляции, и идея продолжения была бы поистине колоссальным проектом, поэтому я думаю, что в ближайшие несколько лет целесообразно сделать state для метода или правила также ошибка времени компиляции.

Или, возможно, еще более уместно, теперь это покрывается SO, с документированной альтернативой (грамматика) и обходным решением (дубль 1), пора переходить на следующий уровень ...

Сноски

1 См. мой ответ на Разница в ... области применения регулярных выражений . Поведение регулярных выражений, объявленных с помощью state, похоже, не следует прямому прочтению предположений о конструкции, которые я привел в этом ответе. И, по крайней мере, следующий фрагмент моего рассказа из этого ответа тоже неверен ...

"<bar> такой, как объяснено выше. Он преимущественно разрешает лексическую (my / our) процедуру с ранним ограничением с именем &bar.

... потому что в коде дубля 1 этого ответа вызовы регулярного выражения имеют иметь префикс & для работы. Может быть, это просто случайность, когда они вообще работают.

...