How to call a function without passing variables into function arguments

So I was making some combat system and I want to keep the script simple as I can. I wonder If you can create a function without passing an arguement. It’s kinda unsimple adding a variable and pass them into function’s arguement. Here’s an example.


local function callSomething()
      print(a,b,c) -- Expecting to print out "1 hi true"
end

game.Players.PlayerAdded:Connect(function()
       local a = 1
       local b = "hi"
       local c = true

      callSomething() -- Expecting to call "callSomething" function without an error
end)

Any solution?

5 Likes

That is not gonna work unless the variables are not local to the PlayerAdded listener or you don’t have any perimeters.

local a = 1
local b = "hi"
local c = true

local function callSomething()
      print(a,b,c)
end

game.Players.PlayerAdded:Connect(function()
      callSomething() 
end)
7 Likes

Parameters are necessary for a function if some data is needed to pass into the function, unless there are already global variables that are directly accessible in the function.

4 Likes

Arguments & parameters are in no way complicated; you should not try to work around them. This is the most efficient and practical method for providing information to a function at runtime. For more information on this, you can read my reply to another post

6 Likes

Either


local function callSomething()
      print(a,b,c) -- Expecting to print out "1 hi true"
end

game.Players.PlayerAdded:Connect(function()
       local a = 1
       local b = "hi"
       local c = true

      callSomething(a, b, c) -- Expecting to call "callSomething" function without an error
end)

or

local a = 1
local b = "hi"
local c = true

local function callSomething()
      print(a,b,c) -- Expecting to print out "1 hi true"
end

game.Players.PlayerAdded:Connect(function()
    callSomething() -- Expecting to call "callSomething" function without an error
end)

5 Likes

This is known as using upvals, its generally not a good idea because it creates messy state relationships.

Another potential idea is using a closure by capturing the variables beforehand, this effectively gives you a similar approach but encloses the state to that function.

local function capture(a, b, c)
  return function()
    print(a, b, c) --> a, b, c from capture call
  end
end

Though, if you know the arguments ahead of time, just pass them into the function.

4 Likes

I understand that It won’t work for some reason. But the fact that it’s annoying to make alot of arguments and makes the script more messier. And those arguments are something that I need for using in event,signal, or if statements. Something like

local function (Char : Model,EnemyChar : Model,Block : BoolValue,Parry  : BoolValue,Hit  : BoolValue,Sprint  : BoolValue, ...) 

end

and I have to set the variables into the function’s parameter in order

3 Likes

You can mitigate long-winded function signatures by removing unnecessary whitespace, new-lining, or packaging parameters into a dictionary, similar to how RaycastParams is used. You can see an example of that in my KillsService module with the “DamageParameters” type

4 Likes

It doesn’t work because the variables and the function are defined in two different scopes

4 Likes

You can declare the variables without the keyword “local”, in this case:

local function callSomething()
      print(a,b,c) -- Expecting to print out "1 hi true"
end

game.Players.PlayerAdded:Connect(function()
       a = 1
       b = "hi"
       c = true

      callSomething() -- Expecting to call "callSomething" function without an error
end)

This way they are declared as global variables and can be used anywhere within the script. I don’t recommend doing this often though.

4 Likes

https://create.roblox.com/docs/luau/variables

“but it’s almost always better to create them with local scope because Luau accesses local variables faster than global ones”

Generally, you should never be writing global variables. The above is a statement from Roblox against them. If you want to make a global variable, forward-declare or initialize that variable at the top of your script. You can justify this practice further as it provides insight into all the globally-accessed variables that will appear and be utilized throughout the script. Allowing yourself to declare global variables at any point in your script makes it hard to track down their origins and know what information is available

4 Likes

You don’t need to use Typechecking if it is a private system that won’t be used by anyone else than yourself, or if theses arguments are guaranteed to be either nil or the expected type/object.

In your case, using a Table to send a bunch of informations between functions, events and scripts would be easier as it require a single argument and no table order is required to do whatever you need to do.

local FightDatas = {}

FightData.Char = --Model
FightData.EnemyChar = --Model
FightData.Block = --BoolValue
FightData.Parry = --BoolValue
FightData.Hit = --BoolValue
FightData.Sprint = --BoolValue

local function Something(DataTable) 
    if DataTable.Char and DataTable.EnemyChar then
        --Example
    end
end
Something(FightDatas) 
2 Likes

Typechecking is not restricted to code that is localized. Its advantages should be used at every opportunity. You can create a type for the parameter table to preserve what OP had before without continuing to lengthen the function signature beyond reasonable limits

2 Likes

I think it mostly comes down to a personal preference. Personally, I don’t see the point of using type checking when the variables, arguments, or whatever else are guaranteed to be either nil or the expected type/instance. It just increases the code length and, in some cases, makes the code less readable without providing real benefits.

2 Likes

Type analysis grants you greater control over how your code is read and interpreted by the Script Editor since you define what each variable should be read as, and can directly enforce what functions should return.

Not to mention it gives you the gift of autocomplete since variables and parameters are defaulted to “any” which doesn’t describe what the variable is supposed to be.


Examples:

-- Type analyzer

type T = { bar: number, key: "value" }

local function foo(t: T)
   t.ba --> 'bar' autocompletes with the given correct type
end
-- No type analyzer

local function foo(t)
  t.ba --> 't' is read as 'any' so it doesn't give you any information about the variable, forcing you to remember what it is
end

Another example:

-- string autocomplete

type Modules = "ProfileService" | "DataStore2" | "TopbarPlus"

local function loadModule(name: Modules)
  --...
end

loadModule(" --> gives you autocomplete options for each of the defined modules, similar to how typing game:GetService() gives you names for every service

It’s true that you don’t need type analysis, but there’s a reason why languages like TypeScript exist

2 Likes

Yeah, I know that it provides autocomplete, but it’s more of a quality-of-life improvement for coding than something else. It would be much more necessary when working in a team compared to working alone, where you already know what is what and what should be there.

2 Likes

The point is that you can’t guarantee that; at some point, yourself, or someone, will make make a mistake with yours or Roblox’s API. Luau still lacks real type enforcement, and some of these mistakes can go unnoticed with potential polymorphic relationships with the faulty data and the code. These mistakes can cause deep-rooted bugs which are difficult to tedious to resolve. Typechecking can catch this nature of mistake prematurely. Even if the mistakes are trivial, it still saves you and others time.

Types can be complex, by they don’t make the code they’re used in any less readable. Roblox has strong inference as well, so not everything needs to be explicitly typed, allowing the additional code length to be negligible. Furthermore, the annotations used can enable extremely powerful technologies like IntelliSense

Annotations can help say more with less code, which is very powerful in team and solo contexts

2 Likes

If you stop a project for 4 months, then return to it, you’ll likely forget some core components (i.e what goes where, what returns what).

It’s just better to save yourself the trouble now than later

2 Likes
local function callSomething(...)
      print(a,b,c) -- Expecting to print out "1 hi true"
end

game.Players.PlayerAdded:Connect(function()
       a = 1
       b = "hi"
       c = true

      callSomething() -- Expecting to call "callSomething" function without an error
end)

u can make globals or use …

2 Likes

Alright! Thanks for the more detailed explanation of the uses of type checking.

I almost never stop a project for that long. However, I usually leave useful comments on reusable systems so I’m not lost when going back to them.

2 Likes