lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Thu, Dec 13, 2012 at 1:24 PM, spir <denis.spir@gmail.com> wrote:
> What kind of go reflection features do you use to perform luar's magic?

Go has a reflection model which offers similar functionality to that
of Java's, except conceptually different. There is no base object
called 'Object' from which everything derives (this is why Stroustrup
said that Java was more than Smalltalk than C++). Instead, there is a
special empty type that can contain any Go type.

This can represent functions as well. We query what the argument types
are, and convert the passed Lua values on the stack to corresponding
Go values, which we pass to the Go function.  We know the return types
(Go does multiple return types like Lua) and do the opposite
operation, pushing the returned values as Lua values on the stack.

The ineresting word is 'corresponding';  you may pass a Lua table to
an imported Go function; if the table is 'array-like' then it can be
converted to a Go slice; if it is 'map-like' then it is converted to a
Go map.  Usually non-primitive Go values are passed to Lua as wrapped
userdata [1] which can be naturally indexed if they represent slices,
maps or structs.  Methods defined on structs can be called, again
using reflection.

The consequence is that a person wishing to use Lua from Go does not
have to use the old-fashioned tedious method needed for C or C++, but
at some cost in speed and memory.[2]

This is very convenient for common tasks like bringing in
configuration, where we're effectively serializing Go structs using
Lua tables.

E.g. say we have the following Go struct type:

type Config struct {
    Baggins bool
    Age int
    Name string
    Ponies []string
    Father *Config
}

Define a function which receives such an object and prints it out:

func config (cfg *Config) {
    fmt.Println("config",cfg)
    fmt.Println("father",cfg.Father)
}

and register it

 luar.Register(L,"",luar.Map{
        "config":config,
   })

and then executing the following piece of Lua code generates perfectly
decent statically-typed structures:

config {
  Baggins = true,
  Age = 24,
  Name = 'dumbo' ,
  Ponies = {'whisper','fartarse'},
  Father = {
     Baggins = false,
     Age = 77,
     Name = 'Wombo',
  }
}

There are some limitations compared to Java. There is no reflection
information available for Go packages, since they are statically
linked (and the linker needs the freedom to leave out unused
functions)

steve d.

[1] Setting metamethods was the change I needed to make to golua,
since __index etc can not be callable userdata
[2] I'm very aware of this at the moment because LuaJava does a
similar trick. But reflection using Java and JNI is slower because of
both the interop boundary and the reflection itself, and reflection
generates a lot of garbage - which is very important on a 'little
Java' platform like Android.