Let me start by saying that I have an actual use case for this in the measurement framework and I'm not just messing around. :slight_smile:

function add_x(x: count): function(a: count): count
  local tmp = function(a: count): count
    # The 'x' variable ends up receiving the value of the same arity as my inner
    # defined function instead of the value of the outer scope where 'x' is.
    return a+x;
  return tmp;

event bro_init()
  local my_adder = add_x(5);
  print my_adder(1); # hopefully would print 6, but it prints 2

  local your_adder = add_x(100);
  print your_adder(2); # hopefully would print 102, but it prints 4

Would this functionality working like I wish it did be difficult? It would make a very nice usability feature for the measurement framework when setting thresholds.


Would this functionality working like I wish it did be difficult?

First, as best as I can figure, the current functionality is seriously
broken. It's reaching into a interpreter stack frame at the offset
associated with x. That just happens to be the offset associated with 'a'
during your my_addr()/your_addr() invocations, which is why the output is
a doubling of 'a'.

Indeed, I've confirmed that if your outer function had an additional
argument that comes before 'x', then the my_addr()/your_addr() invocations

To fix this, it makes sense that for functions defined inside other
functions, there's a clear binding model. The only trick is what
that model should be. If it's bind-on-function-creation, then you'd
get the semantics you desire. But I suspect there are other uses
for such interior funtions where bind-on-application is handy - *providing*
of course that the interior function doesn't escape to the exterior like
it does in your example.

My proposal would be to introduce bind-on-function-creation semantics,
and if later we find we sometimes want bind-on-application semantics,
introduce that using an attribute.

But there's still the "would this .... be difficult" question. I suspect
it's going to be messy. I'm having a hard time seeing how it doesn't
involve a full parse-tree traversal of the interior function's body during
creation. (And I leave the problem of the interior function itself having
an interior function as an exercise for the reader. :slight_smile: