рдореИрдВ рдЖрдкрдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд╣реАрдВ рдЬрд╛рдирддрд╛, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдкреНрд░рдгрд╛рд▓рд┐рдпреЛрдВ рдХреЗ рдЪрдХреНрдХрд░ рдореЗрдВ рдлрдВрд╕рдирд╛ рдкрд╕рдВрдж рд╣реИред рдФрд░ рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдореИрдВ рд▓реБрдЖ рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдХреА рдЖрдВрддрд░рд┐рдХ рд╕рдВрд░рдЪрдирд╛ рдФрд░ рдЙрдирдХреА рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред рдбреНрдпреВрдЯреА рдХреЗ рд▓рд┐рдП рд▓реБрдЖ рдореЗрд░реА рдкреНрд░рд╛рдердорд┐рдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рд╣реИ, рдФрд░ рдЕрдЪреНрдЫрд╛ рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдХрдо рд╕реЗ рдХрдо рдереЛрдбрд╝рд╛ рд╕рдордЭрдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИ рдХрд┐ рдкрд░реНрджреЗ рдХреЗ рдкреАрдЫреЗ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИред рдЬрд┐рдЬреНрдЮрд╛рд╕реБ, рдореИрдВ рдореЗрд░реЗ рд▓рд┐рдП рдкреВрдЫрдирд╛ред

рд▓реБрдЖ рдХреЗ рдХрдИ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдФрд░ рдХрдИ рд╕рдВрд╕реНрдХрд░рдг рд╣реИрдВред рд▓реЗрдЦ рдореБрдЦреНрдп рд░реВрдк рд╕реЗ LuaJIT 2.1.0 рдкрд░ рдХреЗрдВрджреНрд░рд┐рдд рд╣реЛрдЧрд╛, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдЯрд╛рд░рдирдЯреВрд▓ рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╣рдорд╛рд░реЗ рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рдкреНрд░рд╛рдорд╛рдгрд┐рдХ LuaJIT рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдереЛрдбрд╝рд╛ рдкреИрдЪ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпреЗ рдЕрдВрддрд░ рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдХреА рдЪрд┐рдВрддрд╛ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред
рдкреАрдпреВрд╕реА-рд░рд┐рдпреЛ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рдФрд░ рдЕрдЪреНрдЫреА рдкреНрд░рд╕реНрддреБрддрд┐ рд╣реИ [1] , рдпрджрд┐ рдЖрдк рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВред
рд╢рд┐рдХреНрд╖рд╛рддреНрдордХ рдХрд╛рд░реНрдпрдХреНрд░рдо
Lua тАФ , . ( ), key-value . ( nil). , тАФ [2].
local t1 = {}
local t2 = { 'Sunday', 'Monday', 'Im tired' }
local t3 = {
cat = 'meow',
dog = 'woof',
cow = 'moo',
}
local t4 = {
'k1', 'k2', 'k3'
['k1'] = 'v1',
['k2'] = 'v2',
['k3'] = 'v3',
}
LuaJIT [3] ( , , ):
typedef struct GCtab {
/* GC stuff */
MRef array; /* Array part. */
MRef node; /* Hash part. */
uint32_t asize; /* Size of array part (keys [0, asize-1]). */
uint32_t hmask; /* Hash part mask (size of hash part - 1). */
} GCtab;
: -. . , LuaJIT , . , , Lua, , . : , . , .
LuaJIT tostring()
, stdout
printf()
.
, , [4]. :
diff --git a/src/lj_strfmt.c b/src/lj_strfmt.c
index d7893ce..45df53c 100644
@@ -392,6 +392,51 @@ GCstr * LJ_FASTCALL lj_strfmt_obj(lua_State *L, cTValue *o)
if (tvisfunc(o) && isffunc(funcV(o))) {
p = lj_buf_wmem(p, "builtin#", 8);
p = lj_strfmt_wint(p, funcV(o)->c.ffid);
+ } else if (tvistab(o)) {
+ GCtab *t = tabV(o);
+ /* print array part */
+ printf("-- a[%d]: ", asize);
+ for (i = 0; i < asize; i++) {
+ // printf(...);
+ }
+
+ /* print hashmap part */
+ printf("-- h[%d]: ", hmask+1);
+ for (i = 0; i <= hmask; i++) {
+ // printf(...);
+ }
} else {
p = lj_strfmt_wptr(p, lj_obj_ptr(o));
}
, :
t = {}
tostring(t)
, LuaJIT 0 1 -, nil
nil
(.. ). :
t["a"] = "A"
t["b"] = "B"
t["c"] = "C"
tostring(t)
, , -. , тАФ . LuaJIT [5] [5] ( ).
, , . traverse()
, for
.
traverse- [4]. .
function traverse(fn, t)
local str = ''
for k, v, n in fn(t) do
str = str .. string.format('%s=%s ', k, v)
end
print(str)
end
t1 = {a = 1, b = 2, c = 3}
tostring(t1)
t2 = {c = 3, b = 2, a = 1}
tostring(t2)
traverse(pairs, t1)
traverse(pairs, t2)
: . -, .
t2["c"] = nil
traverse(pairs, t2)
tostring(t2)
print(next(t2, "c"))
, . тАФ , .
: , lookup' . . main node , predecessor main ( ). O(n), . dead node . . [5].
, , . тАФ :
t = {1, 2}
tostring(t)
Lua , . , LuaJIT . / .
, , ( ) тАФ :
t = {[2] = 2, 1}
tostring(t)
, , -. , : , .
: ?: LuaJIT, Lua, .
, .
$ luac -l - <<< "t1 = {1, 2}"
1 [1] NEWTABLE 0 2 0 -- 2 , 0 -
...
тАФ 1 -.
$ luac -l - <<< "t2 = {[2] = 2, 1}"
1 [1] NEWTABLE 0 1 1 -- 1 , 1 -
...
, , , . LuaJIT -, . , . .
pairs()
pairs()
. . . LuaJIT pairs()
, -. - -, :
t = table.new(4, 4)
for i = 1, 8 do t[i] = i end
tostring(t)
traverse(pairs, t)
: ?: table.new(narr, nrec)
тАФ lua_createtable(L, a, h)
Lua C API. (, ), .
. ( ) :
t[9] = 9
tostring(t)
. 99.9 % "" Lua , .
table.getn()
- . , тАФ Lua [6].
3.4.6 тАУ The Length Operator
The length of a table t is only defined if the table is a sequence, that is,
the set of its positive numeric keys is equal to {1..n} for some non-negative
integer n. In that case, n is its length. Note that a table like
{10, 20, nil, 40}
is not a sequence, because it has the key 4 but does not have the key 3. (So,
there is no n such that the set {1..n} is equal to the set of positive numeric
keys of that table.) Note, however, that non-numeric keys do not interfere with
whether a table is a sequence.
, . тАФ Lua undefined behavior. "" . LuaJIT lj_tab_len
[7] :
/*
** Try to find a boundary in table `t'. A `boundary' is an integer index
** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
*/
MSize LJ_FASTCALL lj_tab_len(GCtab *t);
LuaJIT "". , , LuaJIT , :
print(#{nil, 2})
print(#{[2] = 2})
: ?: .
tostring({nil, 2})
tostring({[2] = 2})
LuaJIT , . , -, .
, . , undefined behavior . , .
table.sort()
1 #t
, . , , :
local function is_array(t)
if type(t) ~= 'table' then
return false
end
local i = 0
for _, _ in pairs(t) do
i = i + 1
if type(t[i]) == 'nil' then
return false
end
end
return true
end
Lua, , , , .
Pack / unpack
? , - . , :
local function vararg(...)
local args = {...}
end
тАФ , .
- vararg(nil, "err")
, . unpack(t)
, ( , , UB).
Lua [8] :
6.5 тАУ Table Manipulation
unpack (list [, i [, j]])
Returns the elements from the given table. This function is equivalent to
return list[i], list[i+1], ┬╖┬╖┬╖, list[j]
except that the above code can be written only for a fixed number of elements.
By default, i is 1 and j is the length of the list, as defined by the length
operator #list.
, unpack(t, 1, #t)
unpack(t, 1, n)
, n
? , . varargs, table.pack()
, :
t = table.pack(nil, 2)
tostring(t)
traverse(pairs, t)
print(unpack(t, 1, t.n))
LuaJIT ( Tarantool) table.pack
- , -DLUAJIT_ENABLE_LUA52COMPAT
. :
function table.pack(...)
return {..., n = select('#', ...)}
end
select('#', ...)
[9], . , Lua [10] тАФ , Lua C (Lua C API). .
ipairs()
тАФ . . ipairs
, while
:
local i = 1
while type(t[i]) ~= 'nil' do
i = i + 1
end
, "" undefined behavior тАФ .
t = {1, 2, nil, 4}
print(#t)
traverse(ipairs, t)
FFI
, type(x) ~= 'nil'
. x == nil
? , LuaJIT, PUC-Rio Lua, cdata
:
ffi = require('ffi')
NULL = ffi.new('void*', nil)
print(type(NULL))
print(type(nil))
print(NULL == nil)
if NULL then print('NULL is not nil') end
Tarantool, box.NULL
. тАФ if NULL
( if nil
), NULL == nil
.
LuaJIT тАФ FFI . Lua, FFI Lua . LuaJIT . , [11]:
Lua tables may be indexed by cdata objects, but this doesn't provide any useful
semantics тАФ cdata objects are unsuitable as table keys!
A cdata object is treated like any other garbage-collected object and is hashed
and compared by its address for table indexing. Since there's no interning for
cdata value types, the same value may be boxed in different cdata objects with
different addresses. Thus t[1LL+1LL] and t[2LL] usually do not point to the
same hash slot and they certainly do not point to the same hash slot as t[2].
, cdata
- ( void*
), , . Tarantool:
tarantool> t = {1}; t[1ULL] = 2; t[1ULL] = 3;
---
...
tarantool> t
---
- 1: 1
1: 3
1: 2
...
tarantool> t[1ULL]
---
- null
...
, , cdata
, . uuid
[12] clock.time64()
Tarantool. , unsigned
.
, FFI, :
tarantool> t = {'normal one'}
t[1.0 + 2^-52] = '1.0 + 2^-52'
t[0.1 + 0.3*3] = '0.1 + 0.3*3'
---
...
tarantool> t
---
- 1: normal one
1: 1.0 + 2^-52
1: 0.1 + 0.3*3
...
#t
. тАФ Undefined behavior.ipairs()
while type(t[i]) ~= 'nil'
тАФ , , .pairs()
, .unpack
, table.sort
, table.insert
, table.remove
, -, undefined behavior #t
.- "" (ffi) . .
[1] The basics and design of Lua table ( slideshare.net).
[2] Programming in Lua тАФ Tables
[3] GitHub тАФ LuaJIT/LuaJIT тАФ lj_obj.h
[4] GitHub тАФ rosik/luajit:habr-luajit-tables
[5] тАФ - тАФ
[5a] GitHub тАФ LuaJIT/LuaJIT тАФ Issue #494.
[6] Lua 5.2 Reference manual тАФ The Length Operator
[7] GitHub тАФ LuaJIT/LuaJIT lj_tab.c
[8] Lua 5.1 Reference manual тАФ Basic Functions тАФ unpack
[9] Lua 5.1 Reference manual тАФ Basic Functions тАФ select
[10] Lua 5.1 Reference manual тАФ The Stack
[11] GitHub тАФ LuaJIT/LuaJIT тАФ ext_ffi_semantics.html
[12] Tarantool ┬╗ 2.2 ┬╗ Reference ┬╗ Built-in modules reference ┬╗ Module uuid
[Bonus] Learn X in Y Minutes, where X=Lua
[Bonus] тАФ Lua.