Partial function application, or “bind”

I’ve been doing a little thing that requires a partial function application, or a “bind” function. In use, I have a bunch of little “vehicles” with different behaviors. Some of those behaviors have parameters, which I want to provide at creation time. I’m looking for advice, ideas, explanations, …

Some code snippets:

Here we define a behavior with parameters 1, 3

    table.insert(bAvoidWalls, BVehicle1:partial(BVehicle1.behaveDefaultMotion, 1, 3))

Here we call our update, calling our bound functions.

function BVehicle1:update()
    self:locateEyes()
    local wheels = vec2(0,0)
    for i,b in pairs(self.behaviors) do
        wheels = wheels + b(self)  -- here we apply our behavior functions, passing self in. The 1,3 should be already bound.
    end
    self:determinePosition(wheels)
end

Here’s my current definition of partial:

function BVehicle1:partial(f, ...)
    local a = {...}
    return function(s)
        return f(s,unpack(a))
    end
end

This seems to work as intended. That is, partial returns a function expecting self followed by whatever parameters were in the call to partial, in our case, 1 and 3.

I’m aware of some packages like “varargs” that do similar things. Since this is all I need, and because of my “style”, I’m happy to roll my own.

It seems that there used to be a magic variable arg that worked like my declared a variable, but that seems to be gone. And for some reason, you can’t just inline with f(s,unpack({...})), though it looks like you could.

So … reflection, discussion, advice welcome. Thanks!

Not sure why you think arg is gone. It’s just a variable name. To use it set arg={…} then you can do v1=arg[1], v2=arg[2], etc or the way you’re using a above. Or am I not seeing what you’re after.

function setup()
    var(45,2,"333",4,32,"678")
end

function var(...)
    arg={...}
    print(arg[1],arg[3],arg[6])
end

@RonJeffries nice! I remember using the hell out of boost::bind a decade ago in C++ (and sending my compile times through the roof). It’s such a neat mechanism.

There’s an interesting discussion on reddit of ways to curry functions in Lua https://www.reddit.com/r/lua/comments/6yy9wu/currying_in_lua/

Thanks for link … :smile:

@dave1707 I had the perhaps mistaken impression that around Lua 5.1, “arg” was automatically set to {…}, but I may have misunderstood what I read. Anyway, yes, can do it as you describe, which is, I guess, essentially what I wound up doing.