What does unpack() do and why do I get different results?

What do I want to achieve?
I would like to know exactly how unpack() works.

What is the issue?
When I store the unpacked table in a variable then print it, it gives me a different value than when I print the unpacked table directly.

What solutions have I tried so far?

local Tab = {"First","Second","Third"}

local Result1 = unpack(Tab)
print(Result1) -- First

local Result2 = print(unpack(Tab)) -- First Second Third

I do not understand why the outputs are different. If anybody knows why and could explain to me, it would mean a lot to me. Thank you!

7 Likes

In Lua, functions can return multiple values. They are not packed into one big data structure, unlike Python for example.

def foo():
    return "a", "b", "c"

tpl = foo()
print(tpl) # ('a', 'b', 'c')

Python implicitly packs the results into 1 big tuple. A tuple in Python is an immutable list.

In Lua however this is different. Tables are actually the only data structure in Lua.

Multiple returns are not implicitly packed into a table.

In your case, since unpack returns multiple things, your variable only gets the first result, and the other ones are discarded.

print can take multiple arguments, which is why it printed all 3

6 Likes

Thank you for explaining it to me! I am still a bit unsure though, how would I print the all values of the table or store it into a function?

1 Like

Here is a post that explains various ways to use Pack() and Unpack():

1 Like

You could pack all the values together again using table.pack

local t = table.pack(table.unpack(Tab))

But that kinda defeats the purpose of unpacking in this case. What are you trying to do?

2 Likes

So I wanted to have have a list of the player’s past usernames.

game.Players.PlayerAdded:Connect(function(plr)
	local NamesTable = game.HttpService:JSONDecode(game.HttpService:GetAsync("https://rprxy.xyz/proxy/api/usernames/"..plr.UserId))
	local List = unpack(NamesTable)
	local Full = string.gsub(List," ",", ")
end)

It uses the API endpoint Rprxy and gets their past usernames, then (I was hoping for it to) return a table. Which it did, but when I unpacked the table it only gave me the value of the first index. I think I know how to do this by using a for loop and inserting it into a string but it would be too tedious. So I was wondering if there was an easier way; perhaps utilising unpack(). The string.gsub() was to replace the spaces (of the unpacked table) with a comma and a space so that it would be nicer to read.

2 Likes

Ah! For this you should use table.concat(t, delimiter, i, j).

It returns a string of all the elements of t separated by delimiter, starting at i and ending at j. The third argument defaults to 1 and the last argument defaults to the length of the table. The second argument defaults to an empty string, so everything will be ‘mashed’ together with no delimiter.

local Full = table.concat(List, ", ")
10 Likes

It worked, thank you so much! You saved me a lot of a time haha.

1 Like