Modifying "self" from a function in a ModuleScript doesn't change self?

I’m trying to code a system for my game, and I’m encountering an error that goes like this.

Let’s say I have a ModuleScript in ReplicatedStorage, with script as follows:

local module = {}

function module:F()
    self["A"] = 2

    print(self) --prints { ["A"] = 2, ["F"] = function }
end

return module

A server script then loads the module with code as follows:

require(game.ReplicatedStorage.ModuleScript):F()

Now, the problem is, running the following code in the console AFTER the script above ran, prints nil.

print(require(game.ReplicatedStorage.ModuleScript)["A"])

And running the following code in the console prints { [“F”] = function }.

print(require(game.ReplicatedStorage.ModuleScript))

Why does Module[“A”] suddenly disappear? How should I modify the module so that the first command prints 2 and not nil?

I think you’ll also have to return self so it’s set to the function. Or set self to a meta table and make a variable called A and set it to 2. and make a method to print it.

Oh wait, When you run it through the console, you first have to run the function, like in a normal script. Otherwise it’s going to return nil because it can’t find any value in the function.

this works:

require(game.ReplicatedStorage.ModuleScript):F() print(require(game.ReplicatedStorage.ModuleScript)["A"])

this doesn’t:

print(require(game.ReplicatedStorage.ModuleScript)["A"])

Requires are not cached. You need to declare it as a variable first because everytime you use require, it creates a new object from that module.

Use this code.

local module = require(game.ReplicatedStorage.ModuleScript)
module:F()
print(module.A)

If you run this straight in the command bar, it will print 2 because its referencing the module as a variable.

local module = {}

function module:F()
    self["A"] = 2

    print(self) --prints { ["A"] = 2, ["F"] = function }
end

module:F()
print(module['A'])

@JAcoboiskaka1121 Thanks, I got a better explanation from another guy from Discord, who said it’s because requiring the module script in the console re-runs the module.
For example, if you have

local module = {}
print("ran")

function module:F()
    self["A"] = 2

    print(self)
end

return module

Running require(game.ReplicatedStorage.ModuleScript):F() in a script will print

ran
{ ["A"] = 2, ["F"] = function }

Running print(require(game.ReplicatedStorage.ModuleScript)["A"]) in another script will print “2” as expected.
However, running print(require(game.ReplicatedStorage.ModuleScript)["A"]) in the console is like running a script in a different actor, resetting the module to { ["F"] = function }. You can see it prints ran again upon requiring the module in the console for the first time. Therefore, you need to re-call module:F() in the console for it to register.

TL;DR: running code in the console is like running a script in a different actor, which resets the module.

1 Like

Very detailed explanation, anyway good thing its fixed.

Did you seriously not read what I just wrote above, let alone try it. The code actually works because I tested it. This is basically what I said except complicated. Modules aren’t cached; they do not come from the same environment as the module script instance itself. When you require it, you basically create a separate environment.

At least acknowledge what people write to help you because they took time themselves to figure out a solution for you.

1 Like

You are very confident of an incorrect and misunderstood behavior of ModuleScripts.

  1. Required values are cached, but only for that environment, and “setting a module to a variable” to manually “cache” it simply wrong.
-- ModuleScript
return {}

-- Script
print(require(script.Parent))
require(script.Parent).foo = "bar"
print(require(script.Parent))

image

  1. The reason why the behavior happens is that studio command line is actually a separate environment from the server, therefore not sharing the same cached value.

It took 30 seconds max to confirm this. Drop the ego.

2 Likes

That is literally what I said, it’s only from the same environment. Here he is using Object Orientated Programming, and is where you need to declare it as a variable.

Does it really matter? Its fixed now.

No, it’s my bad for carrying this on. I just hate when people write solutions and aren’t acknowledged.