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
// 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
Is that satire, or what?!
ReplyDeleteThat depends on the eye of the beholder ;)
ReplyDeleteOpposite of Failed is Succeeded
ReplyDeleteAs I said, never mind the silly example
ReplyDeleteIn plain pascal, I will define in the same unit than TResult:
ReplyDeleteconst RESULT_FAILED = [HorriblyWrong];
and write a clean
if DoSomething in RESULT_FAILED then ...
Sounds MUCH cleaner to me than using a record helper.
function TResultHelper.Failed: Boolean;
ReplyDeletebegin
Result := (Self in RESULT_FAILED);
end;
or
ReplyDeleteTResultSet = 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.
THorriblyWrongFrowny;
ReplyDeleteWhy not create a record, with implicit conversion from the TResult, to give some methods? Could make the code even more circumvented...
ReplyDeletetype TNilHelper=record helper for nil ... end; if Something.Failed ...
ReplyDeleteLuddites ;)
ReplyDeleteLars 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
ReplyDeleteGWBASIC? 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