1

I am following the example of simple lua class from this tutorial but try to store the class definition in a separate file and load as a module

I created a simple class called List and I can create a list, and fill with following code (List.lua):

local List = {}
List.__index=List
function List.create(t)   -- 2nd version
      local list = {}
      setmetatable(list, List)
    --  self.__index = self
      for i=1,#t do list[i] = t[i] end
      return list
end
function List.fill(self, x)
    for k=1, #self do self[k]=x end
end
return List

to use it, I just need to type

List = require "List"
a = List.create({1,2,3,4})
print(a)  -- {1,2,3,4}
a:fill(a,0)
print(a) -- shows {0,0,0,0}

So far so good.

Question

Now I am going to move List to a package in LuaJ so I can do the List implementation in Java.

public class ListLib extends TwoArgFunction {
    public LuaValue call(LuaValue modname, LuaValue env) {
        LuaTable lib = new LuaTable(0,30);
        List.rawset(LuaValue.INDEX, List);
        //List.rawset(LuaValue.ADD, new add());
        lib.set("create", new create());
        lib.set("fill", new fill());

        String name = "List";
        env.set(name, lib);
        env.get("package").get("loaded").set(name, lib);
        return lib;
    }
    static LuaTable List = new LuaTable();
    static final class create extends OneArgFunction {
        @Override
        public LuaValue call(LuaValue arg) {
            LuaTable list=new LuaTable();
            list.setmetatable(List);
            LuaTable in = (LuaTable)arg;
            for(int i=1; i<=in.length();i++)
                list.set(i, in.get(i));

            return list;
        }
    }
    final class fill extends TwoArgFunction {
        @Override
        public LuaValue call(LuaValue arg1, LuaValue arg2) {
            LuaTable self = (LuaTable) arg1;
            double x = arg2.checkdouble();
            for(int i=1;i<=self.length();i++)
                self.set(i, LuaNumber.valueOf(x));
            return NONE;
        }
    }
}

I can create the list in the same way, but I couldn't find a way to call fill on object a now, e.g. a:fill(0) doesn't work. It shows

attempt to call nil

I can do List.fill(a, 0). Is this the limitation of LuaJ, or is there any other way to make a:fill(0) work?

Hai Bi
  • 1,173
  • 1
  • 11
  • 21
  • I don't know if there is a problem with your LuaJ code, but there is an error with how you are calling it. `a.fill(0)` calls the `fill()` function with only one argument: `0`. What you need is `a:fill(a, 0)` which is syntax sugar for `a.fill(a, 0)`. Hope that solves your issue, but I'm not certain it will. – ktb Jul 21 '18 at 19:32
  • Thanks for this finding, but have fixed it. It should be a:fill(0) which is equivalent to fill(a,0) (note there is no a. in front fill). Or it should be List.fill(a,0). But in lua, a:fill(0) works as well. – Hai Bi Jul 21 '18 at 20:42
  • 1
    Yep, totally screwed writing that comment up. Sorry to confuse you. `a:fill(0)` should be correct. Did you try that? – ktb Jul 21 '18 at 20:44
  • I figured out what's going on now, and will put an answer. Thanks for making me feeling confident that it should work. – Hai Bi Jul 21 '18 at 21:34

1 Answers1

1

I made a mistake. I created a List and set __index which was fine. I also created a lib in the call function at the beginning of the ListLib class. It returned lib. What I should do is: merge these two tables into one: List is lib. After I did that. It works fine now.

public class ListLib extends TwoArgFunction {
    public LuaValue call(LuaValue modname, LuaValue env) {
        List.rawset(LuaValue.INDEX, List);
        //List.rawset(LuaValue.ADD, new add());
        List.set("create", new create());
        List.set("fill", new fill());

        String name = "List";
        env.set(name, List);
        env.get("package").get("loaded").set(name, List);
        return List;
    }
    static LuaTable List = new LuaTable();
...
Hai Bi
  • 1,173
  • 1
  • 11
  • 21