As Mason said, there's an ambiguity in the Delphi syntax. Where TFoo.Bar
is a method, it's not clear that FooValue.Bar
means to refer to the result of calling TFoo.Bar
, or a method pointer (or reference) TFoo.Bar
itself (with implied Self argument of FooValue).
In the comments of Mason's answer, Rob Kennedy seems to suggest that the compiler simply figure this out based on the types of everything involved. This isn't simple; the compiler already does a lot of work to figure out whether you mean to refer to a method pointer value or a method call. It actually parses expressions in a different way when the expected receiver is a method pointer (or reference, or function pointer) type. The effort is especially involved when overloads are brought into the picture: the compiler scans through every overload candidate and checks for method pointer types in every parameter position, and then parses arguments differently depending on whether or not that parameter position contains a function pointer in one of the overloads. Then, if an overload that expects a function pointer isn't matched, the compiler changes the parse tree from function pointer to method call. The overloading mechanism itself needs to figure out which to use when its doing value to parameter comparisons. It's pretty messy, and it would be great if we didn't make it messier.
A prefix-style operator like @
or Addr()
isn't much help in resolving this ambiguity, not least because functions may return function pointers, and so on; how many @
do you need to inhibit implicit (no ()
necessary) calling to grab the right value out? So when anonymous methods were introduced, a change in the expression parsing was made: I introduced the possibility of using ()
to force an invocation.
You can read more about it here:
http://blog.barrkel.com/2008/03/odd-corner-of-delphi-procedural.html
and here:
http://blog.barrkel.com/2008/03/procedurally-typed-expressions-redux.html