|Don't ask to ask, just ask|
The arbitrary operator makerby jimt (Chaplain)
|on Nov 22, 2006 at 19:14 UTC||Need Help??|
Over in Ultra compact set searching, I had a little function called "and_maker" which inspired two comments, so I figured I'd generalize it and give it its own node.
The general problem is: I have an operation I would like to perform on each element in a list.
It's very easy to state. It's very easy to think about. "I want to add up these 5 items." "I want to multiply these 7 things." "I want to xor these 83 elements." Like so many things, the devil's in the details. While you can hardwire your function to add up exactly 5 things, you may need to add up 6 next time. And maybe 4 after that.
The standard approach is to use an iterator. I'll show you a different way. Not necessarily better, but different.
A standard way to do this might be something like the following. Say you want to add up a list of elements:
What we're gonna do instead is dynamically generate a subroutine that only operates on the number of elements you have for this call. We'll be slick and cache the function so that subsequent calls give us back the same code snippet. Call the arbitrary_operator_maker with two arguments - the operator and the number of elements.
You then create a new coderef for what you want to do:
The function generated is straightforward. If you looked at what it actually does (which you can see by dumping out the $built variable inside the arbitrary_operator_maker, it builds up your list of elements once for you, for repeated use.
Okay, so what? Well, this newly created function doesn't need to iterate, it just performs the operation as many times as you need. Performance can be impressive, as I'd written up over here. But, in other testing I'd done, its scaling is twitchy.
There also is overhead with doing the lookup and dispatching a pre-created function. If you can cache yourself in advance, the benefits are impressive. But my caching routine may just suck.
Basically, a technique like this would be useful if you're going to do the same operation many many times over the same number of arguments. If not, the overhead of building the function or even looking up a pre-cached function may cause performance to fall below that of an iterator. This version of the operator maker also does no bounds checking. So you can call $add_5_things with 3 elements or 97 of them. That may be a bad thing. YMMV.