I'm trying to wrap functions with a function for protection purpose.
My Code:
function Lib()
function self:foo(x, y) return x+y end
function self:goo(x, y) return x-y end
end
print(Lib():foo(3, 2))
I expect to get 5 but I get the following error.
attempt to index a nil value (global 'self')
What is wrong with my code and how to fix this?
ADDED: Can anyone compare this with using Lib = {} instead? I'm considering to wrap functions with a function since writing self: is easier to maintain than writing Lib. which can be changed later. I wonder if my idea makes sense.
EDITED: Okay, I just found out this works.
function Lib()
function foo(x, y) return x+y end
function goo(x, y) return x-y end
return self
end
Lib()
print(foo(3, 2))
But I don't understand why. Can't functions inside a function be protected?
P.S: I'm sorry if my question is stupid.
Functions are values that are created when function definitions are executed. Any variable can reference a function value.
So, although a function definition might inside another function body, the function value it not inside the function. It is available via whatever expressions, table keys and fields, and variables that reference it.
Variables are global or local (including parameters). If a name of a variable is not previously declared as local, it is global. So, executing this code:
function Lib()
function foo(x, y) return x+y end
function goo(x, y) return x-y end
return self
end
Sets the global variable Lib to the function value created by evaluating the function definition. That's all up to that point.
Then, executing:
Lib()
Uses the value of the global variable Lib, assumes it's a function and calls it with no parameters. That executes the function, which evaluates a function definition to obtain a function value and sets it to the global variable foo; similarly for goo; and returns the value of the global variable self (presumably nil). The return value is discarded because the call doesn't do anything with it.
Then, executing:
print(foo(3, 2))
Uses the value of the global variable foo, assumes it's a function and calls it with two parameters. That executes the function, which returns 5. It then uses the value of the global variable print, assumes it's a function and calls it with the value 5. The return value is discarded because the call doesn't do anything with it.
Other answers are leading you to what you might want to do. You can evaluate what they are suggesting using these principles.
function Lib()
local function foo(x, y) return x+y end
local function goo(x, y) return x-y end
interface = {}
interface.foo = foo
interface.goo = goo
return interface
end
So:
l = Lib()
print(l.foo(3, 2))
will print 5
Is that what you need? There is no direct access to the foo and goo functions.
The next idea this leads to is to not expose, say, the goo function via interface, but just use it within foo or some other function. In that case, goo would be an implementation detail (a private function), not exposed via the object interface.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With