Difference between "end" and "end)"? - lua

A while ago I had stumbled upon script tutorials where end was used. But then, a few pages later, I've found an end) instead of just end. So I was troubled by this, what is the closing bracket meant to do?

There is no end) syntax. There is end and ), both with their own meanings. end closes a block (initiated with if, for, do, while or function) and ) closes something that started with (, an expression in parentheses, parameter list etc. You have to use end where a block was started, and use ) where something was started with (.
Since the only way a block can appear in an expression is via a function, both those parts of syntax can appear together, if a function is a part of a complex expression or an argument list. However, it's nothing special really, something like end} or end] can appear the same way.
local func = function() print("hello") end
string.dump(func)
This is the same as:
string.dump(function() print("hello") end)
end is a part of the function syntax (function expression), and ) is a part of the ( syntax (function call here).
The first line in the first piece of code can be also written like this:
local func = (function() print("hello") end)
Here, ) just closes the first parenthesis, and the expression is identical to the original one.

I assume you're talking about ROBLOX's modded version of Lua, if so then
end) would end :connect, for example.
workspace.part.Touched:connect(function(part)
--stuff
end)
If not then refer to llidanS4's answer.

Related

Why do I use 'end)' instead of just end |?

draw.RoundedBox(0,0,0,100,100,Color(120,255,120))
end)
I'm watching tutorials for learning Lua, more specifically Lua for the Garry's Mod engine. During the tutorial, I noticed using just 'end' didn't work. I had to use 'end)' with a ')'.
Why do I have to place a ')' at the end of end in this code?
Some functions take other functions as parameters.
When you see a function called like this:
hello(param, function(a) print(a) end)
(Sorry, poor example. This function doesn't really do anything) The function on the inside is called internally from the source of the hello function.
The end is the end of the inside function, and the ) is the end of the parameter list for the first function.
So here we have a function hook.Add() being called:
hook.Add("HUDPaint", "DrawMyHud", function()
draw.RoundedBox(0,0,0,100,100,Color(120,255,120))
end)
and from the GMOD wiki:
hook.Add( string eventName, any identifier, function func )
--Add a hook to be called upon the given event occurring.
Although we're calling a function, what the function is doing is creating a special connection in the code called a hook. On the event "HUDPaint", the GMOD client will call the function provided.
Another way to write this function that might make the meaning of end) more clear is by making each parameter it's own line:
hook.Add(
"HUDPaint",
"DrawMyHud",
function() draw.RoundedBox(0,0,0,100,100,Color(120,255,120)) end --end of function declaration
) --end of hook.Add function call

Adding labels to my programming language

Actually I am writting a programming language in Lua. It was quite fun. I've wrote a bit of standard library (stack op and simple io). Then I've thought about labels. It would look like in assembly. While and for loop aren't funny in any bit so programming in that language can be quite challenging. Here are some requirements for this system:
Label stack (or array, dictionary) must be accessible from global context.
Jump instruction handler will be in separate file.
This is how my label-handling function look like:
function handleLabel(name,currentLine)
end
I have no idea how to implement this kind of magic. First I've thought about that:
LabelLineIDS = {}
Labels = {}
Labelamount = 1;
function handleLabel(name,currentLine)
LabelLineIDS[Labelamount]=currentline
Labels[Labelamount]=name
Labelamount=Labelamount+1
end
-- In file "jump.lua":
local function has_value (tab, val)
for index, value in ipairs(tab) do
if value == val then
return index
end
end
print ("Error: Label not defined.") -- Bail out.
os.exit(1)
end
local function _onlabel()
local labelName = globalparams --Globalparams variable contain parameters to each function, at the moment
--this will contain label name. It _can_ be nil.
return LabelLineIDS[has_value(Labels, labelName)]
end
CurrLine = _onlabel() --Currline - current line that get's parsed.
--1 command per one line.
But I'm unsure is this well written or even work. Can you give me idea how to parse labels in my programming language (and write jump functions)? Or if my code is pretty ok at the moment, can you help me to improve it?
Using line counter in my parser I've decided to implement gotos like we can see in BASIC. Thanks everyone for help.

Control flow in Lua

I have a problem which i suppose must be very common and most of you would have faced it.
I have written a program in lua, say main.lua which on receiving key event should modify the coordinates and display the geometry figure.
This lua code calls reg.c, where it kind of registers.
Now in reg.c i have a function engine which receives the key pressed and passes it to the lua function responsible for key handling.
But by the time key event comes, lua code is done with the registration and exits, thus the call from engine() becomes illegal memory access leading to segmentation fault.
Also i suppose we can't have lua call hanging in reg function, and call engine function from somewhere else.
Then what should be the solution, please guide me through this.
#jacob: here is the prototype of what i am trying to achieve:
function key_handler() //this function will get the latest key pressed from some other function
{
draw.image();
draw.geometry();
...
...
while(1)
{
//draw Points until some condition goes wrong
}
}
Now, once entered into key_handler, while he is busy drawing the points unless and until the failing condition occurs, i am unable to receive key pressed till that time.
I hope this explanation is much simpler and have made my point, and will help others to understand the problem.
I am really sorry, but i am not good at expressing or making others understand.
One more thing, i ahve followed the C syntax to explain, however this is completely implemented in lua
Your code snippet is still largely non-informative (ideally one should be able to just run your code in a stock Lua interpreter and see your problem). If you're describing a Lua problem, use Lua code to describe it.
However I'm beginning to see where you want to go.
The thing you need to could do is have a coroutine that's called in your key handler, which passes an argument back to your handler:
function isContinue() --just to simulate whatever function you use getting keypresses.
-- in whatever framework you're using there will probably be a function key_pressed or the like.
print('Initialize checking function')
while true do
print('Continue looping?')
local ans = io.read():match('[yY]')
local action
if not ans then
print('Do what instead?')
action = io.read()
if action:match('kill') then -- abort keychecker.
break
end
end
coroutine.yield(ans,action)
end
print('finalizing isContinue')
return nil,'STOP' -- important to tell key_handler to quit too, else it'll be calling a dead coroutine.
end
function key_handler()
local coro = coroutine.create(isContinue)
local stat,cont,action
while true do
print'Draw point'
stat,cont,action = coroutine.resume(coro)
if not stat then
print('Coroutine errored:',cont)
elseif not cont then
print('isContinue interrupted keyhandler')
print("We'll "..action.." instead.")
break
end
end
print('finalizing key_handler')
end
key_handler()
-- type something containing y or Y to continue, all else aborts.
-- when aborting, you get asked what to do instead of continuing,
--- with "kill" being a special case.
This should be self explanatory. You should probably take a good look at Programming in Lua, chapter 9: Coroutines.
The big difficulty (well, if you're not accustomed to collaborative threading) is that a coroutine should yield itself: it's not the calling function that's in charge of returning control.
Hope this helps you.

How to set name for function which is in the table

For example, I have a table
table.insert( t, 1, function()
print ("rock");
end );
Is there any way to get function name from this table. I know that I can store name like a key, but what if I want to keep numeric index and also I want to know function name?
Is there any way to do it?
Thanks, on advance.
Say you have this code:
t = {}
x = 5
table.insert(t, 1, x)
t would then be {[1] = 5}. "5" is just a number - it has no name, and isn't associated with the variable "x"; it's a value.
In Lua, functions are treated exactly the same way, as values:
t = {}
x = function() print("test! :D") end
table.insert(t, 1, x)
The value of x is not associated with x in any way, shape, or form. If you want to manually name a function, you can do it by wrapping the function in a table, for example:
t = {}
x = function() print("test! :D") end
table.insert(t, 1, {
name = "MyFunctionName",
func = x
})
That is how you would do it!
...unless..
..you break the rules!
When Lua was developed, the developers realised that the anonymous nature of functions would make productive error messages difficult to produce, if not impossible.
The best thing you'd see would be:
stdin: some error!
stdin: in function 'unknown'
stdin: in function 'unknown'
So, they made it so that when Lua code was parsed, it would record some debug information, to make life easier. To access this information from Lua itself, the debug library is provided.
Be very careful with functions in this library.
You should exert care when using this library. The functions provided here should be used exclusively for debugging and similar tasks, such as profiling. Please resist the temptation to use them as a usual programming tool: they can be very slow. Moreover, several of these functions violate some assumptions about Lua code (e.g., that variables local to a function cannot be accessed from outside or that userdata metatables cannot be changed by Lua code) and therefore can compromise otherwise secure code.
To achieve your desired effect, you must use the debug.getinfo function; an example:
x = function()
print("test!")
print(debug.getinfo(1, "n").name)
end
x() -- prints "test!" followed by "x"
Unfortunately, the form of debug.getinfo that operates directly on a function doesn't fill the name argument (debug.getinfo(x, "n").name == nil) and the version above requires you to run the function.
It seems hopeless!
...unless..
..you really break the rules.
The debug.sethook function allows you to interrupt running Lua code at certain events, and even change things while it's all happening. This, combined with coroutines, allows you to do some interestingly hacky stuff.
Here is an implementation of debug.getfuncname:
function debug.getfuncname(f)
--[[If name found, returns
name source line
If name not found, returns
nil source line
If error, returns
nil nil error
]]
if type(f) == "function" then
local info = debug.getinfo(f, "S")
if not info or not info.what then
return nil, nil, "Invalid function"
elseif info.what == "C" then
-- cannot be called on C functions, as they would execute!
return nil, nil, "C function"
end
--[[Deep magic, look away!]]
local co = coroutine.create(f)
local name, source, linedefined
debug.sethook(co, function(event, line)
local info = debug.getinfo(2, "Sn")
name = info.namewhat ~= "" and info.name or nil
source, linedefined = info.short_src, info.linedefined
coroutine.yield() -- prevent function from executing code
end, "c")
coroutine.resume(co)
return name, source, linedefined
end
return nil, nil, "Not a function"
end
Example usage:
function test()
print("If this prints, stuff went really wrong!")
end
print("Name = ", debug.getfuncname(test))
This function isn't very reliable - it works sometimes, and doesn't others. The debug library is very touchy, so it's to be expected.
Note that you should never use this for actual release code! Only for debugging!
The most extreme case that is still acceptable is logging errors on piece of released software, to help the developer fix issues. No vital code should depend on functions from the debug library.
Good luck!
The function hasn't got any name. If you want you can assign it to a named variable:
theFunction = t[1]
-- Call it:
theFunction()
If what you want is storing a named function to the table, define it beforehand and use its name to store it:
theFunction = function()
print ("rock");
end
table.insert(t, 1, theFunction)
If this is not what you meant, give more details; for example how you would like to access the function. You're question is a bit misty.
The thing is table.insert considers the table as a sequence, only with numeric keys.
If you want to be able to call the function as t.fun() you'll have to use the table as an associative array and hence use a string as key. (BTW any type except nil or NaN are allowed as key)
t={}
t['MyFun']=function print'foo' end
t.myFun() -- uses syntactic sugar for string keys that are valid identifiers.
You might also notice that functions are passed by reference. So all functions are actually anonymous, and are just stored as a value to a certain key or variable.
You can store the names in a separate table.
functions = {}
functionNames = {}
function addFunction(f, name)
table.insert(functions, f)
functionNames[name] = f
end
To get the function, you can use the index. Once you have the function, you can get its name from function_names:
f = functions[3]
name = functionNames[f]
Good luck!

What's with PCALL or is Wowwiki wrong?

This is a WoW (World of Warcraft) lua script question. Not many of these get asked here but I have no where to turn and Stackoverflow is the programmer oasis for answers.
Question:
Wowwiki states that the 2nd, 3rd, 4th arguments are your calling functions 1st, 2nd, 3rd arguments. I don't find this to be true. I find that the 3rd, 4th, 5th arguments end up being the 1st, 2nd, 3rd arguments.
Link: http://www.wowwiki.com/API_pcall
Function:
function myTest(arg1)
return arg1 .. 10;
end
Problem:
local retOK, ret1 = pcall(myTest,"string value");
when I try the sample I get an error of "trying to perform concatenate on local 'arg1' (a nil value)". If I change the code to:
local retOK, ret1 = pcall(myTest,"string value", "bob");
then I get the output of "bob10". Where does the 2nd argument go and what is it for?
More Testing:
function BobsToolbox:RunTest()
local test1, value1 = pcall(BobsToolbox.Test1, "string value");
SharpDeck:Print("Test1: " .. tostring(test1) .. " Value: " .. tostring(value1));
end
function BobsToolbox:Test1(arg1)
return arg1 .. "10";
end
Results: attempt to concatenate local 'arg1' (a nil value)
function BobsToolbox:RunTest()
local test1, value1 = pcall(Test1, "string value");
SharpDeck:Print("Test1: " .. tostring(test1) .. " Value: " .. tostring(value1));
end
function Test1(arg1)
return arg1 .. "10";
end
Results: string value10
I am new to lua and I can't understand why these are different.
New Question:
The following code works but why?
function BobsToolbox:RunTest()
local test1, value1 = pcall(BobsToolbox.Test1, "string value");
SharpDeck:Print("Test1: " .. tostring(test1) .. " Value: " .. tostring(value1));
end
function BobsToolbox.Test1(arg1)
return arg1 .. "10";
end
What's the difference between the following: ("." vs ":")
function BobsToolbox.Test1(arg1)
function BobsToolbox:Test1(arg1)
Lua Documentation:
http://www.lua.org/pil/16.html
This use of a self parameter is a central point in any object-oriented language. Most OO languages have this mechanism partially hidden from the programmer, so that she does not have to declare this parameter (although she still can use the word self or this inside a method). Lua can also hide this parameter, using the colon operator. We can rewrite the previous method definition as
function Account:withdraw (v)
self.balance = self.balance - v
end
and the method call as
a:withdraw(100.00)
The effect of the colon is to add an extra hidden parameter in a method definition and to add an extra argument in a method call. The colon is only a syntactic facility, although a convenient one; there is nothing really new here. We can define a function with the dot syntax and call it with the colon syntax, or vice-versa, as long as we handle the extra parameter correctly:
Account = { balance=0,
withdraw = function (self, v)
self.balance = self.balance - v
end
}
function Account:deposit (v)
self.balance = self.balance + v
end
Account.deposit(Account, 200.00)
Account:withdraw(100.00)
Possible Conclusion:
With this in mind I assume that when calling a ":" function using "pcall" you must supply the "self" argument.
Related: There are nice live code editors for WoW. I used to use LuaSlinger, but turns out that's no longer developed and the developer recommends Hack instead.
However, what you might be encountering here is that the colon method-call syntax is just syntax sugar, ditto for method definitions, IIRC. Basically, if you do foo:bar("quux!"), where foo is an object, you are in reality just doing foo.bar(foo, "quux!").
Hope that helps!
Well, I don't think WoWWiki is wrong. Here is the code I am using:
function myTest(arg1) return arg1 .. 10; end
local retOK, ret1 = pcall(myTest,"string value");
DEFAULT_CHAT_FRAME:AddMessage(ret1);
local retOK, ret1 = pcall(myTest,"string value", "bob");
DEFAULT_CHAT_FRAME:AddMessage(ret1);
Here is the output I get in my General chat box:
string value10
string value10
How are you trying your sample code? I just pasted my code into an existing mod lua file and made sure that mod was enabled in the addons window before selecting my character and logging in. I made a few changes to the source lua file and typed:
/console reloadui
To try the new changes and have the results output to my screen. I don't have much advice to offer you, because I haven't done much work with WoW addons. Have you tried this code in a blank addon to make sure nothing else is interfering? Have you actually tried the code in game? If you can provide any more information or want me to try anything else, let me know!
Update: Decided to try a few more tests. Here are the tests (with the same function):
local retOK, ret1 = pcall(myTest,"");
DEFAULT_CHAT_FRAME:AddMessage(ret1);
local retOK, ret1 = pcall(myTest, nil, "bob");
DEFAULT_CHAT_FRAME:AddMessage(ret1);
And the results:
10
attempt to concatenate local 'arg1' (a nil value)
It's interesting that the error I see when arg1 is nil is slightly different than the error you see. I'd be interested in knowing how you are testing your code. Or maybe you didn't copy the error down verbatim? I guess you could also try clearing out your WTF folder and disabling the rest of your addons to test this function. If it makes a difference, then you can enable them one a time until you find the problem.

Resources