ноября 26, 2015

Анонс фичи: Обобщённые функции, процедуры и методы

Это мой перевод анонса так называемых 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).

С уважением,
Свен


Комментариев нет:

Отправить комментарий

Постоянные читатели

Обо мне

Моя фотография
Мой e-mail: vitek_03(at)mail(dot)ru