Anonymous Method constraints

Anonymous Method constraints

Due to the occasional shooting of foot due to how capture works, I wish there was a way of optionally constraining references for an anonymous method, so that I could enforce local references only.


  TFilterMethod = constrained reference to function (const Item:T):Boolean;

  TInstanceList = class

    property function Filtered(Filter: TFilterMethod):TInstanceList;



  SomeRef: TQualifier;

  List: TInstanceList;

  Element: TThing;



  // compiles

  for Element in List.Filtered(function (Item: TThing)


      Result := Item.Qualifier in [This, That]);


  do begin


  // should not compile – but error on “reference outside method not allowed for constrained methods

  for Element in List.Filtered(function (Item: TThing)


      Result := (Item.Qualifier = SomeRef);


  do begin


30 thoughts on “Anonymous Method constraints

  1. Could you explain further please? Why would you want the second example to not compile – isn’t a reference it an item in a list perfectly valid? (Or is it something to do with the property Filtered being a property not function?  I’ve never seen property syntax like that before – it’s not an indexed property, it has normal braces like a method?)

  2. I think he means that the second example should fail because the anonymous method captures are variable (SomeRef). The first example dont need any variable capturing…

    But isnt that an advantage of anonymous method? Capturing variables from outside?

  3. David Millington My bad: Should be function, not property.

    Stefan Glienke – I could do that, but it is a lot less flexible, and it can take miniscule pieces of logic of it’s context.

    David Heffernan – Duh, Captain Obvious! That advice has a Microsoft help quality about it: Accurate, but useless.

    Fabian S. Biehn – Capturing is an advantage – but it can also be a pitfall.  In some cases – you capture only the initial value of something that should have changed later.

    It would be nice to be able to constrain the abstract method definition by design.

  4. “In some cases – you capture only the initial value of something that should have changed later.”

    Actually it is the opposite – variable capturing means you always get the most recent value of this variable. Capturing means by reference and not by value. If you don’t want that then write a function that returns the anonymous method or use the specification pattern (see Spring.Designpatterns.pas)

  5. Lars Fosdal I don’t think the advice is useless. I think it’s important to know your tools and understand the code that you write. Certainly when I write anonymous methods, I think very carefully about what, if anything, is being captured. Do you not?

    It seems to me that you are responding to being caught out by your own incomplete understanding of how variable capture works and think that a change to the language is the fix.

    Furthermore, your proposed fix would be the absolute worst way to tackle this. You’d condemn any users of that type to be unable to use variable capture. If a change were to be made, and I see no reason to make one, but if one were to be made you would make it at the point at which the anonymous method was defined. So you’d have the programmer state in the definition of the anonymous method that the method did not capture any variables. And then the compiler could verify that.

  6. Stefan Glienke “Actually it is the opposite – variable capturing means you always get the most recent value of this variable.”

    Capturing a mutable variable by reference is a hell… I’d rather wish to always capture by value, not by reference.

  7. Roman Yankovsky “I’d rather wish to always capture by value, not by reference.”

    That would actually cripple this feature. If you want capture value then make a local variable, assign the mutable variable to it and you are done (as you have to do with certain types like records).

  8. Stefan Glienke this feature came from functional languages where all variables are immutable by default. Capturing by value cannot cripple this feature 🙂

    Disclaimer: I know, that some times is accessible only by a reference. That’s why Emba didn’t have a choice.

  9. Stefan Glienke Slightly tricky to reproduce the C# code (the second example) in Delphi because Delphi can’t readily create local variables in the same way that C family languages do by declaring them inside a loop body.

  10. David Heffernan – It is not a “fix”, it is a constraint – such as setting a field to be strict private.  It gives me, as the class designer, the option to constrain the use and enforce a design.

    If you design a class that uses anon methods, it is all well and fine that you do the required thinking, but you can’t enforce this for those that will be using your designs.

    I really would like to have more granular control of the capture requirements – i.e. to, in the procedure in which the anon method is declared, discern the constraint between “simple” local variable captures and referenced object/property value or reference captures – but I can’t think of an easy way to introduce the constraint.  

    If it needs to be done where you implement the anon method – as you suggest – then the type declaration needs a way to say that the compiler must require a capture constraint declaration at the implementation.

  11. Lars Fosdal You are looking at it from a wrong perspective. A delegate type is an interface (even literally) or contract. If you are using variable capturing or not is an implementation detail of that anonymous method and should not be constrained by the interface.

  12. +Lars What Stefan just said is my point about where the constraint would be specified. The consumer of an anon method has no grounds to care about its implementation. Which is why you’ll never see the feature you asked for.

    What you actually looking for is a tool to help you find your mistakes.

  13. David Heffernan What I would like is a means to help those that use the code of others, avoid making such mistakes.  

    I’ve made the mistakes, and learned from them – but if you use code with Generics, without the experience – you won’t know the pitfalls until you spend time digging them out in the debugger.  

  14. Hints and warnings serve a similar purpose.

    Not initializing a variable is a typical novice mistake, right?  

    Changing the language is indeed drastic, and it may add clutter – but the challenge is not ephemeral.

  15. Asbjørn Heid It’s perhaps not the best of examples. The original thought was to prevent “bad captures” (i.e. value instead of value reference).  Stefan Glienke / David Heffernan had compelling arguments for why my suggestion was the wrong solution.

    The concept can have potential as a way to ensure that the anon method has no side effects – but, yeah – not for the original thought.

  16. Lars Fosdal Yeah ok. I could understand why the caller would consider it bad, but not Filtered.

    For what it’s worth, in C++[1] you can specify exactly which and how variables are captured. Of course only when you declare the lambda, whatever is using the lambda can’t, and shouldn’t care.

    The syntax is a bit fugly, but at least you get absolute control. Want to make sure no variables are capture? No problem. Want to auto-capture variables by value, except “foo” by reference? Sure thing.