Libraries+, a library extension module

That was what came out when (-1)^(1/3) operation was done.

1 Like

@Halalaluyafail3 and @TacoBellSaucePackets, thanks for the replies. I will remove it once i get back on my computer.

@Halalaluyafail3, could you explain table.move and table.create? I was actually trying to work with the former, as I haven’t used roblox and just Lua in general. The official Lua site doesn’t explain the second-fourth arguments, and there’s absolutely no documentation on them in the roblox developer hub.

1 Like

Some of these library extensions are useful as for some of my older code I wrote my own implementation for a feature I needed.

A few case examples are:

  • GetAncestors, getting a player instance from a partial segment of their username
  • Table Shuffle
  • A custom WaitForChildWhichIsA based off a simple repeat wait() until instance:FindFirstChildWhichIsA(...)
  • preforming operands on Color3 datatypes. (Why are Color3 operands not native in the first place like Vector operations!!)

Suggested Additions

Incase TL;DR
Add these:

  • math.root(number, nthRoot)
  • math.sumOfInteriorAngles(sides)
  • math.exteriorAngleOfRegularNthSidedPolygon(sides)
  • math.truncate(number, figure)

You should add a math.root function for general root operands. math.root(x, n) where x is the number you’re trying to find the nth root of. This can simple be done using something such as return x^(1 / n)

function math.cbrt(x)
	if x < 0 then
		return -((-x)^(1 / 3))
	end
	
	return x^(1 / 3)
end

Or a messier solution,

On the topic of root functions, you should be able to fix your math.cbrt by just using a simple if statement. If x < 3 then you should want to find the cube root of -x and then return the negative counterpart of the value of that expression.

I believe this works because x^(1/3) is symmetric about the origin. Therefore you could expect -(x^(1/3) to be equal to (-x)^(1/3)
image

There are also other geometrical functions you could add related to math.triarea. Perhaps a user might need to know the sum of interior angles in an nth sided shape math.sumOfInteriorAngles(sides)! Or how much each exterior angle is in a regular nth sided shape math.exteriorAngleOfRegularNthSidedPolygon(sides)!

I am also not aware of a function similar to math.truncate(number, figure). This could be used to well, truncate numbers. f(1.23456, 4)1.234

Other

Some of these functions seem useless such as tobool. With that I must add I think using was an interesting implementation that is based off abusing the fact that single parameters calls do not need to be wrapped in ().

I did something similar of what you did for using to create a very hacky language inside lua using brackets. if_then(expression) {ifTrueCallback, ifFalseCallback} Was just for funzies. It worked by returning lots of simple closures.

Here is an example code block!
local function if_then(evaluation)
    return function(input)
        local trueCallback = input[1]
        local falseCallback = input[2]

        if evaluation then
            return trueCallback
        end
        
        return falseCallback
    end
end

local function a()
    print"it's true"
end

local function b()
    print"it's false"
end

if_then(1 == 1) {a, b}

Overall I’m glad to see such a great community resource such as this one.

4 Likes

table.move is documented on the 5.3 manual.
https://www.lua.org/manual/5.3/manual.html#pdf-table.move
Equivalent to
a2[t],··· = a1[f],···,a1[e]
Default for a2 is a1
Returns a2

table.create was added by roblox, and creates an array with the size specified, with an optional argument for what to fill the values in with.
Creating the array with a specific size avoids preallocations.

1 Like
function cbrt(x)
    local a = math.sign(x)
    return (math.abs(x)^(1/3))*a;
end

This should work. Use this instead of x^(1/3)
1 Like

I suggest adding the sign function (sgn, sign, signum) as I use it quite frequently and I believe it would be a useful addition to write it down quicker.

Example implementation:

function math.sign(x)
    return x == 0 and 0 or x/math.abs(x)
end

Otherwise great resource I will see myself using.

Roblox has had this since May 2017!

https://devforum.roblox.com/t/new-lua-functions-math-sign-and-math-clamp/37309

6 Likes

I see a math.secant but no math.cotanent and math.cosecant.
You should add those two to the library, as well as document some hidden behavior the library extension preforms!

And you should probably continue to use the naming scheme ROBLOX uses for their trigometric functions and use the abbreviation as the name of the function instead. math.sec (secant); math.csc (cosectant); and math.cot (cotangent).

1 Like

This is a very nice module and all, but I really do not think this code belongs in there without any actual documentation about this behavior.

env.shared, env._G, env.table.foreach, env.table.foreachi, env.table.getn, env.string.len = nil -- nullify deprecated/discouraged

local old_wait = wait
env.wait = function(n) -- goodbye to while wait(n) do
	return false, (old_wait(n)) -- second return after the delta time seems pointless, so call is wrapped in () -- local _, dt = wait(n)
end

This has the potential to cause issues for people who may not know why certain things are not working correctly after implementing your module. I understand why you implemented this behavior, but not why you chose not to document it.

3 Likes

Hey thanks for pointing this out. Was actually trying to document that, but the forum wouldn’t save the edits. It would just be stuck on loading. But now the edits have been published!

2 Likes

I’m still working on this, but I’m at a point where I don’t know what else to add. So I came back here looking for ideas. If you have any, feel free to drop them below!

1 Like

Perhaps you could clean the way the module is setup? It personally for me is pretty hard to read. Perhaps add separate modules inside the main one that are inherited by it.

Somewhat like this, where each library is a child of the main module:

Main
 |_ Math
 |_ String
 |_ Instance
 |_ ... 

Perhaps iterate over the children to collect the modules. Something like this:

local _M = {}

for i, v in pairs(script:GetChildren()) do
    local name = v.Name
    local module = require(v)

    _M[name] = module
end

local function setupEnvironment()
    local callingEnv = getfenv(2)
    
    for i, v in pairs(_M) do
        callingEnv[i] = v
    end
end

return setupEnvironment
1 Like

Yup I was actually going to start making a separate project that used modules the “classic” way, but I’ll definitely split it into separate modules as that’s what they’re for.

1 Like

I got a chance to check some of it out.

WaitForChildOfClass = function(instance, class_name, timeout) -- Wait for a child of class
	if type(timeout) == "number" then
		wait(timeout)
		return instance:FindFirstChildOfClass(class_name)
	end
	while not instance:FindFirstChildOfClass(class_name) do
		instance.ChildAdded:Wait()
	end
	return instance:FindFirstChildOfClass(class_name)
end

This isn’t the intended functionality of ‘WaitForChild’. If given a Timeout, this will simply stall the entire time duration (ignoring any instances created in the intermission) and then spit-out an already existing Instance that fits the criteria. Check out this post on how you may actually implement this correctly. (Of course, substituting the now deprecated RbxUtility signal for a BindableEvent.)

1 Like

Update

_M no longer forces library injection.

Now how it should be used is

local import = require(_M)

And you can import the specific libraries you want, e.g.

import("table")

will import the table extensions.

It can be called with multiple arguments, so

import("table", "math", "string") 

Gives that python feeling.

That will import the extensions for table, math and string.

using has been changed to import. All of this is now documented in the OP!

@EpicMetatableMoment the module now contains submodules and it should be easier now!

@AskWisp The function has been implemented correctly now!

2 Likes

Good Work!

This looks much cleaner!

image

Other things you could change:

  • Type Checking
  • Update Math Functions
  • Update Color3 Functions
  • Update Incapaz Specials

Type Checking:

Add type checking with the new lua demo? (Of course if you do this please create a separate version of the module as the type checking is not enabled on the server / client)

Update Math Functions

I still see no math.cosecant and math.cotangent, also a math.nroot would be nice; easily implementable via (replace the 3 with n):

On the note of Brendan’s post, you should update the math.cbrt to use his (in my opinion) cleaner method of doing this.

Update Color3 Functions

This is assuming people use Color3.fromRGB rather than Color3.new (in which case Color3.new is being used by the function internally, perhaps change this to ValueError: new RGB component is over 1) or alternatively just use clamp and not spit an error?.

Update Incapaz Specials

Perhaps use a quick variable for _M.printf?

_M.printf = function(s, ...) -- C's printf
    print(s:format(...))

    return #s:format(...)
end

The extra s:format(...) is not needed and could be removed with a simple variable declaration.

Overall, very cool!

image

2 Likes

incapaz_specials formatting was fixed.

I will be making a separate project that doesn’t do any library injection that uses the “classic” way of requiring in the future which will use typed Lua once it is ready. It’s been really unstable rn and so many bugs. Like I can’t even use ipairs(table.pack(...)) without it complaining I need to call it as a method with the : and that the types mismatch.

let me be honest here bro i don’t know anything about math. A friend was using Lua for his math homework or something and he asked if there was a way to use secant. And I asked “what is the formula” and he said it was 1/cos(n) so I made a function that easily did that.

But I did add that root function. Should I remove cbrt since root is added?

2 Likes

No, you don’t need to remove the cbrt function.

Also, cosecant, secant, and cotangent are just the reciprocal of their respective counterparts.

cosecant (csc) = 1 / sin(x)
secant (sec) = 1 / cos(x)
cotangent (cot) = 1 / tan(x)

Yes, type checking currently is pretty botched. That is why I suggested a separate module / project for it because it is annoying to work with for one, and two it is not enabled ingame.

1 Like

Hey! I wanted to share something that I’ve been working on for some time. I forked Libraries+ (before the update you just released, and it is up-to-date). If you are interested, I can share what I added.

1 Like

Here is the link to the Libraries+ fork. I added some functions to it. I did move some functions around (such as pathtostring is now in Rbx_Instance, etc.)

I added Roblox-created libraries, such as Symbol, and cryo.

I changed the main module to be a table with a __call metamethod. I added a function called GetLibraries which gets the Libraries without importing (there’s also the __index metamethod doing its own stuff with retrieving libraries)

It’s probably not much, but here it is:
https://www.roblox.com/library/4557280035/LibPlus-Fork

4 Likes