Consider this code:
procedure SplitAt(const _Input: string; _Position: integer; out _Head, _Tail: string); begin _Head := Copy(1, _Position-1); _Tail := Copy(_Position); end;
It’s meant to split a given string into two parts at the given position.
Nothing fancy, really, isn’t it?
Now, consider this call to the procedure above:
var s1: string; s2: string; begin s1 := 'hello world'; SplitAt(s1, 5, s1, s2); WriteLn('s1: "', s1, '"'); WriteLn('s2: "', s2, '"'); end;
Which output do you expect?
The output I got certainly wasn’t what I expected:
s1: "" s2: ""
I took me a while to understand what happened:
The compiler passes the parameters right to left, so the first parameter it passes is s2, then s1, then 5 and last s1 again as the input. Since the two rightmost parameters are *out* parameters it clears them before passing them, so s1 is already an empty string when it gets passed as input.
Not quite what I would have expected. It doesn’t help to remove the const modifier either.