127.0.0.1:6379> eval "local aa=pack(unpack(ARGV,2,#ARGV)) return redis.call('sadd',KEYS[1],aa)" 1 key arg1 arg2 (error) ERR Error running script (call to f_2961ff8533652dde446fc22e1f4e041364a4fc82): @enable_strict_lua:15: user_script:1: Script attempted to access nonexistent global variable 'pack'

Why can I use unpack, but pack can't? Which version of lua does redis use? Which libaray does this unpack come from?

The goal is to extract the list of parameters, except for the first parameter. The current method is to use the function.

final RedisScript<Long> script = RedisScript.of(
"local function f_sadd_expire(a_timeout,...) " +
"local count=redis.call('sadd', KEYS[1], unpack(arg)) " +
"redis.call('pexpire', KEYS[1], a_timeout) " +
"return count end " +
"return f_sadd_expire(unpack(ARGV))",
Long.class);

Equivalent to

eval "local function _f(a_t,...) local c=redis.call('sadd',KEYS[1],unpack(arg)) redis.call('pexpire',KEYS[1], a_t) return c end return _f(unpack(ARGV))" 1 aset 500000 arg1 arg2 arg3

The final goal is atomic operation of sadd with expire, any suggestions in any steps? THX!

Comment From: yoav-steinberg

Hi, first please try posting redis usage questions in one of these:


Specifically here I don't see any usage of pack in your script. It seems to run just fine and atomically sets the expiry value and adds selements to the set as described. Whats the problem exactly? Redis uses LUA 5.1.

Comment From: AHBICJ

OK, next time i will post question in discussions.

I try to run this script and it fails

eval "local aa=pack(unpack(ARGV,2,#ARGV)) return redis.call('sadd',KEYS[1],aa)" 1 key arg1 arg2

Comment From: yoav-steinberg

pack() isn't part of lua 5.1

Comment From: AHBICJ

Indeed, so I am confused where the unpack comes from

Comment From: yoav-steinberg

Indeed, so I am confused where the unpack comes from

https://www.lua.org/manual/5.1/manual.html#pdf-unpack

Comment From: itamarhaber

Adding to everything that @yoav-steinberg said, note that the pack you're looking for is the table constructor, i.e. {}. Lua's unpack() is the equivalent of the so-called splat operator in other languages. We can see this in the following example:

127.0.0.1:6379> EVAL "return 1, 2, 3" 0
(integer) 1
127.0.0.1:6379> EVAL "return {1, 2, 3}" 0
1) (integer) 1
2) (integer) 2
3) (integer) 3
127.0.0.1:6379> EVAL "return unpack({1, 2, 3})" 0
(integer) 1
127.0.0.1:6379> EVAL "return {unpack({1, 2, 3})}" 0
1) (integer) 1
2) (integer) 2
3) (integer) 3

In the first example, you see that while Lua supports the return of multiple values, Redis always limits it to the first one. In the 2nd, we return a table/list as a single argument that Redis knows internally how to "unpack" to an array. In the 3rd, the table is unpacked in Lua, essentially turning it into multiple values. The 4th shows how it can be reversed.

I hope this clarifies matters.

Comment From: AHBICJ

Indeed, so I am confused where the unpack comes from

https://www.lua.org/manual/5.1/manual.html#pdf-unpack

I got it, thank you very much

Comment From: AHBICJ

Adding to everything that @yoav-steinberg said, note that the pack you're looking for is the table constructor, i.e. {}. Lua's unpack() is the equivalent of the so-called splat operator in other languages. We can see this in the following example:

127.0.0.1:6379> EVAL "return 1, 2, 3" 0 (integer) 1 127.0.0.1:6379> EVAL "return {1, 2, 3}" 0 1) (integer) 1 2) (integer) 2 3) (integer) 3 127.0.0.1:6379> EVAL "return unpack({1, 2, 3})" 0 (integer) 1 127.0.0.1:6379> EVAL "return {unpack({1, 2, 3})}" 0 1) (integer) 1 2) (integer) 2 3) (integer) 3

In the first example, you see that while Lua supports the return of multiple values, Redis always limits it to the first one. In the 2nd, we return a table/list as a single argument that Redis knows internally how to "unpack" to an array. In the 3rd, the table is unpacked in Lua, essentially turning it into multiple values. The 4th shows how it can be reversed.

I hope this clarifies matters.

Thank you very much! So I wonder is there any elegant way to extract the other parameters in the parameter list except the first one. This is the beginning of all the trouble.