Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Существует ли в компиляторе реальная функция Ifthen, оценивающая результат только при необходимости?

Delphi , Синтаксис , Синтаксис

Реализация условного оператора IfThen в Object Pascal: проблемы и решения

В Object Pascal разработчики часто сталкиваются с необходимостью использовать условные операторы, возвращающие значения. В этой статье мы рассмотрим особенности реализации функции IfThen, её ограничения и альтернативные решения.

Проблема с стандартной функцией IfThen

Стандартная функция IfThen, доступная в модулях StrUtils и SysUtils, имеет существенное ограничение: она вычисляет оба возможных значения до проверки условия. Рассмотрим пример:

function ComplexCalculation1: String;
begin
  // Длительные вычисления
  Result := 'Результат 1';
end;

function ComplexCalculation2: String;
begin
  // Длительные вычисления
  Result := 'Результат 2';
end;

// Оба вычисления выполнятся, даже если нужно только одно
Result := IfThen(Condition, ComplexCalculation1, ComplexCalculation2);

Это приводит к неоптимальной работе кода, так как выполняются ненужные вычисления.

Решение с использованием generics в современных версиях FPC

Начиная с версии 3.2.0, Free Pascal поддерживает generic-версию IfThen:

{$mode delphi}
uses SysUtils;

var
  a: Integer = 100;
  b: Integer = 200;
begin
  // Использование generic-версии IfThen
  Writeln(IfThen<Integer>(True, a, b));
  Writeln(IfThen<Integer>(False, a, b));
end.

В версии 3.3.1+ с включённым режимом implicitfunctionspecialization можно использовать ещё более компактный синтаксис:

{$mode delphi}
{$modeswitch implicitfunctionspecialization}
uses SysUtils;

begin
  Writeln(IfThen(True, 'Истина', 'Ложь'));
  Writeln(IfThen(False, 'Истина', 'Ложь'));
end.

Альтернативные решения

1. Использование анонимных функций

function LazyIfThen<T>(Condition: Boolean; 
  TrueFunc, FalseFunc: TFunc<T>): T;
begin
  if Condition then
    Result := TrueFunc()
  else
    Result := FalseFunc();
end;

// Пример использования:
Result := LazyIfThen<String>(
  Condition,
  function: String begin Result := ComplexCalculation1 end,
  function: String begin Result := ComplexCalculation2 end
);

2. Расширенная версия для Object Pascal

function IfThenEx<T>(Condition: Boolean; 
  const TrueValue: T; FalseFunc: TFunc<T>): T; overload;
begin
  if Condition then
    Result := TrueValue
  else
    Result := FalseFunc();
end;

function IfThenEx<T>(Condition: Boolean; 
  TrueFunc: TFunc<T>; const FalseValue: T): T; overload;
begin
  if Condition then
    Result := TrueFunc()
  else
    Result := FalseValue;
end;

function IfThenEx<T>(Condition: Boolean; 
  TrueFunc, FalseFunc: TFunc<T>): T; overload;
begin
  if Condition then
    Result := TrueFunc()
  else
    Result := FalseFunc();
end;

Практический пример с TCheckListBox

Рассмотрим исправленную версию кода из исходного вопроса:

// Оригинальная проблема:
// checkList.Checked[1] := ifThenStr(...); // Неправильно: Checked - Boolean

// Правильное решение:
checkList.Checked[1] := (checkList.Items[1] = foo('All Header: ON'));

// Если нужна инверсия:
checkList.Checked[1] := not (checkList.Items[1] = foo('All Header: ON'));

// Или с использованием IfThen для Boolean:
checkList.Checked[1] := IfThen(checkList.Items[1] = foo('All Header: ON'), False, True);

Будущее IfThen в Free Pascal

Как отметили участники обсуждения, в 2016 году предлагалось реализовать IfThen как встроенную функцию (intrinsic), что позволило бы избежать вычисления неиспользуемых веток. К сожалению, это предложение не было принято.

Однако с развитием возможностей generic-программирования в FPC, возможно, стоит пересмотреть это решение. На данный момент лучшим вариантом остаётся использование анонимных функций или ожидание реализации неявной специализации в будущих версиях компилятора.

Заключение

Хотя стандартная функция IfThen в Object Pascal имеет ограничения, существуют различные способы обойти их - от использования generic-версий до реализации собственных "ленивых" вариантов этой функции. Выбор конкретного решения зависит от версии компилятора и требований к производительности вашего кода.

Создано по материалам из источника по ссылке.

Реализация условного оператора IfThen в Object Pascal: проблемы и решения.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Синтаксис ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-05-21 08:25:58/0.0060629844665527/0