Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Partial function application, or “bind”

in General Posts: 338

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!

Comments

  • dave1707dave1707 Mod
    edited March 8 Posts: 7,468

    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
    
  • SimeonSimeon Admin Mod
    Posts: 4,837

    @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/

  • Posts: 338

    Thanks for link ... :smile:

  • Posts: 338

    @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.

Sign In or Register to comment.