# Introduction to luajr

luajr allows you to run Lua code from R.

Lua is a lightweight, simple, and fast scripting language that is used in a variety of settings. The standard Lua interpreter is already reasonably fast, but there is also a just-in-time compiler for Lua called LuaJIT that is even faster. luajr uses LuaJIT.

This is not a guide to Lua or LuaJIT; it is a quick-start guide to luajr for people who already know how to program in Lua. See the Lua web site for resources related to coding in Lua, and the LuaJIT web site for resources related to LuaJIT itself.

## Running Lua code: `lua()` and `lua_shell()`

    library(luajr)

To get a feel for luajr or to run “one-off” Lua code from your R project, use `lua()` and `lua_shell()`.

When you pass a character string to `lua()`, it is run as Lua code:

    lua("return 'Hello ' .. 'world!'")
    #> [1] "Hello world!"

Assignments to global variables will persist between calls to `lua()`:

    lua("my_animal = 'walrus'")
    lua("return my_animal")
    #> [1] "walrus"

This is because luajr maintains a “default Lua state” which holds all global variables. This default Lua state is opened the first time a package function is used. You can create your own, separate Lua states, or reset the default Lua state (see Lua states, below).

Assignments to local variables will not persist between calls to `lua()`:

    lua("local my_animal = 'donkey'")
    lua("return my_animal")
    #> [1] "walrus"

In this case, the second line returns `"walrus"` because the local variable `my_animal` goes out of scope after the first call to `lua()` ends, so the second call to `lua()` is referring back to the global variable `my_animal` from before.

You can include more than one statement in the code run by `lua()`:

    lua("local my_veg = 'potato'; local my_dish = my_veg .. ' pie'; return my_dish")
    #> [1] "potato pie"

You can also use the `filename` argument to `lua()` to load and run a Lua source file, instead of running the contents of a string.

Call `lua_shell()` to open an interactive Lua shell at the R prompt. This can be helpful for debugging or for testing Lua statements.

## Calling Lua functions from R: `lua_func()`

The key piece of functionality for luajr is probably `lua_func()`. This allows you to call Lua functions from R.

The first argument to `lua_func()`, `func`, is a string that should evaluate to a Lua function. `lua_func()` then returns an R function that can be used to call that Lua function from R. For example, you can use `lua_func()` to access an existing Lua function from R:

    luaprint = lua_func("print")
    luaprint("Hello, world")
    #> NULL

Here, `"print"` is just referring to the built-in Lua function `print` which prints a Lua value to the console. You can also use `lua_func()` to refer to a previously defined function in the default Lua state:

    lua("function excited_print(x) print(x .. '!') end")
    lua("return excited_print('Hello, world')")

    xp = lua_func("excited_print", "native")
    xp("Wow")
    #> NULL

Or you can use `lua_func()` to define an anonymous Lua function:

    timestwo = lua_func("function(x) return x*2 end", "native")
    timestwo(123)
    #> [1] 246

Under the hood, `lua_func()` just takes its first parameter (a string), adds `"return "` to the front of it, executes it as Lua code, and registers the result as the function.

The second argument to `lua_func()`, `argcode`, is also very important. `argcode` determines how the arguments passed to the function from R are translated into Lua variables for use inside the function.

The most important argcodes are `"auto"` and `"native"`.

The argcode `"auto"` means that the parameter should be passed as a luajr type providing direct access to the R variable passed in. For example, with the argcode `"auto"`, an R numeric vector is passed as a `luajr.numeric` type, an R character vector is passed as a `luajr.character` type, and an R function is passed as a `luajr.rfunction type`. For a guide to luajr types, see the vignette The luajr.lua module

The argcode `"native"` means that the R value passed in should be converted to a native Lua type. For example, with the argcode `"native"`, a single number in R like `2.5` is passed as a Lua number, a single string like `"foo"` is passed as a Lua string, and a list like `list(a = 1, b = 2)` or a vector like `10:12` is passed as a Lua table.

For example, suppose you want to pass the R numeric vector `c(1.1, 3.3, 2.2)` into a Lua function from which you will return the biggest number in the vector. If you want the numeric vector to come into your function as a `luajr.numeric` type, you could write:

    x = c(1.1, 3.3, 2.2)
    my_max = lua_func("
    function(x)
        local max = nil
        for i = 1,#x do
            if max == nil or x[i] > max then
                max = x[i]
            end
        end
        return max
    end", "auto")
    my_max(x)

If you want the numeric vector to come into your function as a Lua table, you could write:

    x = c(1.1, 3.3, 2.2)
    my_max = lua_func("
    function(x)
        return math.max(unpack(x))
    end", "native")
    my_max(x)

where the above example takes advantage of Lua’s built-in `math.max` function that returns the biggest element from among all the arguments passed in.

The permissible arg codes are:

Arg code | Short form | Accepted R types | Resulting Lua type
--- | --- | --- | ---
`auto` | `.` | any |
`sexp` | `S` | any | `R.sexp`
`rfunction` | `F` | function | `luajr.rfunction`
`environment` | `E` | environment | `luajr.environment`
`logical` | `L` | logical | `luajr.logical`
`integer` | `I` | integer, numeric (coerced) | `luajr.integer`
`numeric` | `N` | numeric, integer (coerced) | `luajr.numeric`
`character` | `C` | character | `luajr.character`
`vector`, `list` | `V` | list | `luajr.list`
`pointer` | `P` | external pointer | light `userdata`
`native` | `$.` | any native-compatible type |
`function` | `$F` | function or external pointer to Lua function | `function`
`boolean` | `$L` | length-1 logical | `boolean`
`number` | `$N` | length-1 integer or numeric | `number`
`string` | `$C` | length-1 character | `string`
`table` | `$V` | list or atomic vector | `table`

Arg codes should be separated from each other by a comma, semicolon, or space within the string. “Short form” arg codes do not need to be separated. For example, `"S$L"` is equivalent to `"sexp, boolean"`.

Above, the `$` prefix specifies “native type”.

There is also the `!` prefix, which can be used to specify “strict” mode. In “strict” mode, there is no coercion between integer and numeric types, and `NULL` yields an error instead of `nil` when a Lua native type is requested.

The `&` prefix can be used to specify that an R vector type should be passed by reference. When a vector (logical vector, integer vector, numeric vector, character vector, or list) is passed from R to Lua by reference, modifications made to the elements of that passed-in vector persist back in the R calling frame. For example:

    values = c(1.0, 2.0, 3.0)
    keep = lua_func("function(x) x[1] = 999 end", ".") # passed by value
    keep(values)
    #> NULL
    print(values)
    #> [1] 1 2 3

    change = lua_func("function(x) x[1] = 999 end", "&.") # passed by reference
    change(values)
    #> NULL
    print(values)
    #> [1] 999   2   3

Vectors can never be resized by reference; only their already-existing elements can be changed by reference.

## Working with Lua States: `lua_open()`, `lua_reset()`

All the functions mentioned above (`lua()`, `lua_shell()`, and `lua_func()`) can also take an argument `L` that specifies a particular Lua state that the function operates in.

When `L = NULL` (the default) the functions operate on the default Lua state.

But you can also open alternative Lua states using `lua_open()`, and then by passing the result as the parameter `L`, specify that the function operates in that specific state. For example:

    L1 = lua_open()
    lua("a = 2")
    lua("a = 4", L = L1)
    lua("return a")
    #> [1] 2
    lua("return a", L = L1)
    #> [1] 4

There is no `lua_close` in luajr because Lua states are closed automatically when they are garbage collected in R.

`lua_reset()` resets the default Lua state:

    lua("a = 2")
    lua("return a")
    #> [1] 2
    lua_reset()
    lua("return a")
    #> NULL

To reset a non-default Lua state `L` returned by `lua_open()`, just do `L = lua_open()` again. The memory previously used by `L` will be cleaned up at the next garbage collection.

## Further reading

For notes on how to create and manipulate R objects – such as vectors, lists, and data.frames – in your Lua code, see the luajr.lua module vignette.