Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

Metatable function not printing name correctly?

The problem is, my code prints nil, when it should, in theory, print Table1. I am new to metatables, and also don't have access to the wiki right now.

Is it because, on Line 4 & 9, when I print and set the 'Name' value, it shouldn't be in the 'funcs/tab1' tables?

This is my code:

local funcs = {}
funcs.__index = funcs
function funcs:printName()
    print(funcs.Name)
end

local tab1 = {}
setmetatable(tab1,funcs)
tab1.Name = "Table1"
tab1:printName()

Thank you!

~TDP

2 comments

0

Try inserting 'Name = "Table1"' into the funcs table.

0

I have already tried something similar. I put 'ayy lmao' into the funcs table, and it just printed 'ayy lmao', even when I changed the name value after setting the metatable.

1 answer

✓ Accepted answer

__index metamethod

I think you kind of have the whole concept backwards between the table and the metatable. __index is invoked when a value that doesn't exist in the regular table, is indexed. So making __index point to the regular table when it's only invoked because it's not in the regular table, won't get you very far.

  • Overview

I think what you're trying to do, is make a regular table inherit some methods and properties the __index metamethod provides. First, you should define a table that will hold these methods and properties. Next, we'll assign a function to __index that will control what gets returned, and how.

  • self

Before we get into that, it's important to know how self works. self is a hidden variable that always holds a reference to the table the function is in, only if the function is indeed written as a method (i.e, using : instead of the standard . format). Acknowledging how this variable works is vital for understanding how to create custom methods.

  • Creating methods

So with all that out of the way, we can make a table that will hold the functions that our normal table will perceive as methods. We'll just call it methods, and we'll call our normal table tab.

local tab = {}
local methods = {}

This is where self comes in. Since __index will return functions from the methods table, we need to keep the returned function a method. We do this by returning a different function, that returns the called function from the table. It seems a bit confusing now, but looking at the code should clear things up a bit. So now let's set the metatable to tab.

local tab = {}
local methods = {}

-- I'll assume you know about using __index as a function, if not, the wiki explains it somewhat decently.
setmetatable(tab,{
	__index = function(t,k)

		-- Indexing "methods" for the key that it couldn't find in "t"
		local v = methods[k]

		-- If the value is a function, then...
		if type(v) == "function" then
		
			-- Return a new function, skipping the first
			-- parameter in place of self.
			return function(_, ...)
				return v(t,...) -- Now returning "t" as self, and "..." as the args.
			end

		end
	end
})

Now we've created a way in which __index will return a non-method formatted function, as a method. Keep in mind, this will mean every function you store in methods will have it's first parameter defined as the table.

Final product

The final product should look something like this:

local tab = {}

local methods = {
	printName = function(self)
		print(self.Name)
	end
}

-- I'll assume you know about using __index as a function, if not, the wiki explains it somewhat decently.
setmetatable(tab,{
	__index = function(t,k)

		-- Indexing "methods" for the key that it couldn't find in "t"
		local v = methods[k]

		-- If the value is a function, then...
		if type(v) == "function" then
		
			-- Return a new function, skipping the first
			-- parameter in place of self.
			return function(_, ...)
				return v(t,...) -- Now returning "t" as self, and "..." as the args.
			end

		else -- If not a function, then...
	
			return v -- just return the value.

		end
	end
})

tab.Name = "Hello"
tab:printName()

Questions?

This is a lot to take in if you're new to metatables. If you have any questions, I have a pretty good answer on how methods work here: https://scriptinghelpers.org/questions/28060/gamedestroy-a-thing

If you're still confused about anything, just let me know.

2 comments

0

Wow, this is pretty crazy! I seem to get it a bit, though. Thank you!

0

Glad it helped!

This discussion is preserved as it was. New answers, comments, and votes are closed.