Login  Register
 



Post new topicReply to topic
 
Author Message
 PostPosted: 03 May, 2007 
 

Joined: 01 Apr, 2007
Posts: 4744
Offline
I've seen some confusion about the way commas work in Lua. If you're one of the people who can't figure out why commas belong where they do, read on.

First: There are no endline markers in lua.

Commas are not the equivalent of semicolons in C++. They are simply the way to designate separate list or table items. For example:

Code:
ATable = {
    Item1 = 0,
    Item2 = 1,
    Item3 = 2,
}


The items within the table are set apart by commas. The table does not end in a comma because it is not part of anything. Note that the last item in a list or table also ends in a comma. Now, if you had something like this:

Code:
ATable = {
    Item1 = 0,
    InnerTable = {
          Item2 = 1,
          Item3 = 2,
    },
}


InnerTable ends in a comma because it is a table inside another table. Blueprint files are just large sets of nested Lua tables. This is why the different subsections of a blueprint end in a comma after the closing brace, but not after the final blueprint closing brace.

This brings us to classes. There really is no such thing as a "class" in Lua. Behind the hood, classes are just fancy tables. Functions work the same as variables in Lua. This is why you are able to change function definitions of classes on the fly (you are just editing a variable). For example:

Code:
function AFunction()
    --do stuff
end

AClass = class() {
    AClassFunction = function()
        --do stuff
    end,
}


The end for AFunction does not have a comma. The syntax for defining AClassFunction is different because it's really assigning a variable to AClass. Since AClass is a table, the end for AClassFunction has a comma.

I hope this clears up some confusion :).

_________________
Image


Top
 Profile  
 PostPosted: 03 May, 2007 
 
User avatar

Joined: 15 Feb, 2007
Posts: 749
Location: Wisconsin, USA
Offline
From a programmer's perspective, a lot of this helps, however I'm still trying to get my mind around what certain parts of the syntax are doing.

Like you say AClass = class() {---stuff---}
Ok... what's the point of saying class()
what does that do? How is that different from just saying
AClass = {---stuff---}

Also, you mentioned that its assigning a variable to AClass.
What variable?
You said AClass is a table, so you can assign variables to tables? How does that work? So instead of AClass being a table, now its a variable? Or is that not the right paradigm?

When I program, I'm used to this syntax:

function MyFunction(parameter1,parameter2)
--do stuff
return result
end function

then, in another place I have code which is in another function, but it can call MyFunction, like this
GetResult = MyFunction(X,Y)
--do stuff with GetResult -- which is a variable..

Tables like what Lua has would be represented with something like a collection, which I understand. A table is just a series of indexed pieces of information you can access from inside a function.

But when I look at lua code, I'm having a really hard time drawing the parallels to what I'm familiar with.
I think I understand the part where you declare AFunction.
But when you say AClassFunction = function() I start to lose track of what's going on.

_________________
We are Supremilated.
www.supremilated.com


Top
 Profile  
 PostPosted: 03 May, 2007 
 

Joined: 27 Feb, 2007
Posts: 1645
Offline
Quote:
What variable?

Well, Lua can store functions and tables in variables. It's helpful if you want to hook a function without destroying the original function, because you load the old function into a variable, overwrite it with your code, then call the original function from its variable. I think that answers your question.


Top
 Profile  
 PostPosted: 03 May, 2007 
 
Forum Engineer
Forum Engineer

Joined: 01 Mar, 2007
Posts: 549
Location: Guelph, ON
Offline
(this post has been through hell to reach the forum. After Opera crashed, I was able to salvage it from the depths of memory using gdb. This is why I love Linux.)

Preamble: almost everything here is covered in 2.5.6 Table Constructors and most of the rest in 2.5.7 Function Calls.
Also, some clarification concerning commas:
(1) The final comma is optional.
This is mentioned in a single sentence in the Manual: "The field list may have an optional trailing separator, as a convenience for machine-generated code." You're allowed to have a comma after the last entry (and this is a good idea, as it makes it easier to insert new entries later), but it's not strictly mandatory.
Code:
-- this is legal
table1 = {
    foo = bar,
    baz = quux,
    zarf = moby,
-- this is too
table2 = {
    foo = bar,
    baz = quux,
    zarf = moby
}

(2) Commas and semicolons are interchangeable in table declarations
This is mentioned in the grammar for table declarations:
Quote:
tableconstructor ::= `{' [fieldlist] `}
fieldlist ::= field {fieldsep field} [fieldsep]
field ::= `[' exp `]' exp | Name `=' exp | exp
fieldsep ::= `,' | `;'

Re-using the above example, we can see:
Code:
-- this is legal
table1 = {
    foo = bar,
    baz = quux,
    zarf = moby,
-- this is too
table2 = {
    foo = bar;
    baz = quux;
    zarf = moby;
}

You can also freely mix commas and semicolons in a single table, although you really shouldn't, just for readability reasons.
Personally, I prefer semicolons, but the SupComm coding standard appears to be to use commas.
Recon wrote:
From a programmer's perspective, a lot of this helps, however I'm still trying to get my mind around what certain parts of the syntax are doing.
Like you say AClass = class() {---stuff---}
Ok... what's the point of saying class()
what does that do? How is that different from just saying
AClass = {---stuff---}

This is mentioned in passing in the Manual, but kind of warrants more detail here.
Functions can be called not only as func(args), but also as func{ args }, in which case the function is passed the table in question as its
single argument. Example:
Code:
print( { foo = bar } ) -- call print with a single table as its argument
print { foo = bar } -- same as the above!

What's actually happening in the code you asked about is somewhat cleverer. Class() returns a function; that function is then immediately called with the { class definition }, and returns the class object itself. That is to say:
Code:
AClass = Class(superclass) { member = value }
-- Class() returns a function, so we now have
AClass = classmaker { member = value }
-- which is a short form for
AClass = classmaker( { member = value } )
-- classmaker returns the actual class, so
AClass = classobject

The classmaker function (which in practice doesn't get a name, but let's call it classmaker for the purposes of this explanation) does extra stuff like setting up the metatable. If you just did AClass = { ...stuff... } all you get is a plain table without any of the extra shinies that give you, for example, inheritance.
Quote:
Also, you mentioned that its assigning a variable to AClass.
What variable?

He phrased that poorly, I think. It's creating a field in AClass (called "AClassFunction"), and assigning a value to it (the function itself).
Quote:
You said AClass is a table, so you can assign variables to tables? How does that work? So instead of AClass being a table, now its a variable? Or is that not the right paradigm?

You can't assign things to values, only to variables. Variables are just names, containers which hold values. (the reality is somewhat more awesome than this, but I figure environment/table equivalence can wait until you have a firmer grasp on the language)

Quote:
When I program, I'm used to this syntax:
Code:
function MyFunction(parameter1,parameter2)
    --do stuff
    return result
end function

then, in another place I have code which is in another function, but it can call MyFunction, like this
Code:
GetResult = MyFunction(X,Y)
--do stuff with GetResult -- which is a variable..

The above is perfectly valid in Lua.
Quote:
Tables like what Lua has would be represented with something like a collection, which I understand. A table is just a series of inde
xed pieces of information you can access from inside a function.

I am unfamiliar with 'collections'. It most closely resembles an untyped hash table - any value of any type (except nil, anyways) can be use
d as a key, and each key has an associated value (which can also be of any type).
Then it has some additional stuff tacked on (table.key and table:key()) to make it easier to use them as records and as objects. But those a
re just different ways of expressing the same action: looking up a value using its key.
Quote:
But when I look at lua code, I'm having a really hard time drawing the parallels to what I'm familiar with.
I think I understand the part where you declare AFunction.
But when you say AClassFunction = function() I start to lose track of what's going on.

If you aren't familiar with lambda (anonymous) functions, and don't realize that foo{} is a function call in Lua, this can be kind of confusing. Hopefully my explanations above clarified this some; the chapter on function declarations will also go into more detail on what function() means.

Also, in case my frequent mentions of it weren't overt enough, I cannot emphasize enough that the Manual is the best resource for this. It explains the entire language from top to bottom and is short enough (if you skip chapter 3, which is almost completely irrelevant to SupComm modding anyways) that you can read the entire thing in an afternoon. SupComm has added some extensions, like # for comments, but the manual is still your one stop shop for the lexis, syntax and semantics of the language.

_________________
The Lua 5.0 Manual
TA-style naval wreckage
Full tech tree in campaign missions


Top
 Profile  
 PostPosted: 03 May, 2007 
 

Joined: 22 Feb, 2007
Posts: 978
Location: Gas Powered Games Office, Redmond, WA
Offline
ToxicFrog rocks for taking the time to write these great posts. But really, people need to RTFM :)

Please read Programming in Lua if you're not familiar with lua and want to write mods for SupCom. I should make this a forum rule :/


Top
 Profile  
 PostPosted: 03 May, 2007 
 
User avatar

Joined: 15 Feb, 2007
Posts: 1404
Offline
One thing I will say is that it can take some time to get used to Lua if you've primarily worked in languages like C++. Concepts like closures, anonymous functions, functions as first class objects, tail recursion and dynamic types are very powerful and expressive but can take a while to get used to. But once you do, boy do you miss them when you have to go back :)

_________________
==}O->

"Primary function completed."


Top
 Profile  
 PostPosted: 04 May, 2007 
 
User avatar

Joined: 15 Feb, 2007
Posts: 599
Location: Rockingham, Australia
Offline
I'm actually very glad I've switched from VB.NET to C# a while ago - I'm not sure if it's just the syntax or what, but it seems to have made it a lot easier for me to pick up Lua.

And yeah, thanks a LOT ToxicFrog for being so willing to help us out :)

_________________
We are Supremilated
www.supremilated.com


Top
 Profile  
Display posts from previous:  Sort by  
Post new topic Reply to topic



Quick Tools

Search for:
Jump to:  

© 2002-2010 Gas Powered Games Corp. All Rights Reserved. Gas Powered Games is the exclusive trademark of Gas Powered Games Corp.
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
 
Home| Games | Company | News & Press | Support
  Terms of Use   |    Copyright Information   |    Privacy Policy