Quick Tip to organise your code: Functions

Yes, I’ve changed the colors for easier understanding

Instead of:

if runFunction then
	func1("Cat", "Apple")
else -- Of course, func2 will run in this example
	func2("Cat", "Apple")
end

Yes, you can also change the args if you want

7 Likes

If you ever feel useless, just remember that this exists.

5 Likes

This isn’t useless :sob:, I didn’t know you could do this

8 Likes

This is great if you want to make your code less optimal and readable

2 Likes
local Function = runFunction and func1 or func2;
Function(...)

Still bum way of doing it btw

1 Like

Yeah but its kind of a waste of space to store it in a variable (it’s also weird) + it’s made out of 1 more line (which is illegal here)

2 Likes

This is a lot better than what was proposed. It’s immediately obvious at a glance what this code is doing. Your shortened version is not more organised; it’s just shorter.

3 Likes

I mean I think it’s better because:

  • I use these things a lot (true and 1 or 2), so it looks better for me at least
  • +2 points it’s only 1 line
  • +1 point exploiters might be confused if they see that

That’s just my opinion, use it if you want. Just know it exists :fire:

That’s what conditional (ternary) operators are for. You can use them for assigning properties…

local part = path.to.part
local state = true

--> 2 different versions of using conditional operators
part.Name = state and "Name1" or "Name2"
part.Name = if state then "Name1" else "Name2"

Also this does not affect the performance.

I’m not referring to ternaries, I’m referring to picking a function to execute using an inline ternary. It makes it less clear what it is actually going on.

Then this should be better:

local function func1(...)
  warn(...)
end

local function func2(...)
  warn(...)
end

local function _Execute(state: boolean)
  return state and func1 or func2
end

_Execute(false)("Cat", "Apple") 

Or…

if runFunction then
	func1("Cat", "Apple")
else -- Of course, func2 will run in this example
	func2("Cat", "Apple")
end

:woman_shrugging:

1 Like

you should look into TypeScript’s compiler; also using your version is better only for functions used once, but when you want to use it often, what I did is better.

I mentionned TypeScript’s compiler because it does the same thing if I don’t say anything

RobloxTs compiler is garbage and produces heavily unoptimised code

Did you even try it? Since the compiler is one of the best i’ve ever seen. Not about organisation but optimisation.

I have. Its opensource. They dont even attempt to do any optimisation. For example, there is zero reason to generate a whole metatable just for an enum

cc @Pcoi94

You’re missing the point that @grilme99 is making and shifting your own point in the process. Any discussion of performance (in the context of this point) is meaningless — this isn’t a performance question and neither approach has any significant performance effect (Pcoi makes this point). This is 100% about readability and organization. You should not consider it a good thing (+2 points) to condense things to one line. Security through obfuscation or poor code design is also not a real defense against exploiters. Good organization facilitates a good understanding of what the code is doing and good base for expanding the direction of the code (this approach impedes both of those)

In-line ternaries (in this context) obstruct readability. It forces you to have pause and waste time figuring out what the line of code is actually doing. Even if you understand what’s going on, that’s probably author bias. You wrote it. Someone picking up your code (a team member or yourself revisiting an old project) is not going to get what’s going on at a quick glance.

That’s not good; ideally code reads like plain English. To mitigate this problem, you need at the very least a lengthy comment breaking down what’s happening - which is basically just going to result in a plain-text conditional tree)

Furthermore, this approach not realistically scalable. Adding more conditions complicates the logic.

Consider this, right:

local NextModeIsFreeForAll = true --// Mode only available in non-matchmaking servers
local MatchmakingActive = true
local PartiesDetectedInGame = true
local PartyPlayDisabledByHost = true

local function AssignTeamsBasedOnElo()
	print("Elo matchmaking")
end

local function AssignTeamsRespectingParties()
	print("Parties respected")
end

local function DoNotAssignTeams()
	print("Everyone for themselves")
end

local function RandomlyAssignTeams()
	print("Random teams")
end

if MatchmakingActive then
	AssignTeamsBasedOnElo()
else
	if NextModeIsFreeForAll then
		DoNotAssignTeams()
	elseif PartiesDetectedInGame and not PartyPlayDisabledByHost then
		AssignTeamsRespectingParties()
	else
		RandomlyAssignTeams()
	end
end

It’s a very simple system for a round-based game. I wrote the logic quickly, and it’s should be clear enough to anyone reading my code what is going on.

Now, consider replacing my conditional tree with:

(MatchmakingActive and AssignTeamsBasedOnElo or (NextModeIsFreeForAll and DoNotAssignTeams or ((PartiesDetectedInGame and not PartyPlayDisabledByHost) and AssignTeamsRespectingParties or RandomlyAssignTeams)))()

That’s infinitely harder to understand what’s going on. Again, it’s not scalable. Depending on how you want to tweak the logic (ex: adding a new match condition) you might just have to rewrite the entire statement.

2 Likes

Yes you’re right. I posted this only so you guys know about it (in case you didn’t ofc). Still, I’m a solo dev and I use this a lot, so I’m very used to this. I agree that most people would need to pause to look at it, and it can be a bit confusing for others.

:fire: Just so you know, it is a thing :muscle:

Edit: It should not be used with a large conditional tree, I mean even the auth wouldn’t be able to read it after a few days (probably)

you’re totally right about this

The readability of a script change between developers

Yeah, Anyone can just ask an ai what does that mean.

For a second time, it depend of the developer

You’re right on that, but what you can do is using Enter key so it should look like this:

(
MatchmakingActive and AssignTeamsBasedOnElo 
  or (NextModeIsFreeForAll and DoNotAssignTeams 
  or (
    (PartiesDetectedInGame and not PartyPlayDisabledByHost) and AssignTeamsRespectingParties 
    or RandomlyAssignTeams
  )
)
)()

This should be more readable but it can be better; of course nobody (or pratically nobody) use a ternary condition of this quantity. But you can do something like this:

-- don't forget it's an example.
local TweenService = game:GetService("TweenService")

local function foo1(n: number)
      return Vector3.new(n, n, n)
end

local function foo2(n: number)
      n ^= 2
      return Vector3.new(n, n, n)
end

local part = ...
local state = false
local size = 2

TweenService:Create(part, TweenInfo.new(0.5), {
    Size = (state and foo1 or foo2)(size)
}):Play()