Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Working with Lua

guides/working-with-lua.livemd

Working with Lua

Mix.install([
  {:lua, "~> 0.0.20"}
])

Setup

import Lua, only: [sigil_LUA: 2]
Lua

Executing Lua

code = ~LUA"""

"""

{value, %Lua{}} = Lua.eval!(code)
{[], #Lua<>}

Getting and Setting values

lua =
  Lua.new()
  |> Lua.set!([:dave], "Lucia")

{["Grohl", "Lucia"], %Lua{} = lua} =
  Lua.eval!(lua, ~LUA"""
  local original = dave;

  dave = "Grohl"

  return dave, original
  """)

Lua.get!(lua, [:dave])
"Grohl"

Exposing Elixir functions

Lua provides a module-based abstraction for defining APIs that can be called from Lua functions. Using use Lua.API with deflua defines APIs that are then loaded into the environment with the Lua.load_api/2 function.

In the example below, we load the my_print variadic function (a function that can take a variable number of arguments), and then call it from Lua.

defmodule Global do
  use Lua.API

  @variadic true
  deflua my_print(args) do
    IO.puts(Enum.join(args, " "))
  end
end

Lua.new()
|> Lua.load_api(Global)
|> Lua.eval!(~LUA"""
my_print("one", "two", "three")
""")
one two three
{[], #Lua<>}

There is quite a bit of flexibility for how functions can be defined. The module itself can define a scope under which all functions will be defined. In the previous example, no scope was defined, so functions were exposed in the globalscope.

Here we’ll define a scope, “my.foo”, and expose functions “bar” and “baz” underneath it

defmodule MyFooAPI do
  use Lua.API, scope: "my.foo"

  deflua bar(string) do
    "bar " <> string
  end

  deflua baz(string) do
    "baz " <> string
  end
end

{vals, %Lua{}} =
  Lua.new()
  |> Lua.load_api(MyFooAPI)
  |> Lua.eval!(~LUA"""
   return my.foo.bar("hi"), my.foo.baz("hello")
  """)

vals
["bar hi", "baz hello"]