Случай (или переключатель) в цикле for или цикл for в случае (или переключателе)?

Может ли вообще быть известно, приведет ли размещение case внутри цикла for к плохой сборке. Меня интересует в основном Delphi, но это интересный вопрос программирования, как с точки зрения стиля, так и с точки зрения производительности.

Вот мой кодез!

  case ResultList.CompareType of
  TextCompareType:
    begin
      LastGoodIndex := -1;
      for I := 1 to ResultList.Count -1 do
      if (LastGoodIndex = -1) and (not ResultList[I].Indeterminate) then
        LastGoodIndex := I
      else if not ResultList[I].Indeterminate then
      begin
        if (StrComp(ResultList[LastGoodIndex].ResultAsText,
                     ResultList[I].ResultAsText) > 0)
            and (Result  FalseEval) then
          Result := TrueEval
        else
          Result := FalseEval;

        LastGoodIndex := I;
      end;
    end;
  end;
  NumericCompareType:
  begin
    //Same as above with a numeric comparison
  end;
  DateCompareType:
  begin
    //Same as above with a date comparison
  end;
  BooleanCompareType:
  begin
    //Same as above with a boolean comparison
  end;

в качестве альтернативы я мог бы написать

    begin
      LastGoodIndex := -1;
      for I := 1 to ResultList.Count -1 do
      if (LastGoodIndex = -1) and (not ResultList[I].Indeterminate) then
        LastGoodIndex := I
      else if not ResultList[I].Indeterminate then
      begin
      case ResultList.CompareType of
      TextCompareType:
      begin
         if (StrComp(ResultList[LastGoodIndex].ResultAsText,
                     ResultList[I].ResultAsText) > 0)
            and (Result  FalseEval) then
           Result := TrueEval
         else
           Result := FalseEval;
         LastGoodIndex := I;
      end;
      NumericCompareType:
      begin
       //Same as above with a numeric comparison
      end;
      DateCompareType:
      begin
       //Same as above with a date comparison
      end;
     BooleanCompareType:
     begin
       //Same as above with a boolean comparison
     end;

   end;
  end;
 end;

Мне не нравится второй способ, потому что я задаю вопрос, на который я знаю ответ в цикле for, и мне не нравится первый способ, потому что я повторяю код, который использую, чтобы выяснить, какие из моих объектов содержат достоверная информация.

Возможно, кто-то может предложить шаблон проектирования, который позволит обойти это все вместе.


person Community    schedule 28.10.2008    source источник
comment
В Perl6 вместо переключателя / case используется данное / when, отчасти для того, чтобы помочь программистам понять, что это не совсем то же самое. Perl6's given / when намного мощнее.   -  person Brad Gilbert    schedule 30.10.2008


Ответы (3)


Почему бы не использовать подклассы?

Это позволяет избежать использования оператора case.

TComparer = class 
protected
  function Compare(const AItem1, AItem2: TItem): Boolean; virtual; abstract;
public
  procedure DoCompare(ResultList: ...);
end;

TTextComparer = class (TComparer)
protected
  function Compare(const AItem1, AItem2: TItem): Boolean; override;
end;

procedure TComparer.DoCompare(ResultList: ...);
var
  LastGoodIndex, I : Integer;
begin 
  LastGoodIndex := -1;
  for I := 1 to ResultList.Count -1 do
  if (LastGoodIndex = -1) and (not ResultList[I].Indeterminate) then
    LastGoodIndex := I
  else if not ResultList[I].Indeterminate then begin
    if Compare(ResultList[LastGoodIndex], ResultList[I]) then
      Result := TrueEval
    else 
      Result := FalseEval;
  end;
end;

function TTextComparer.Compare(const AItem1, AItem2: TItem): Boolean; 
begin
  Result := StrComp(ResultList[LastGoodIndex].ResultAsText,
    ResultList[I].ResultAsText) > 0)    
end;
person Community    schedule 28.10.2008
comment
В этой программе я на самом деле немного (для меня), но она не идеальна, и здесь я хотел бы просто написать некоторый структурированный код. - person Peter Turner; 28.10.2008
comment
Хорошо, с Delphi это нормально ;-). - person Toon Krijthe; 28.10.2008
comment
Вау, думаю, я сделаю это. хороший момент, мне даже не стоило задавать этот вопрос. Я не собираюсь говорить, что это ответ, потому что это ответ на вопрос, почему бы мне не использовать оператор case. Но тем не менее спасибо. - person Peter Turner; 28.10.2008

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

Если вас это действительно беспокоит, проще всего скомпилировать программу и посмотреть, что она генерирует. Поиграйте с кодом и настройками оптимизации, пока он не станет таким, как вы хотите. (Или напишите сборку от руки.)

Общий совет - просто пишите максимально понятный код и не беспокойтесь о настройке производительности, если это действительно не нужно.

person Community    schedule 28.10.2008

Я подозреваю, что эффективнее использовать лямбду, замыкание или даже просто ссылку на функцию. Мой Паскаль полностью заржавел, поэтому мой пример - Perl:

my %type = (
            TextCompareType => sub { $_[0] lt $_[1] },
            NumericCompareType => sub { $_[0] < $_[1] },
            DateCompareType => sub { ... },
            BooleanCompareType => sub { ... },
           );

for (my $i = 1; $i <= $#list; ++$i)
{
    if ( $type{$ResultList{CompareType}}->($list[$i-1], $list[$i]) )
    {
        $result = 1; # ?
    }
}

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

Другое решение - создать объекты компаратора как подклассы базового класса компаратора, а затем вызвать функцию сравнения объекта, но вы упомянули попытку сохранить структурированность вместо объектно-ориентированного подхода.

person Tanktalus    schedule 28.10.2008
comment
Да, что-то подобное сработало бы в Delphi, но, вероятно, это столько же работы, сколько и создание объектно-ориентированного подхода. - person Peter Turner; 28.10.2008
comment
Это известно как таблица переходов или таблица переходов. Он получил свое название от ASM, когда на самом деле это был массив кодов операций jmp. en.wikipedia.org/wiki/Branch_table - person Brad Gilbert; 30.10.2008