Search code examples
delphioptimizationdelphi-7

How to cache function Boolean result


I have this function:

var
  _WordApplicationExistsCache: Integer = -1; // Cache result

function WordApplicationExists: Boolean;
var
  WordObj: OleVariant;
begin
  if (_WordApplicationExistsCache = -1) then
  begin
    Result := False;
    try
      try
        WordObj := CreateOleObject('Word.Application');
        WordObj.Visible := False;
        WordObj.Quit;
        WordObj := Unassigned;
        Result := True;
      except
        // error
      end;
    finally
      _WordApplicationExistsCache := Ord(Result); // 0;1
    end;
  end
  else
  begin
    Result := Boolean(_WordApplicationExistsCache);
  end;
end;

I'm trying to call this function only once in the Application lifetime. I might not call this function at all.

Is this the correct pattern? Can this be done better?

EDIT: Another way I can think of, in this case is to use 2 variables:

var
  _WordApplicationExistsInitialized: Boolean = False; // Cache result
  _WordApplicationExistsCacheResult: Boolean; // Undefined ?

function WordApplicationExists: Boolean;
var
  WordObj: OleVariant;
begin
  if not _WordApplicationExistsInitialized then
  begin
    _WordApplicationExistsInitialized := True;
    Result := False;
    try
      try
        WordObj := CreateOleObject('Word.Application');
        WordObj.Visible := False;
        WordObj.Quit;
        WordObj := Unassigned;
        Result := True;
      except
        // error
      end;
    finally
      _WordApplicationExistsCacheResult := Result;
    end;
  end
  else
  begin
    Result := _WordApplicationExistsCacheResult;
  end;
end;

What bugs me a bit about the first version is the type casting Boolean<->Integer. If Boolean could be initialized to nil it would have been perfect (I think).


Solution

  • Use a TriState type for the cached result.

    type
      TTriState = ( tsUnknown, tsFalse, tsTrue );
    
    var
      _WordApplicationExists : TTriState = tsUnknown;
    
    function WordApplicationExists : Boolean;
    var
      WordObj: OleVariant;
    begin
      if _WordApplicationExists = tsUnknown 
      then
        try
          WordObj := CreateOleObject('Word.Application');
          WordObj.Visible := False;
          WordObj.Quit;
          WordObj := Unassigned;
          _WordApplicationExists := tsTrue;
        except
          _WordApplicationExists := tsFalse;
        end;
    
      Result := _WordApplicationExists = tsTrue;
    end;