#enums #metaprogramming #raku
#перечисления #метапрограммирование #раку
Вопрос:
В Raku HOWs должен предоставлять список архетипов с помощью archetypes
метода, который используется для определения того, какие более широкие возможности типов реализует тип, например параметричность или компоноваемость. Я заметил, что Metamodel::EnumHOW
(КАК используется с перечислениями) имеет augmentable
архетип, который присваивается типам, которые могут быть расширены после композиции с augment
ключевым словом, когда MONKEY-TYPING
включена прагма.
Мое первое предположение о том, почему перечисления можно было бы дополнять, заключалось бы в том, чтобы разрешить добавление значений перечислений, поэтому я попытался написать это:
use v6;
use MONKEY-TYPING;
enum Foo <foo bar baz>;
augment enum Foo <qux>;
say qux;
Но это бросает:
bastille% raku test.raku
===SORRY!=== Error while compiling /home/morfent/test.raku
Redeclaration of symbol 'Foo'.
at /home/morfent/test.raku:5
------> augment enum Foo⏏ <qux>;
Таким образом, они, вероятно, не предназначены для расширения таким образом.
Мое следующее предположение состояло в том, что они предназначены для расширения в отношении значений перечисления, а не самого типа перечисления. augment
Интересно, что не учитывает, что на самом деле имеет тип, когда вы указываете ему, какой тип вы дополняете, поэтому я попытался увеличить перечисление, как вы бы класс:
use v6;
use MONKEY-TYPING;
enum Foo <foo bar baz>;
augment class Foo {
proto method is-foo(::?CLASS:D: --> Bool:D) {*}
multi method is-foo(foo: --> True) { }
multi method is-foo(::?CLASS:D: --> False) { }
}
say foo.is-foo;
Что работает:
bastille% raku test.raku
True
Но это не похоже на то, как вы собираетесь дополнять перечисления для меня. Такое использование augment
довольно странно, и нет никаких указаний на то, что это должно быть возможно сделать из его документации. Как вы собираетесь увеличивать перечисления?
Вопросы и ответы
Foo.is-foo
похоже, что в нем нет никакого кода? Что это делает?
is-foo
довольно сложно использовать особенности подписей и параметров. Это зависит от следующего:
- Постоянные значения могут использоваться как типы в подписях. Сюда входят значения перечислений, которые обрабатываются во время компиляции.
- Можно настроить процедуру так, чтобы она всегда возвращала постоянное значение, задав тип возвращаемого значения для своей подписи.
- Переменные для любого заданного параметра в подписи являются необязательными.
- Когда после первого параметра ставится двоеточие, подобное этому, этот первый параметр является вызывающим параметром подписи. В случае методов это позволяет вам вводить
self
то, что вы хотите. ::?CLASS
является псевдонимом для класса, в области видимости которого объявлен метод. Это существует в телах классов и ролей, поэтому, несмотря на то, чтоFoo
на самом деле это не класс, это то, на что ссылается символ.:D
смайлик типа означает, что тип должен проверять тип только на своих собственных экземплярах, а не на объектах типа, которые проверяют тип, как это.
Поскольку foo
это более конкретный тип, чем ::?CLASS:D
(псевдоним для Foo:D
), при вызове этого метода на foo
будет выбрано foo
несколько и True
будет возвращено, но в любом другом случае будет выбрано ::?CLASS:D
несколько и False
будет возвращено.
Ответ №1:
В Java вы можете добавлять к перечислениям практически произвольные атрибуты и функции. Итак, я думаю, что дополнение так, как вы описываете, может иметь смысл. Например:
use MONKEY-TYPING;
enum Days(Monday => 1, Tuesday => 2, Wednesday => 3, Thursday => 4, Friday => 5, Saturday => 6, Sunday => 7);
augment class Days {
proto method is-weekend(::?CLASS:D: --> Bool:D) {*}
multi method is-weekend(Saturday: --> True) { }
multi method is-weekend(Sunday: --> True) {}
multi method is-weekend(::?CLASS:D: --> False) { }
proto method days-til-weekend(::?CLASS:D: --> Int:D) {*}
# there is probably a better way to express this, but
# hopefully the concept is clear
multi method days-til-weekend(Monday: --> 4) {}
...
}
say Monday.is-weekend;
say Wednesday.days-til-weekend;
say Saturday.is-weekend;