Dual-syntax method with single parameter; any issues in doing this?

At the moment, I am currently creating a library loading system to streamline my development. I did write it myself however I referenced quite a bit from Nevermore so it looks pretty much the same, just with the lack of any OSS components. The second part of this paragraph is irrelevant, just wanted to give background.

Currently, I am trying to make a method that is intended to load a library. However, even though it’s not quite OSS, I ended up writing a way to catch if the method is indexed either from dot or colon syntax, which means I can call it either way.

LibraryLoader.LoadLibrary = function(self, libraryName)
	local libraryName = self and libraryName or self
    warn(libraryName)
end

LibraryLoader.LoadLibrary("ABTest") --> ABTest
LibraryLoader:LoadLibrary("ABTest") --> ABTest

Is there anything inherently bad about doing this? I was just playing around with some code and found that this works. Almost certain I won’t keep this in, though for the sake of knowledge I’d like to know what the pros or cons of doing this are, either from a technical or usage standpoint (public or private usage).

You shouldn’t run into problems for this basic case, but it may become more bloated when you need to add parameters, or just have multiple parameters at the start. As an example, here is how it may look for 3 parameters:

LibraryLoader.Method = function(self,Argument1,Argument2,Argument3)
	local Argument1 = Argument3 ~= nil and Argument1 or self
	local Argument2 = Argument3 ~= nil and Argument2 or Argument1
	local Argument3 = Argument3 ~= nil and Argument3 or Argument2
end

This example will also not work if the last parameter or parameters is nil. You may be able to work around this, but it may not be worth it.

2 Likes

Catching self itself isn’t worth it at all and I just happened to write this while creating the LoadLibrary method. Considering it’s not intended to be OSS, tailoring it as such wouldn’t make much sense.

That being said, nice to hear that there aren’t too many problems with it. Single-parameter methods check out but I don’t think I’d ever attempt this with multiple parameters.

So I was checking it out, and turns out you only need “self or libraryName”. The reason is that boolean operators work with something called “short circuit”. The “a and b or c” is a fake ternary, but it’s totally irrelevant and not doing it’s full function in your example.

So regardless of which of the two ways you call your function, self will ALWAYS have a value, and the second parameter, libraryName, could be the string you pass or Nil.

Then, the ternary you have does the next two steps in sequence:

Check if self is false or nil. self is Absolutely Always something (when you call with colon, it’s the object, when you call with dot, it’s the string. So then, BASICALLY, it becomes “true and libraryName”. Here is when the shortcut kicks in: When you have “and”, if the first value is NOT FALSE OR NIL, it will always, basically, be replaced with the second value. Try it out: local a = true or 2. a will be equal two.

So then your line sort of becomes “libraryName or self”, and that’s where the magic happens. libraryName can be nil if you call it with the dot and a single parameter, and then the or short circuit does it’s thing: or basically becomes the second term if the first one is false or nil. The opposite of the and. So if libraryName is nil, it’ll become self. If libraryName is not nil, it’ll continue being libraryName.

Technicalities aside: It is fine to “overload” your function in such way, except for the case someone commented where you have more parameters and then you’d have to sort of slide them all back:

function overload(self, par1, par2, par3)
local initialVal = par3 --We’d lose the initial nil if we replace the parameters in the right order:
local par3 = initialValor par2
local par2 = initialVal or par1
local par1 = initialVal or self
end

You could also just call the function and slide the parameters:

function overload(self, par1, par2, par3)
if par3 == nil then
return overload(nil, self, par1, par2)
end
end
From @ElectricAxel !

2 Likes

The information is appreciated and I’ll remember this in the future when working with ternary (I use a and b or c in most of my ternary operations and use short circuiting in other circumstances), however this is isn’t fully relevant to the question I asked. It’s simply an alternative way to write what I have in my method, it doesn’t answer my question otherwise.

Yes but this looks relatively ugly and the module isn’t intended to be OSS, so it doesn’t have much use for me. I’ll note this for the sake of knowledge but I most likely won’t ever use this to catch parameters. If I’m making OSS, then the end user should be using it the way it’s documented rather than me trying to cover for improper usage (instead, I throw warnings or errors).

1 Like