How could I improve this function?

Hi! As a small project I made a function that converts a string into a TweenInfo. It supports all parameters, you can enter as many or as few as you want (as long as they are in order), and it supports decimals. It works perfectly fine from my testing, but I’d like to know if I can clean it up at all since it’s a lot of repeated code. Thanks
Function:

local styles = {
        ["ba"] = Enum.EasingStyle.Back,
        ["bo"] = Enum.EasingStyle.Bounce,
        ["ci"] = Enum.EasingStyle.Circular,
        ["cu"] = Enum.EasingStyle.Cubic,
        ["el"] = Enum.EasingStyle.Elastic,
        ["ex"] = Enum.EasingStyle.Exponential,
        ["li"] = Enum.EasingStyle.Linear,
        ["q1"] = Enum.EasingStyle.Quad,
        ["q2"] = Enum.EasingStyle.Quart,
        ["q3"] = Enum.EasingStyle.Quint,
        ["si"] = Enum.EasingStyle.Sine
    }
    local directions = {
        ["i"] = Enum.EasingDirection.In,
        ["o"] = Enum.EasingDirection.Out,
        ["io"] = Enum.EasingDirection.InOut
    }

    local time = string.match(str, "^%d+") or ""
    str = string.gsub(str, time, "", 1)
    if string.find(str, "^%.") then
        local timeDecimal = string.match(str, "^%.%d+")
        time = time .. timeDecimal
        str = string.gsub(str, timeDecimal, "", 1)
    end

    local style = string.match(str, "^%a%w") or ""
    str = string.gsub(str, style, "")
    local direction = string.match(str, "^%a+") or ""
    str = string.gsub(str, direction, "")
    local repeatCount = string.match(str, "^%d+") or ""
    str = string.gsub(str, repeatCount, "")
    local reverse = string.match(str, "^%a") or ""
    str = string.gsub(str, reverse, "")
    local delayTime = str

    time = tonumber(time) or 1
    style = styles[string.lower(style)] or Enum.EasingStyle.Quad
    direction = directions[string.lower(direction)] or Enum.EasingDirection.Out
    repeatCount = tonumber(repeatCount) or 0
    reverse = string.lower(reverse) == "t" and true or false
    delayTime = tonumber(delayTime) or 0


    return TweenInfo.new(time, style, direction, repeatCount, reverse, delayTime)

Thank you!

I don’t see how this could be beneficial to code readability.

An outside user is not going to understand bai2.4

A tween wrapper is fine, but having shorthand dictionaries seems unnecessary.

3 Likes

Yeah, it’s more for myself than anything. I was tired of seeing almost identical tweens with slight differences that made me have to scroll my code.
Also, what’s bai2.4?

From what I am understanding, it would be back, in, 2.4 seconds TweenInfo.

See how it is already confusing?

1 Like

Oh, I thought that was something else entirely XD
In this, it would be 2.4bai, but I understand.

I believe this in itself is enough evidence that what you’re doing is confusing, if even you (the creator of the module) was confused. It seems like an attempt to create a solution for a non-existent problem.

1 Like

If you assume that the string is seperated by commas like this:

local info = "1, ba, i, 5, t, 0"

Then you can just remove the spaces with :gsub() and then split based on the commas using :split()

local info = "1, ba, i, 5, t, 0"
local splits = info:gsub("%s", ""):split(",") -- %s removes all spaces.

local duration = splits[1]
local style = splits[2]
local dir = splits[3]
local repeats = splits[4]
local reverses = splits[5]
local reverseDelay = splits[6]

You can even take it a step further by using unpack.

local info = "1, ba, i, 5, t, 0"
local splits = info:gsub("%s", ""):split(",") -- %s removes all spaces.
local duration, style, dir, repeats, reverses, reverseDelay = unpack(splits)

You will still need to do checks to make sure people dont put in strings for numbers but this can be a good base to start off.

Yeah, that’s completely fair. The main reason I was confused is because the example they were using wouldn’t be valid in the system.

It basically is. I was being nitpicky cause I had to look at
TweenInfo.new(0.5, Enum,EasingStyle.Quad, Enum.EasingDirection.InOut) on like a billion different lines with a different time parameter.

The reason I coded it how I did was to teach myself how to use some of the string specifiers, since I knew nothing about them prior.
That’s mainly why I’m asking for code review.

If you’re needing to create multiple TweenInfo with a different time you could just create a little helper function that can supply default args.

local function createTween(time: number, style?: Enum.EasingStyle, direction?: Enum.EasingDirection): TweenInfo
	return TweenInfo.new(time, style or Enum.EasingStyle.Quad, Enum.EasingDirection.InOut)
end

createTween(3)

I did this at first, but then I thought I make it work with anything and teach myself string specifiers at the same time

I reccommend using string.gmatch for that instead, and you can create a string pattern from there

1 Like

Oh, so I could get rid of all of the str = gsub lines? That’s super helpful
Edit: Just did that, it is so much easier to read. Thanks, I didn’t know gmatch existed!

2 Likes

You can use a loop to iterate over a table that defines the order of the parameters and the type of the parameter. Then, you can use a function that extracts the value of a specific type from the string, which will be called for each parameter.

local styles = {
[“ba”] = Enum.EasingStyle.Back,
[“bo”] = Enum.EasingStyle.Bounce,
[“ci”] = Enum.EasingStyle.Circular,
[“cu”] = Enum.EasingStyle.Cubic,
[“el”] = Enum.EasingStyle.Elastic,
[“ex”] = Enum.EasingStyle.Exponential,
[“li”] = Enum.EasingStyle.Linear,
[“q1”] = Enum.EasingStyle.Quad,
[“q2”] = Enum.EasingStyle.Quart,
[“q3”] = Enum.EasingStyle.Quint,
[“si”] = Enum.EasingStyle.Sine
}

local directions = {
[“i”] = Enum.EasingDirection.In,
[“o”] = Enum.EasingDirection.Out,
[“io”] = Enum.EasingDirection.InOut
}

local params = {
{“time”, “number”},
{“style”, “string”, function(str) return styles[str] end},
{“direction”, “string”, function(str) return directions[str] end},
{“repeatCount”, “number”},
{“reverse”, “boolean”, function(str) return string.lower(str) == “t” end},
{“delayTime”, “number”}
}

local function extractValue(str, param)
local value = string.match(str, “^%S+”)
str = string.gsub(str, value, “”, 1)

if param[2] == "number" then
    value = tonumber(value) or 0
elseif param[2] == "boolean" then
    value = param[3] and param[3](value) or false
elseif param[2] == "string" then
    value = param[3] and param[3](value) or value
end

return str, value

end

local function stringToTweenInfo(str)
local paramsCount = #params
local tweenInfoParams = {}

for i = 1, paramsCount do
    str, value = extractValue(str, params[i])
    table.insert(tweenInfoParams, value)
end

return TweenInfo.new(unpack(tweenInfoParams))

end