Это мой перевод анонса так называемых generic routines. Оригинальный текст письма доступен здесь. Слова «generic routine» я перевожу напрямую как «обобщённая подпрограмма», т.к. пока ещё не знаю какой русский термин приживётся в паскаль-сообществе (возможны ещё варианты функция-дженерик, параметризованная функция или просто дженерик)
Всем привет!
Я рад наконец-то объявить о добавлении обобщённых функций, процедур и методов (вместе назваемых «подпрограммами») во Free Pascal, позволяющих писать типобезопасный код, который можно переиспользовать для многих типов.
Синтаксис:
Синтаксис объявления обобщённых подпрограмм схож с синтаксисом объявления обычнох подпрограмм, и тоже поддерживает классовые методы:
generic [class] (procedure|function) IDENTIFIER<TYPEARGLIST>[(PARAMETERLIST)][: RESULTTYPE]; MODIFIERS;
TYPEARGLIST пишется по тем же правилам, что и соответствующий список в обобщённых типах. Типы-параметры, объявленные в TYPEARGLIST, могут быть использованы в PARAMETERLIST, в RESULTTYPE и, конечно же, в теле подпрограммы.
Обобщённые подпрограммы могут быть перегружены и по TYPEARGLIST, и по PARAMETERLIST.
Для вызова обобщённой подпрограммы используется следующий синтаксис:
specialize IDENTIFIER<TYPELIST>[(PARAMETERS)]
TYPELIST пишется по тем же правилам, что и при специализации обобщённых типов. Если подпрограмма вызывается не из глобального пространства имён, а из типа, переменной, или через имя модуля, то нужно поместить соответствующее выражение перед словом «specialize»:
TYPENAME.specialize IDENTIFIER<TYPELIST>[(PARAMETERS)] VARIABLE.specialize IDENTIFIER<TYPELIST>[(PARAMETERS)] UNITNAME.specialize IDENTIFIER<TYPELIST>[(PARAMETERS)]
Вызовы обобщённых подпрограмм считаются обычным выражением, поэтому они могут быть использованы так:
=== начало примера === {$mode objfpc} generic function Add<T>(aLeft, aRight: T): T; begin Result := aLeft + aRight; end; begin Writeln(specialize Add<String>('Generic ', 'routines') + specialize Add<String>(' with ', 'Free Pascal')); end. === конец примера ===
Совместимость с Delphi:
Конечно, эта возможность также реализована в режиме совместимости с Delphi. Синтаксис объявления обобщённых функций в этом случае будет выглядеть как-то так:
[class] (procedure|function) IDENTIFIER<TYPELIST>[(PARAMETERLIST)][: RETURNTYPE]; MODIFIERS;
Т.е. всего лишь опущено слово «generic». Аналогично и при вызове:
IDENTIFIER<TYPELIST>[(PARAMETERS)]
Из-за того, что нет ключевого слова «specialize», указывающего на специализацию, сложные выражения пока что не работают в Delphi режиме. Поэтому запись результата вызова функции работает хорошо, но с чем-то более сложным вы можете столкнуться с ошибкой компиляции.
Пожалуйста, обратите внимание, что в отличие от Delphi, мы поддерживаем глобальные обобщённые функции/процедуры даже в Delphi режиме.
Ограничения/Планы:
Разработка фичи ещё не окончена, что-то ещё требует серьёзных доработок, а какие-то части ещё совсем не работают. Вот список подобных моментов:
- поддержка сложных выражений в Delphi режиме (относится также и к специализации типов)
- поддержка указателей на обобщённые подпрограммы (сейчас это приведёт к ошибке компиляции в лучшем случае, и внутренней ошибке или исключению в худшем)
- поддержка возвращаемого значения в режимах без поддержки слова «Result»
- поддержка вложенных обобщённых функций, особенно важен случай обобщённых методов внутри обобщённых классов
Поэтому прошу вас тестировать и сообщать о любых багах в трекер. Вопросы могут быть также заданы здесь в рассылке (и нет, эта фича не будет добавлена в FPC 3.0.0).
С уважением,
Свен
Читать дальше......