How Do I Nest Functions Inside A Module Script

Ok so this might be confusing. Im not sure how to word it but basically I want to nest functions in other functions in a module script. So i have 3 functions here

Screen Shot 2023-02-05 at 10.50.38 PM

I want Rotate and Rocks to go inside of the Orb function but everytime I do that it throws an error because the script im requiring the functions on is not detecting the rotate and rocks function only the orbs function.

In short im asking how to nest functions in a module script

1 Like

Why do you want this? Why are you putting functions inside of functions if you’re also intending to call them externally?

1 Like

You could use OOP for this, but I’m not sure about the “Putting functions inside functions” as they are basically already in a table, and putting them inside each other defeats the purpose of reusable, unless you mean this:

function Global() -- First function (Global)
    local function Local() -- Local Function
3 Likes

Im making client side VFX.

So basically here is another Module script i have in the serverscriptservice (ignore the red lines at folder I already fixed that)

Screen Shot 2023-02-05 at 11.05.02 PM

this module script is passing arguments to my other module script

I want to do this is because im trying to make it so when you shoot a fireball and the fireball touches something a VFX plays:

sorry for the bad video but the idea is when the fireball hits something the VFX(Rotate) and Rocks
function plays. I miss a few times at the beginning but eventutally it works

but i keep getting a attempt to call nil value because the module script i passed the arguments in isnt detecting the Rock, nor Rotate function

also ignore the yellow circle you see at my mouse thats my video recorder doing that for some reason. Sorry its a new video recorder im testing out.

For the First Image you are basically creating threads, It is important to note that spawn is deprecated and should be replaced with task.spawn()

Second Image is an Array of functions, nothing important

For your last image, there is a reason you use OOP for this, instead of you adding functions to functions, Here is a Basic Example of OOP:

local module = {} -- Module table
module.__index = module -- metamethod (important if you want to fire module functions)

function module.GetSomething()
    local self = setmetatable({}, module) -- creates metatable (aka stronger table)

    self.Something = "string" -- index within metatable (important)

    return self -- returns metatable
end

function module:PrintSomething() -- different function operator
    return print(self.Something) -- self is already specified, no need to add any specification
end

return module -- returns table

Script:

local mod = require(module) -- Module

local Something = mod.GetSomething() -- Gets metatable from function

Something:PrintSomething() -- "string" (self was specified)

You can look at Documentation for metatables + metamethods here


Plus, I think Using OOP is a lot better than this:

function module.MoreFunctions()
    local Array = {}

    function Array.Thing()
        print"Hi, Why are you doing this???"
    end)
    -- this is basically a module INSIDE a module
    return Array

end

or this:

function Global()
    local function Local()
        print"why???"
    end
    return Local
end
3 Likes

am assuming you wanna do this
local new = SpinVFX.Orb(arg)
new.Rotate(arg)
new.Rocks(arg)

if that’s the case then
there are a few ways
one is this way

local SpinVFX = {}

function SpinVFX.Orb(arg)
    -- do stuff here
    local new = {} -- table to store functions of SpinVFX.Orb, can add properties of "orb" into table (e.g. Size = Vector3.one; CFrame = CFrame.identity), you can do custom properties too like "Instance = (actual orb instance here)"want to
    function new.Rotate(arg)
        -- rotate func
    end
    function new.Rocks(arg)
        -- rocks func
    end
    return new -- return the function
end

return SpinVFX

the other way is this way (no idea how to explain, looks fancier tho)

local SpinVFX = {}
local Orb = {} -- contain functions of SpinVFX.Orb

function SpinVFX.Orb(arg)
    -- do stuff here
    local self = {
        -- properties of "orb" here (e.g. Size = Vector3.one; CFrame = CFrame.identity), you can do custom properties too like "Instance = (actual orb instance here)"
    }
    return setmetatable(self, {__index = Orb}) -- this thing, no idea how to explain without it being overly complicated
end

function Orb:Rotate(arg) -- ":" instead of ".", now it's basically same as Orb.Rotate(self, arg)
end

function Orb:Rocks(arg)
end

return SpinVFX
1 Like

Some people would say to do self.Ex = "" rather than:
self = { Ex = "" }
Usually so you can access another index, plus doesn’t require commas or semi colons.

self = {}
self.Number = 123912312
self.concat = "Number_"..self.Number -- works
self = {
Number = 123912312;
concat = "Number_"..self.Number; -- does not work
concat = "Number_"..Number; -- doesnt work either
concat = "Number_"..self[Number]; -- neither does this
}
1 Like

Ok so far I have:

Now its throwing a error on my local script saying “Attempted to call require with invlid arguments” - Line 10
image

Im confused :sweat_smile:

You cant just require() a module by its name, you have to do it by instance.

Plus, I dont see the purpose of you doing it in a table

2 Likes

You can do this. Its complaining probably because you’re trying to say an inner function also belongs to an outside table, which isn’t allowed. What you want probably looks like this:

local staticLikeProperty = 2

function Orb()
    local orb = {}
    local privateLikeProperty = 5
    orb.publicLikeProperty = 10

    function orb:MyOrbFunction()
        return self.publicLikeProperty + privateLikeProperty + staticLikeProperty
    end

    return orb
end

I also use this pattern and it works a lot better than metatable based OOP.

You can then call MyOrbFunction like a member function:

local newOrb = Orb()
newOrb:MyOrbFunction() --newOrb will be implicitly passed as 'self'

Statements inside MyOrbFunction can access both members of the orb table, and local variables in Orb() which will be different for each object returned by calls to Orb(), you can use this feature to make some parts of your object effectively private. You can also access variables in the scope above Orb(), and those will be shared between all Orbs, so they can act as static.

1 Like

I did show an example which is what I put in the second post at the bottom, however its just my opinion so you dont have to take my word for it.

1 Like