Question

consider the following delphi pascal code:

var
  tc: TComponent
begin
{ do something to get tc }
repeat
  if(tc is TDBEdit)then begin
    if(check_something_about_edit(tc))then break;
    do_something_else_edit(tc);
    break;
  end else if(tc is TBMemo) then begin
    if(check_something_about_memo(tc))then break;
    do_something_else_memo(tc);
    break;
  end;
  raise exception.create('invalid component type');
until(true); {single iteration look required to use break }

I know there's probably some polymorphic stuff that I could do with TComponent, but that's not my question. I'm wondering if there's a way to get rid of the single iteration repeat-until statement. Without it, I can't use the break statement anywhere in the processing block, and I need that to stop processing at any time.

Was it helpful?

Solution

Pack it into a function and use exit to jump back. if there is more code to follow the repeat statement, use a local function/procedure, something like:

procedure ...
  procedure testsomething(tc: TComponent);
  begin 
    if(tc is TDBEdit)then begin
      if(check_something_about_edit(tc))then exit;
      do_something_else_edit(tc);
      exit;
    end else if(tc is TBMemo) then begin
      if(check_something_about_memo(tc))then exit;
      do_something_else_memo(tc);
      exit;
    end;
    raise exception.create('invalid component type');
  end;

var
  tc: TComponent;
begin
{ do something to get tc }
  try
    TestSomething(tc);
    { do something more }
  except
     ...
  end;
end;

OTHER TIPS

There is another easy way to go:

if(tc is TDBEdit)then begin
  if not (check_something_about_edit(tc)) then
    do_something_else_edit(tc);
end else if(tc is TBMemo) then begin
  if not (check_something_about_memo(tc)) then
    do_something_else_memo(tc);
end else
  raise exception.create('invalid component type');
end;

What you are actually doing is using break as a goto. Ralph's suggestion to use a function as a scope is a good one. But otherwise you might as well be honest and use a 'goto finished'. Losing the repeat will make it actually more readable.

Why do you want to use break rather than Exit? Break in Delphi is not the same as "break" in the curly brace languages.

var
  tc: TComponent
begin
  { do something to get tc }
  if (tc is TDBEdit) then 
  begin
    if not (check_something_about_edit(tc)) then 
      do_something_else_edit(tc);
    Exit;
  end;
  if (tc is TBMemo) then 
  begin
    if not (check_something_about_memo(tc)) then 
      do_something_else_memo(tc);
    Exit;
  end;
  raise exception.create('invalid component type');
end;

A point about layout. If you didn't try to reduce whitespace so much it mightn't take "another hour to make sure all my if-else's lined up correctly" as you said in an earlier comment.

If you have code that you want to execute after this, either use Ralph's suggestion of a local procedure, or wrap in a try..finally - the code in the finally will still be executed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top