Recipes Lua - AnaNek/tarantool GitHub Wiki

Lua Language

Iterate over a Lua table

tarnatool> array = { 'Apple', 'Orange', 'Grapefruit', 'Banana'}
tarantool> for k, v in ipairs(array) do print(k, v) end
1       Apple
2       Orange
3       Grapefruit
4       Banana
---
...

tarantool> map = { k1 = 'v1', k2 = 'v2', k3 = 'v3' }
tarantool> for k, v in pairs(map) do print(k, v) end
k3      v3
k1      v1
k2      v2
---
...

Remember: :func:`ipairs()` for arrays-like tables and :func:`pairs()` for map-like and mixed tables. :func:`ipairs()` is faster than :func:`pairs()`.

Get the number of items in array-like table

Use operator '#':

tarantool> array = { 1, 2, 3}
---
...
tarantool> #array
---
- 3
...

Please note this operation has O(log(N)) complexity.

Try not to put nil in arrays. The length operator # will be confused and standard table functions like table.sort() will complain bitterly.

tarantool> t = {}
tarantool> t[1] = 1
tarantool> t[4] = 4
tarantool> t[10] = 10
tarantool> = #t  --> NB!
---
- 1
...
tarantool> for k,v in pairs(t) do print(k,v) end
1       1
4       4
10      10

Get the number of items in map-like table

Lua doens't store this value anywhere. Iterate over the table and calculate size:

tarantool> map = { a = 10, b = 15, c = 20 }
---
...

tarantool> size = 0; for _ in pairs(map) do size = size + 1; end
---
...

tarantool> size
---
- 3
...

Swap two variables

x, y = y, x

Classes and objects

-- define class objects
local myclass_somemethod = function(self)
    print('test 1', self.data)
end

local myclass_someothermethod = function(self)
    print('test 2', self.data)
end

local myclass_tostring = function(self)
    return 'MyClass <'..self.data..'>'
end

local myclass_mt = {
    __tostring = myclass_tostring;
    __index = {
        somemethod = myclass_somemethod;
        someothermethod = myclass_someothermethod;
    }
}

-- create a new object of myclass
local object = setmetatable({ data = 'data'}, myclass_mt)
print(object:somemethod())
print(object.data)

See also:

Run garbage collector

collectgarbage('collect')

See also :func:`collectgarbage` documentation.

Tables and nil values

Lua doesn't store nil in tables. a[2] = nil is semantically means delete key 2 from a. However, you can store special NULL value which is semantically identical to nil:

tarantool> json.encode({a = 10, b = nil, c = 20})
---
- '{"a":10,"c":20}'
...
tarantool> json.encode({a = 10, b = json.NULL, c = 20})
---
- '{"b":null,"a":10,"c":20}'
...
tarantool> json.NULL == nil
---
- true
...

Call a built-in C function

#!/usr/bin/env tarantool

local ffi = require('ffi')
ffi.cdef[[
    int printf(const char *format, ...);
]]

ffi.C.printf("Hello, %s\n", os.getenv("USER"));

See FFI tutorial for more examples.

Call a C function from a library

#!/usr/bin/env tarantool

local ffi = require("ffi")
ffi.cdef[[
    unsigned long compressBound(unsigned long sourceLen);
    int compress2(uint8_t *dest, unsigned long *destLen,
    const uint8_t *source, unsigned long sourceLen, int level);
    int uncompress(uint8_t *dest, unsigned long *destLen,
    const uint8_t *source, unsigned long sourceLen);
]]
local zlib = ffi.load(ffi.os == "Windows" and "zlib1" or "z")

-- Lua wrapper for compress2()
local function compress(txt)
    local n = zlib.compressBound(#txt)
    local buf = ffi.new("uint8_t[?]", n)
    local buflen = ffi.new("unsigned long[1]", n)
    local res = zlib.compress2(buf, buflen, txt, #txt, 9)
    assert(res == 0)
    return ffi.string(buf, buflen[0])
end

-- Lua wrapper for uncompress
local function uncompress(comp, n)
    local buf = ffi.new("uint8_t[?]", n)
    local buflen = ffi.new("unsigned long[1]", n)
    local res = zlib.uncompress(buf, buflen, comp, #comp)
    assert(res == 0)
    return ffi.string(buf, buflen[0])
end

-- Simple test code.
local txt = string.rep("abcd", 1000)
print("Uncompressed size: ", #txt)
local c = compress(txt)
print("Compressed size: ", #c)
local txt2 = uncompress(c, #txt)
assert(txt2 == txt)

See FFI tutorial for more examples.

Metamethods for C objects

local ffi = require("ffi")
ffi.cdef[[
typedef struct { double x, y; } point_t;
]]

local point
local mt = {
  __add = function(a, b) return point(a.x+b.x, a.y+b.y) end,
  __len = function(a) return math.sqrt(a.x*a.x + a.y*a.y) end,
  __index = {
    area = function(a) return a.x*a.x + a.y*a.y end,
  },
}
point = ffi.metatype("point_t", mt)

local a = point(3, 4)
print(a.x, a.y)  --> 3  4
print(#a)        --> 5
print(a:area())  --> 25
local b = a + point(0.5, 8)
print(#b)        --> 12.5

Current time with millesecond precision

Call :func:`gettimeofday()` or :func:`clock_gettime()` using Foreign Function Interface (FFI):

local ffi = require('ffi')
ffi.cdef[[
    typedef long time_t;
    typedef struct timeval {
    time_t tv_sec;
    time_t tv_usec;
} timeval;
    int gettimeofday(struct timeval *t, void *tzp);
]]

-- Function for getting current time
local timeval_buf = ffi.new("timeval")
local now = function()
    ffi.C.gettimeofday(timeval_buf, nil)
    return tonumber(timeval_buf.tv_sec * 1000 + (timeval_buf.tv_usec / 1000))
end
⚠️ **GitHub.com Fallback** ⚠️