Record helpers can do wonders for code clarity.

Record helpers can do wonders for code clarity.
// Never mind the silly example

TResult = (CompletedOK, PartiallyPerformed, NothingHappened, HorriblyWrong);

function DoSomething:TResult;
begin
Result := PartiallyPerformed;
end;

How do we determine failure vs success?

if not DoSomething = CompletedOK then ...?

What about Partially performed and nothing happened?

Enter the helper:

TResultHelper = record helper for TResult
function Failed:Boolean;
function Success:Boolean;
end;

function TResultHelper.Failed: Boolean;
begin
Result := (Self = HorriblyWrong);
end;

function TResultHelper.Success:Boolean;
begin
Result := not Failed;
end;

Now we can write
if DoSomething.Failed then ...

Note that you also can enter the murky waters of obfuscation through helpers, but at least the murkiness will be consistent :P

Comments

  1. That depends on the eye of the beholder ;)

    ReplyDelete
  2. As I said, never mind the silly example

    ReplyDelete
  3. In plain pascal, I will define in the same unit than TResult:
    const RESULT_FAILED = [HorriblyWrong];
    and write a clean
    if DoSomething in RESULT_FAILED then ...
    Sounds MUCH cleaner to me than using a record helper.

    ReplyDelete
  4. function TResultHelper.Failed: Boolean;
    begin
    Result := (Self in RESULT_FAILED);
    end;

    ReplyDelete
  5. or

    TResultSet = Set of TResult;

    const
    RESULT_FAILED = [HorriblyWrong];
    RESULT_SUCCESS = [CompletedOK, PartiallyPerformed, NothingHappened];

    type
    TResultHelper = record helper for TResult
    function Success(const SuccessStates:TResultSet = RESULT_SUCCESS):Boolean;
    function Failed(const FailStates: TResultSet = RESULT_FAILED):Boolean; //

    ...

    function TResultHelper.Success(const SuccessStates:TResultSet): Boolean;
    begin
    Result := (Self in SuccessStates);
    end;

    function TResultHelper.Failed(const FailStates: TResultSet): Boolean;
    begin
    Result := (Self in FailStates);
    end;

    to allow you to deviate from the defaults on need.

    ReplyDelete
  6. Why not create a record, with implicit conversion from the TResult, to give some methods? Could make the code even more circumvented...

    ReplyDelete
  7. type TNilHelper=record helper for nil ... end; if Something.Failed ...

    ReplyDelete
  8. Lars Fosdal Luddites? I not going back to GWBASIC. I will continue to happily run my Turbo Pascal in a Windows 98 command window thank you very much :p

    ReplyDelete
  9. GWBASIC? Luxury! We had to cut our own punchcards from old shoe boxes with a blunt pair of scissors and then punch holes in them with a rusty nail! And on Fridays...

    ReplyDelete

Post a Comment