Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call a function in a function in Lua

Tags:

lua

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.

like image 859
Zack Lee Avatar asked Apr 02 '26 05:04

Zack Lee


2 Answers

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.

like image 117
Tom Blodget Avatar answered Apr 04 '26 00:04

Tom Blodget


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.

like image 33
brianolive Avatar answered Apr 03 '26 23:04

brianolive