Howdy, Stranger!

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

Wrap Sort anonymous function

edited July 2014 in Questions Posts: 6

I want to sort a list of points in space - however, the area wraps around. So I want to take a starting point and sort points based on walking in one direction, wrapping back round to where I started.

Basically I'm pushing some crates that will appear through the edge of the map behind me as I push them through the edge of the map in front of me.

I must however move the crate in front of me last for obvious reasons. That's why I need to sort the list of crates in this fashion.

I need to get the starting point of the wrapping sort into the function I'm feeding to table.sort(). I can think of some extremely hacky ways to do it (I've noticed the compiler doesn't like a lot of my ideas in this direction). But I'm wondering if there's a simple way to do this. I've looked up lots of examples of table.sort() and they only have anonymous function examples. I've tried to feed it a class function but it didn't like the colon syntax. Which annoys me because I could have kept the logic for the sort internal to the class calling it.

Any ideas?

Comments

  • Posts: 134

    I'd use two crates with identical values and rotate between the two...

    If(Crate1.x + crate1.length >= WIDTH) then
    Crate2 = Crate()
    --copy all values for crate1
    Crate2.x = WIDTH - (crate1.x + crate1.length)
    End

    If(Crate2.x + crate2.length >= WIDTH) then
    Crate1 = Crate()
    --copy all values for crate2
    Crate1.x = WIDTH - (crate2.x + crate2.length)
    End

    So as one falls off another would start at the very beginning of the left of the screen...I'm not really a pro, but that's how I'd do it

  • IgnatzIgnatz Mod
    Posts: 5,396

    @st33d - maybe this will help

    http://codea.io/talk/discussion/3166/methods-as-callbacks/p1

    (Googling "class callback" may bring up more, this has been raised several times before)

  • edited July 2014 Posts: 425

    If you want to pass a class function use

    function()
        classname:function()
    end
    

    Edit: sorry Ignatz already said that

  • edited July 2014 Posts: 6

    I get it now with classes and self referencing, but what I was really asking was if there was a way to get persistent data into the anonymous function that is fed to table.sort.

    I think there's a way to do it with closures. I've put together a clunky example with my basic knowledge:

    function setSort(a, b)
      local c = a
      return function(a, b)
        print(a, b, c)
        return a < b
      end
    end
    
    test = setSort(5)
    
    t = {4, 2, 1, 3, 4, 5}
    
    table.sort(t, test)
    
    print(table.concat(t, " "))
    

    Can anyone with a better understanding of closures improve on this?

    *edit

    I'm guessing that technically I should be able to return an anonymous function from a class method and that sort function would have access to the class - right?

  • Posts: 425

    You could pass selfto the function from the class

  • Jmv38Jmv38 Mod
    edited July 2014 Posts: 3,295

    @st33d yes that would work

    MyClass = class()
    function MyClass:getSort()
      return function(a,b) return a<b end
    end
    
    a = MyClass()
    
    f = a:getSort()
    

    but it is more efficient (speed, memory) to use a defined function than an anonymous one:

    MyClass = class()
    function MyClass.sort(a,b)
       return a<b 
    end
    
    a = MyClass()
    
    f = a.sort
    
  • Posts: 6

    Ah, but MyClass.sort doesn't have access to self. The colon syntax is shorthand:

    obj:method(a, b)
    
    -- actually calling:
    obj.method(self, a, b)
    

    Which is why a class function is inadmissible as a sort function. "self" isn't an intrinsic property of the class. It's passed into every function of an object secretly through the colon syntax. The function has to be declared in a scope where self exists. MyClass.sort won't work because it has access to global scope and itself. Not the scope of the class where the boundaries to wrap around are defined.

    This should work however:

    function MyClass:init(bounds)
      self.bounds = bounds
      self.sort = function(a, b)
        local ax = a.x
        local bx = a.x
        if ax < self.bounds then ax = ax + self.bounds end
        if bx < self.bounds then bx = bx + self.bounds end
        return ax < bx
      end
    end
    

    The function is declared in a scope aware of self and bounds. I should be able to pass self.sort to table.sort. The class aware of the bounds is a Controller class for the crates - so I'm only likely to declare one at a time. Declaring in the crates would be a waste of memory, yes.

  • Jmv38Jmv38 Mod
    Posts: 3,295

    i didnt read in your post and example that you needed to access self.bounds, this is why i suggested MyClass.sort.
    Your last example should work as you say.

Sign In or Register to comment.