Table sorting fails

I’m hitting a snag trying to sort a class by its member compval. The table seems to be normal, but when I call table.sort(), the second input parameter to the compare function is always nil.

My code, offending function is FlockingDude:findNearest():

--# Flocking

Flocking = class()

function Flocking:init()
    self.name = "Flocking"
    self.dudes = {}
end

function Flocking:setup()
    self.numDudes = 5
    for i = 1,self.numDudes do
        angle = 2*math.pi*i/self.numDudes
        self.dudes[i] = FlockingDude(i,(math.cos(angle)*.75+1)*WIDTH/2, (math.sin(angle)*.75+1)*HEIGHT/2, -angle)
    end
    physics.resume()
end

function Flocking:cleanup()
    
end

-- This function gets called once every frame
function Flocking:draw()
    print("foo")
    -- This sets a dark background color 
    background(40, 40, 50)

    -- This sets the line thickness
    strokeWidth(5)

    -- Do your drawing here
    for k, dude in pairs(self.dudes) do
        dude:interact(self.dudes)
        dude:react()
        dude:draw()
    end
end
--# FlockingDude
FlockingDude = class()

function FlockingDude:init(id, x, y, angle)
    -- you can accept and set parameters here
    self.id = id
    self.x = x
    self.y = y
    self.vel = vec2(0,0)
    self.angle = angle*180/math.pi
    self.rad = 20
    self.maxSpeed = 2
    
    self.body = physics.body(CIRCLE, self.rad)
    self.body.type = DYNAMIC
    self.body.interpolate = true
    self.body.position = vec2(x,y)
    self.body.angle = self.angle
    self.body.linearDamping = .5
end

function FlockingDude:draw()
    -- Codea does not automatically call this method
    self.x = self.body.position.x
    self.y = self.body.position.y
    self.vel = self.body.linearVelocity
    self.angle = self.body.angle
    fill(24, 255, 0, 255)
    pushMatrix()
    translate(self.x, self.y)
    rotate(self.angle)
    text(self.id)
  --  ellipse(0,0,self.rad*2)
    line(0,0,self.rad,0)
    popMatrix()
end

function FlockingDude:interact(dudes)
    local nearest = self:findNearest(dudes)
    
    for k, dude in pairs(nearest) do
        print(self.id, dude.id)
        line(self.x, self.y, dude.x, dude.y)
       -- local r = vec2(dude.x - self.x, dude.y - self.y)
        -- apply force and torque
        local f = vec2(dude.x - self.x, dude.y - self.y)
        local g = .1*math.min((.2-(30/f:len())^2), .05)
       -- print(g)
        self.body:applyForce(g*f)
    end
end

function FlockingDude:react()
    local r = self.maxSpeed - self.vel:len()
    if r > 0 then
        self.body:applyForce(r*self.vel)
    end
end

function FlockingDude:findNearest(dudes)
    local numFriends = 1
    local foundFriends = 0
    local nearest = {}
    local minDist = math.huge
    for k, dude in pairs(dudes) do
     --   print(self.id, k)
        if dude.id ~= self.id then
         --   print (vec2(self.x-dude.x,self.y-dude.y):len())
            if foundFriends < numFriends - 1 then
                table.insert(nearest, dude)
                dude.compval = vec2(self.x-dude.x,self.y-dude.y):len()
                foundFriends = foundFriends + 1
            else
                if vec2(self.x-dude.x,self.y-dude.y):len() < minDist then
                    table.insert(nearest, dude)
                    minDist = vec2(self.x-dude.x,self.y-dude.y):len()
                    dude.compval = minDist
                    foundFriends = foundFriends + 1
                end           
            end
        end
    end
    --if self.id == 3 then
      --  for i = 1,foundFriends do
      --      print(nearest[i].id, nearest[i].compval)
     --   end
   -- end
    if #nearest == 0 then
        return {}
    elseif #nearest <= numFriends then
        return nearest
    end
    print(self.id,"sort", #nearest)
    for i = 1,foundFriends do
            print(nearest[i].id, nearest[i].compval)
        end
    table.sort(nearest, FlockingDude.compare)
    --if self.id == 3 then
        for i = 1,foundFriends do
            print(nearest[i].id, nearest[i].compval)
        end
   -- end
    for i = 1,(foundFriends-numFriends) do
        table.remove(nearest)
    end
    return nearest
end

function FlockingDude:compare(dude1, dude2)
  --  print(dude1.id, dude1.compval, dude2.id, dude2.compval)
        
    if dude1 == nil then
        print("dude1 nil")
        return true
    elseif dude2 == nil then
        print("dude2 nil")
        return false
    end
    print("comp",dude1.compval, dude2.compval)
    if dude1.compval < dude2.compval then
        return true
    end
    return false
end

function FlockingDude:touched(touch)
    -- Codea does not automatically call this method
end

--# Main
-- Centurion

-- Use this function to perform your initial setup
function setup()
    -- Lock to current orientation
    supportedOrientations(CurrentOrientation)
    
    allModes = { Flocking() }
    currentMode = nil
    
    parameter.integer("ModeNumber", 1, #allModes, 1, setMode)
    
 --   parameter.action("Start / Reset Mode", function() currentMode:startOrResetAnimations() end)
    
    parameter.watch("currentMode.name")
    
    physics.gravity(0,0)
end

function setMode(index)
    if currentMode ~= nil then
        currentMode:cleanup()
    end
    
    currentMode = allModes[index]
    currentMode:setup()
end

-- This function gets called once every frame
function draw()
    if currentMode then
        currentMode:draw()
    end
end


```

Write the comparison function with a dot:


function FlockingDude.compare(dude1, dude2)

If you use the colon syntax, the compiler assumes an implicit parameter “self” and will transform it for you:


function FlockingDude:compare(dude1, dude2)
    |
    |  transformation by compiler
    v
function FlockingDude.compare(self, dude1, dude2)

Thanks a bunch! That worked like a charm and I’d never have tried that on my own.