A simple way of avoiding the implicit variable is to use the one variable you have, Result:
function Apples(nb : Integer) : String; begin Result := IntToStr(nb); Result := Result + ' apple(s)'; end;
While that does look stupid, if you look behind the code at asm, it is much simpler now:;
Project65.dpr.31: begin 005D82B0 53 push ebx 005D82B1 56 push esi 005D82B2 8BDA mov ebx,edx 005D82B4 8BF0 mov esi,eax Project65.dpr.32: Result := IntToStr(nb); 005D82B6 8BD3 mov edx,ebx 005D82B8 8BC6 mov eax,esi 005D82BA E8D15FE4FF call IntToStr Project65.dpr.33: Result := Result + ' apple(s)'; 005D82BF 8BC3 mov eax,ebx 005D82C1 BADC825D00 mov edx,$005d82dc 005D82C6 E819F9E2FF call @UStrCat Project65.dpr.34: end; 005D82CB 5E pop esi 005D82CC 5B pop ebx
And it executes about twice faster as well, and as a bonus, it will be even faster in multi-threaded applications due to reduced pressure on the memory-manager.
And if you inline the functions, the second one will still keep its advantage, as inlining will only move the implicit variable and frame to the function where the inlining takes place.
Not so stupid after all
Note that this “optimization” use of an explicit local variable can be leveraged with all reference-counted types (dynamic arrays, interfaces, objects in ARC compilers…), and it can also help with debugging, as it makes it very simple to inspect the intermediate returned values.
So sometimes, it can pay twice to write a little more code: it’ll be easier to debug/maintain, and it will run faster.
That was for a single concatenation. What happens if you have many?
Check the followup article: Efficient String Building in Delphi.